[创建时间:2016-04-13 22:37:00]

NetAnalyzer下载地址

起因

最近因为NetAnalyzer2016的发布,好多人都提出是否可以在NetAnalyzer中加入一个基于进程的抓包功能。所以最近研究了一下大概有这样一个想法:

获取系统打开端口的所有进程,并获取进程所开启的端口、IP地址以及使用的协议等信息,然后生成对应的过滤表达式,然后给NetAnalyzer设置该过滤表达式,然后开始抓包。

开始

虽然.Net中提供了进程信息查看的相关库,但是却没有提供相关网络端口查询的功能,所以也没有过多深入的研究,就把注意打到了Windows API 的头上。最后经过一番查找与总结,最后找到了两个方法,

在iphlpapi.dll 针对于TCP和UDP分别是

DWORD GetExtendedTcpTable(
_Out_ PVOID pTcpTable,
_Inout_ PDWORD pdwSize,
_In_ BOOL bOrder,
_In_ ULONG ulAf,
_In_ TCP_TABLE_CLASS TableClass,
_In_ ULONG Reserved
);
DWORD GetExtendedUdpTable(
_Out_ PVOID pUdpTable,
_Inout_ PDWORD pdwSize,
_In_ BOOL bOrder,
_In_ ULONG ulAf,
_In_ UDP_TABLE_CLASS TableClass,
_In_ ULONG Reserved
);

找到了对应的接口方法,那么接下来要做的就是对这个接口进行c#封装,因为这两个接口还带一些结构体,此处就不卖关子了,先看图,后面直接把可用的代码贴出来

