[创建时间: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. -bash: mysql: command not found 解决办法 (转)

    root@DB-02 ~]# mysql -u root-bash: mysql: command not found 原因:这是由于系统默认会查找/usr/bin下的命令,如果这个命令不在这个目录下 ...

  2. 初学Pexpect

    概述 Pexpect 是 Don Libes 的 Expect 语言的一个 Python 实现,是一个用来启动子程序,并使用正则表达式对程序输出做出特定响应,以此实现与其自动交互的 Python 模块 ...

  3. .NET基础拾遗(7)多线程开发基础4

    一.多线程编程中的线程同步 1.C#中的lock关键字 lock关键字可能是我们在遇到线程同步的需求时最常用的方式,但lock只是一个语法糖,为什么这么说呢,下面慢慢道来. (1)lock的等效代码其 ...

  4. js动态加载html,加载后的页面元素某些事件失效的解决方案

    用 live 来绑定 例如: $("#items li .addToCartimg").live("click",function(){ $('.popDeta ...

  5. 使用angularjs中ng-repeat的$even与$odd属性时的注意事项

    JavaScript中数组的索引是从0开始的,因此我们再取奇偶的时候需要用!$even和!$odd来将$even和$odd的布尔值反转 下面给出一个实例: 使用$odd和$even来制作一个红蓝相间的 ...

  6. Word隐藏回车符技巧

    每一次在Word中敲击回车时,都会留下一个回车符,回车次数多了回车符也就跟着变多了,这的确是太影响视觉效果了,我们要如何操作才能将这些回车符去掉呢?特意为大家献上Word2003和Word2007中隐 ...

  7. Ajax动态刷新验证码图片

    一> 原理: 把用代码生成的图片存放到硬盘当中,然后在返回存储路径把图片通过图片标签的 src 属性 自动加载到浏览器中 二> 步骤 1. 首先用GDI+ 绘图 把验证码图片给绘制出来 2 ...

  8. C语言初学 计算表达式的值 switch的意义

    #include<stdio.h> main() { int a; printf("请输入一个数字\n"); scanf("%d",&a); ...

  9. python登陆教务管理系统

    想试着模拟登陆一些网站,这次先拿学校的教务管理系统练练手,写一下登陆的流程. 1.我们登陆的url:http://222.195.8.201,但我们所填的密码不是提交到这个页面上去,检查一下页面代码 ...

  10. jquery easyui根据需求二次开发记录

    1.tree需要显示多个图标 实际需求:设备树上节点需搁三个图片,分别标识运行状态.告警状态.设备类型 解决方法:给tree的iconCls传入一个数组,分别是各状态下的class(css),然后要改 ...