以下是核心代码

 using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text; namespace ProcessViewer
{
public class NetProcessAPI
{ /// <summary>
/// 获取TCP连接对象
/// </summary>
/// <param name="pTcpTable"></param>
/// <param name="dwOutBufLen"></param>
/// <param name="sort"></param>
/// <param name="ipVersion"></param>
/// <param name="tblClass"></param>
/// <param name="reserved"></param>
/// <returns></returns>
[DllImport("iphlpapi.dll", SetLastError = true)]
private static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwOutBufLen, bool sort, int ipVersion, TCP_TABLE_CLASS tblClass, uint reserved = ); /// <summary>
/// 获取UDP连接对象
/// </summary>
/// <param name="pTcpTable"></param>
/// <param name="dwOutBufLen"></param>
/// <param name="sort"></param>
/// <param name="ipVersion"></param>
/// <param name="tblClass"></param>
/// <param name="reserved"></param>
/// <returns></returns>
[DllImport("iphlpapi.dll", SetLastError = true)]
private static extern uint GetExtendedUdpTable(IntPtr pUdpTable, ref int dwOutBufLen, bool sort, int ipVersion, UDP_TABLE_CLASS tblClass, uint reserved = ); /// <summary>
///获取TCP连接对象
/// </summary>
/// <returns></returns>
public static TcpRow[] GetAllTcpConnections()
{
TcpRow[] tTable;
int AF_INET = ; // IP_v4
int buffSize = ;
uint ret = GetExtendedTcpTable(IntPtr.Zero, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL);
IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
try
{
ret = GetExtendedTcpTable(buffTable, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL);
if (ret != )
{
return null;
}
TcpTable tab = (TcpTable)Marshal.PtrToStructure(buffTable, typeof(TcpTable));
IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries));
tTable = new TcpRow[tab.dwNumEntries]; for (int i = ; i < tab.dwNumEntries; i++)
{
TcpRow tcpRow = (TcpRow)Marshal.PtrToStructure(rowPtr, typeof(TcpRow));
tTable[i] = tcpRow;
rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow)); // next entry
}
}
finally
{
Marshal.FreeHGlobal(buffTable);
}
return tTable;
} /// <summary>
///获取udp连接对象
/// </summary>
/// <returns></returns>
public static UdpRow[] GetAllUdpConnections()
{
UdpRow[] tTable;
int AF_INET = ; // IP_v4
int buffSize = ;
uint ret = GetExtendedUdpTable(IntPtr.Zero, ref buffSize, true, AF_INET, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
try
{
ret = GetExtendedUdpTable(buffTable, ref buffSize, true, AF_INET, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
if (ret != )
{
return null;
}
UdpTable tab = (UdpTable)Marshal.PtrToStructure(buffTable, typeof(UdpTable));
IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries));
tTable = new UdpRow[tab.dwNumEntries]; for (int i = ; i < tab.dwNumEntries; i++)
{
UdpRow udpRow = (UdpRow)Marshal.PtrToStructure(rowPtr, typeof(UdpRow));
tTable[i] = udpRow;
rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(udpRow)); // next entry
}
}
finally
{
Marshal.FreeHGlobal(buffTable);
}
return tTable;
} #region 针对于TCP管理
/** 由于该部分使用到了Linq查询 需要.Net版本较高(当前使用的是.Net2.0),再着该部分代码在现有功能点并不需要, 所以注释了(主要是我懒得改了 ^_^)
/// <summary>
/// 设置
/// </summary>
/// <param name="pRow"></param>
/// <returns></returns>
[DllImport("iphlpapi.dll", SetLastError = true)]
public static extern uint SetTcpEntry(IntPtr pRow);
public static void CloseConnByLocalPort(int port)
{
var tcpRows = GetAllTcpConnections();
var tmpRows = from i in tcpRows
where i.LocalPort == port
select i;
TcpRow[] tcpArry = tmpRows.ToArray();
for (int i = 0; i < tcpArry.Length; i++)
{
tcpArry[i].state = ConnectionState.Delete_TCB;
SetTcpEntry(GetPtrToNewObject(tcpArry[i]));
}
}
public static IntPtr GetPtrToNewObject(object obj)
{
IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, ptr, false);
return ptr;
}
* */
#endregion
} #region TCP返回的数据结构
/// <summary>
/// TCP表类型
/// </summary>
public enum TCP_TABLE_CLASS
{
TCP_TABLE_BASIC_LISTENER,
TCP_TABLE_BASIC_CONNECTIONS,
TCP_TABLE_BASIC_ALL,
TCP_TABLE_OWNER_PID_LISTENER,
TCP_TABLE_OWNER_PID_CONNECTIONS,
TCP_TABLE_OWNER_PID_ALL,
TCP_TABLE_OWNER_MODULE_LISTENER,
TCP_TABLE_OWNER_MODULE_CONNECTIONS,
TCP_TABLE_OWNER_MODULE_ALL
}
/// <summary>
/// TCP当前状态
/// </summary>
public enum ConnectionState : int
{
/// <summary> All </summary>
All = ,
/// <summary> Closed </summary>
Closed = ,
/// <summary> Listen </summary>
Listen = ,
/// <summary> Syn_Sent </summary>
Syn_Sent = ,
/// <summary> Syn_Rcvd </summary>
Syn_Rcvd = ,
/// <summary> Established </summary>
Established = ,
/// <summary> Fin_Wait1 </summary>
Fin_Wait1 = ,
/// <summary> Fin_Wait2 </summary>
Fin_Wait2 = ,
/// <summary> Close_Wait </summary>
Close_Wait = ,
/// <summary> Closing </summary>
Closing = ,
/// <summary> Last_Ack </summary>
Last_Ack = ,
/// <summary> Time_Wait </summary>
Time_Wait = ,
/// <summary> Delete_TCB </summary>
Delete_TCB =
} /// <summary>
/// TCP列结构(行)
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct TcpRow
{
// DWORD is System.UInt32 in C#
public ConnectionState state;
public uint localAddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = )]
public byte[] localPort;
public uint remoteAddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = )]
public byte[] remotePort;
public int owningPid;
public System.Net.IPAddress LocalAddress
{
get
{
return new System.Net.IPAddress(localAddr);
}
}
public ushort LocalPort
{
get
{
return BitConverter.ToUInt16(
new byte[] { localPort[], localPort[] }, );
}
}
public System.Net.IPAddress RemoteAddress
{
get
{
return new System.Net.IPAddress(remoteAddr);
}
}
public ushort RemotePort
{
get
{
return BitConverter.ToUInt16(
new byte[] { remotePort[], remotePort[] }, );
}
}
} /// <summary>
/// TCP表结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct TcpTable
{
public uint dwNumEntries;
TcpRow table;
}
#endregion #region UDP结构 /// <summary>
/// UDP表类型
/// </summary>
public enum UDP_TABLE_CLASS
{
UDP_TABLE_BASIC,
UDP_TABLE_OWNER_PID,
UDP_TABLE_OWNER_MODULE
} /// <summary>
/// TCP列结构(行)
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct UdpRow
{
public uint localAddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = )]
public byte[] localPort;
public int owningPid;
public System.Net.IPAddress LocalAddress
{
get
{
return new System.Net.IPAddress(localAddr);
}
}
public ushort LocalPort
{
get
{
return BitConverter.ToUInt16(
new byte[] { localPort[], localPort[] }, );
}
}
} /// <summary>
/// UDP表结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct UdpTable
{
public uint dwNumEntries;
UdpRow table;
}
#endregion }

分别通过上面的GetAllTcpConnections()方法和GetAllUdpConnections() 可获得TCP和UDP的所有当前在线的进程,

额外给一段通过进程号获取应用图标的代码

 using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text; namespace ProcessViewer
{ /// <summary>
/// 通过API获取进程图标
/// </summary>
public class ProcessAPI
{
[DllImport("Shell32.dll")]
private static extern int SHGetFileInfo
(
string pszPath,
uint dwFileAttributes,
out SHFILEINFO psfi,
uint cbfileInfo,
SHGFI uFlags
); [StructLayout(LayoutKind.Sequential)]
private struct SHFILEINFO
{
public SHFILEINFO(bool b)
{
hIcon = IntPtr.Zero; iIcon = ; dwAttributes = ; szDisplayName = ""; szTypeName = "";
}
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.LPStr, SizeConst = )]
public string szDisplayName;
[MarshalAs(UnmanagedType.LPStr, SizeConst = )]
public string szTypeName;
}; private enum SHGFI
{
SmallIcon = 0x00000001,
LargeIcon = 0x00000000,
Icon = 0x00000100,
DisplayName = 0x00000200,
Typename = 0x00000400,
SysIconIndex = 0x00004000,
UseFileAttributes = 0x00000010
}
//获取进程图标
public static Icon GetIcon(string strPath, bool bSmall)
{
SHFILEINFO info = new SHFILEINFO(true);
int cbFileInfo = Marshal.SizeOf(info);
SHGFI flags;
if (bSmall)
flags = SHGFI.Icon | SHGFI.SmallIcon | SHGFI.UseFileAttributes;
else
flags = SHGFI.Icon | SHGFI.LargeIcon | SHGFI.UseFileAttributes; SHGetFileInfo(strPath, , out info, (uint)cbFileInfo, flags);
return Icon.FromHandle(info.hIcon);
} //获取进程图标
public static Icon GetIcon(int pid, bool bSmall)
{ try
{
var p = System.Diagnostics.Process.GetProcessById(pid); return GetIcon(p.MainModule.FileName, bSmall);
}
catch (Exception ex)
{
return null;
}
} //获取进程名称
public static string GetProcessNameByPID(int processID)
{
//could be an error here if the process die before we can get his name
try
{
Process p = Process.GetProcessById((int)processID);
return p.ProcessName;
}
catch (Exception ex)
{
return "Unknown";
}
}
}
}

我们已经完成了进程信息的获取

那么接下来就是使用了,其实使用起来还是非常容易的

         private void loadProcess()
{
dataGridProcess.Rows.Clear();
//tcp
foreach (var p in NetProcessAPI.GetAllTcpConnections())
{
var icon=ProcessAPI.GetIcon(p.owningPid, true);
dataGridProcess.Rows.Add(new object[] { icon==null?Properties.Resources.app:icon, ProcessAPI.GetProcessNameByPID(p.owningPid), "TCP", p.LocalAddress.ToString(), p.LocalPort.ToString(), p.RemoteAddress.ToString(), p.RemotePort.ToString() });
}
//udp
foreach (var p in NetProcessAPI.GetAllUdpConnections())
{
var icon = ProcessAPI.GetIcon(p.owningPid, true);
dataGridProcess.Rows.Add(new object[] { icon == null ? Properties.Resources.app : icon, ProcessAPI.GetProcessNameByPID(p.owningPid), "UDP", p.LocalAddress.ToString(), p.LocalPort.ToString(), "-", "-" });
}
}

好了就写到这里了

欢迎关注NetAnalyzer公众平台,感谢使用NetAnalyzer2016

示例代码下载:http://files.cnblogs.com/files/twzy/MyTcpView.zip

NetAnalyzer笔记 之 六 用C#打造自己的网络连接进程查看器(为进程抓包做准备)的更多相关文章

  1. GAN实战笔记——第六章渐进式增长生成对抗网络(PGGAN)

    渐进式增长生成对抗网络(PGGAN) 使用 TensorFlow和 TensorFlow Hub( TFHUB)构建渐进式增长生成对抗网络( Progressive GAN, PGGAN或 PROGA ...

  2. Silverlight项目笔记6:Linq求差集、交集&检查网络连接状态&重载构造函数复用窗口

    1.使用Linq求差集.交集 使用场景: 需要从数据中心获得用户数据,并以此为标准,同步系统的用户信息,对系统中多余的用户进行删除操作,缺失的用户进行添加操作,对信息更新了的用户进行编辑操作更新. 所 ...

  3. Kafka技术内幕 读书笔记之(二) 生产者——服务端网络连接

    KafkaServer是Kafka服务端的主类, KafkaServer中和网络层有关的服务组件包括 SocketServer.KafkaApis 和 KafkaRequestHandlerPool后 ...

  4. NetAnalyzer笔记 目录

    目录 NetAnalyzer笔记 之 一 开篇语 NetAnalyzer笔记 之 二 简单的协议分析 NetAnalyzer笔记 之 三 用C++做一个抓包程序 NetAnalyzer笔记 之 四 C ...

  5. NetAnalyzer笔记 之 八 NetAnalyzer2016使用方法(2)

    [创建时间:2016-05-06 22:07:00] NetAnalyzer下载地址 在写本篇的时候,NetAnalyzer 3.1版本已经发布,所以本篇就以最新版本的为例继续使用,并且顺带说明一下, ...

  6. Hadoop阅读笔记(六)——洞悉Hadoop序列化机制Writable

    酒,是个好东西,前提要适量.今天参加了公司的年会,主题就是吃.喝.吹,除了那些天生话唠外,大部分人需要加点酒来作催化剂,让一个平时沉默寡言的码农也能成为一个喷子!在大家推杯换盏之际,难免一些画面浮现脑 ...

  7. opencv学习笔记(六)直方图比较图片相似度

    opencv学习笔记(六)直方图比较图片相似度 opencv提供了API来比较图片的相似程度,使我们很简单的就能对2个图片进行比较,这就是直方图的比较,直方图英文是histogram, 原理就是就是将 ...

  8. python学习笔记(六)文件夹遍历,异常处理

    python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...

  9. NetAnalyzer笔记 之 二. 简单的协议分析

    [创建时间:2015-08-27 22:15:17] NetAnalyzer下载地址 上篇我们回顾完了NetAnalyzer一些可有可无的历史,在本篇,我决定先不对NetAnalyzer做介绍,而是先 ...

随机推荐

  1. [转]Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果

    转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17539199),请尊重他人的辛勤劳动成果,谢谢! 我在上一 ...

  2. Linux(CentOS 5.5) Redis安装

    一,什么是redis redis是一个key-value存储系统. 和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset ...

  3. SQLite中不支持的sql语法

    今天很自然的在写Sql语句的时候用了Top,一开始没发现问题,因为我从数据库读出的值正好是0,而我习惯变量定义的时候也都赋值0,可是到我不要0的时候我就发现问题了.后来才知道,可爱的小sqlite竟然 ...

  4. C#基础语法总结

    C#笔记——基础篇 一.入门知识 VS中的常用快捷键 Ctrl+K+D:快速对齐代码 Ctrl+Z:撤销 Ctrl+S:保存(一定要经常保存!) Ctrl+J:快速弹出智能提示 Shift+End . ...

  5. servlet的含义和作用

    servle(Server Applet):全称Java Servlet,未有中文译文.是用Java编写的服务器端程序.其主要功能在于交互式地浏览和修改数据,生成动态Web内容.狭义的Servlet是 ...

  6. 使用VS Code开发AngularJS 2 第一个应用程序

    使用VS Code开发AngularJS 2 第一个应用程序 目录 运行环境 创建项目 安装依赖包 创建TypeScript应用程序 配置应用程序 运行应用程序 运行环境 运行环境: Windows ...

  7. (转)ip地址,手机ip查询

    页面地址:http://www.ip138.com/ 外链地址(实际主页面里面有)http://www.ip138.com/iplink.htm 外链地址里面的内容: <FORM METHOD= ...

  8. SQL从入门到基础 - 05 数据分组、Having语句

    一.数据分组 1. 按照年龄进行分组统计各个年龄段的人数: Select FAge,count(*) from T_Employee group by FAge; 2. Group by子句必须放到w ...

  9. Unable to find manifest signing certificate in the certificate(Visual studio)

    今天打开之前做的项目,突然得到很奇怪的编译错误: Unable to find manifest signing certificate in the certificate 网上搜一下,有两个方法, ...

  10. scala学习笔记-集合

    变长数组:数组缓冲 Scala中对于那种长度会变的数组的数据结构为ArrayBuffer. import scala.collection.mutable.ArrayBuffer; // 一个空的数组 ...