zoukankan      html  css  js  c++  java
  • NetAnalyzer笔记 之 六 用C#打造自己的网络连接进程查看器(为进程抓包做准备)

    [创建时间: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#封装,因为这两个接口还带一些结构体,此处就不卖关子了,先看图,后面直接把可用的代码贴出来

    以下是核心代码

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Diagnostics;
      4 using System.Runtime.InteropServices;
      5 using System.Text;
      6 
      7 namespace ProcessViewer
      8 {
      9     public class NetProcessAPI
     10     {
     11 
     12         /// <summary>
     13         /// 获取TCP连接对象
     14         /// </summary>
     15         /// <param name="pTcpTable"></param>
     16         /// <param name="dwOutBufLen"></param>
     17         /// <param name="sort"></param>
     18         /// <param name="ipVersion"></param>
     19         /// <param name="tblClass"></param>
     20         /// <param name="reserved"></param>
     21         /// <returns></returns>
     22         [DllImport("iphlpapi.dll", SetLastError = true)]
     23         private static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwOutBufLen, bool sort, int ipVersion, TCP_TABLE_CLASS tblClass, uint reserved = 0);
     24 
     25 
     26         /// <summary>
     27         /// 获取UDP连接对象
     28         /// </summary>
     29         /// <param name="pTcpTable"></param>
     30         /// <param name="dwOutBufLen"></param>
     31         /// <param name="sort"></param>
     32         /// <param name="ipVersion"></param>
     33         /// <param name="tblClass"></param>
     34         /// <param name="reserved"></param>
     35         /// <returns></returns>
     36         [DllImport("iphlpapi.dll", SetLastError = true)]
     37         private static extern uint GetExtendedUdpTable(IntPtr pUdpTable, ref int dwOutBufLen, bool sort, int ipVersion, UDP_TABLE_CLASS tblClass, uint reserved = 0);
     38 
     39 
     40         /// <summary>
     41         ///获取TCP连接对象
     42         /// </summary>
     43         /// <returns></returns>
     44         public static TcpRow[] GetAllTcpConnections()
     45         {
     46             TcpRow[] tTable;
     47             int AF_INET = 2;    // IP_v4
     48             int buffSize = 0;
     49             uint ret = GetExtendedTcpTable(IntPtr.Zero, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL);
     50             IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
     51             try
     52             {
     53                 ret = GetExtendedTcpTable(buffTable, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL);
     54                 if (ret != 0)
     55                 {
     56                     return null;
     57                 }
     58                 TcpTable tab = (TcpTable)Marshal.PtrToStructure(buffTable, typeof(TcpTable));
     59                 IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries));
     60                 tTable = new TcpRow[tab.dwNumEntries];
     61 
     62                 for (int i = 0; i < tab.dwNumEntries; i++)
     63                 {
     64                     TcpRow tcpRow = (TcpRow)Marshal.PtrToStructure(rowPtr, typeof(TcpRow));
     65                     tTable[i] = tcpRow;
     66                     rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow));   // next entry
     67                 }
     68             }
     69             finally
     70             {
     71                 Marshal.FreeHGlobal(buffTable);
     72             }
     73             return tTable;
     74         }
     75 
     76 
     77         /// <summary>
     78         ///获取udp连接对象
     79         /// </summary>
     80         /// <returns></returns>
     81         public static UdpRow[] GetAllUdpConnections()
     82         {
     83             UdpRow[] tTable;
     84             int AF_INET = 2;    // IP_v4
     85             int buffSize = 0;
     86             uint ret = GetExtendedUdpTable(IntPtr.Zero, ref buffSize, true, AF_INET, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
     87             IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
     88             try
     89             {
     90                 ret = GetExtendedUdpTable(buffTable, ref buffSize, true, AF_INET, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
     91                 if (ret != 0)
     92                 {
     93                     return null;
     94                 }
     95                 UdpTable tab = (UdpTable)Marshal.PtrToStructure(buffTable, typeof(UdpTable));
     96                 IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries));
     97                 tTable = new UdpRow[tab.dwNumEntries];
     98 
     99                 for (int i = 0; i < tab.dwNumEntries; i++)
    100                 {
    101                     UdpRow udpRow = (UdpRow)Marshal.PtrToStructure(rowPtr, typeof(UdpRow));
    102                     tTable[i] = udpRow;
    103                     rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(udpRow));   // next entry
    104                 }
    105             }
    106             finally
    107             {
    108                 Marshal.FreeHGlobal(buffTable);
    109             }
    110             return tTable;
    111         }
    112 
    113 
    114 
    115         #region 针对于TCP管理
    116         /**  由于该部分使用到了Linq查询 需要.Net版本较高(当前使用的是.Net2.0),再着该部分代码在现有功能点并不需要, 所以注释了(主要是我懒得改了 ^_^)
    117         /// <summary>
    118         /// 设置
    119         /// </summary>
    120         /// <param name="pRow"></param>
    121         /// <returns></returns>
    122         [DllImport("iphlpapi.dll", SetLastError = true)]
    123         public static extern uint SetTcpEntry(IntPtr pRow);
    124         public static void CloseConnByLocalPort(int port)
    125         {
    126             var tcpRows = GetAllTcpConnections();
    127             var tmpRows = from i in tcpRows
    128                           where i.LocalPort == port
    129                           select i;
    130             TcpRow[] tcpArry = tmpRows.ToArray();
    131             for (int i = 0; i < tcpArry.Length; i++)
    132             {
    133                 tcpArry[i].state = ConnectionState.Delete_TCB;
    134                 SetTcpEntry(GetPtrToNewObject(tcpArry[i]));
    135             }
    136         }
    137         public static IntPtr GetPtrToNewObject(object obj)
    138         {
    139             IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(obj));
    140             Marshal.StructureToPtr(obj, ptr, false);
    141             return ptr;
    142         }
    143          * */
    144         #endregion
    145     }
    146 
    147 
    148 
    149     #region TCP返回的数据结构
    150     /// <summary>
    151     /// TCP表类型
    152     /// </summary>
    153     public enum TCP_TABLE_CLASS
    154     {
    155         TCP_TABLE_BASIC_LISTENER,
    156         TCP_TABLE_BASIC_CONNECTIONS,
    157         TCP_TABLE_BASIC_ALL,
    158         TCP_TABLE_OWNER_PID_LISTENER,
    159         TCP_TABLE_OWNER_PID_CONNECTIONS,
    160         TCP_TABLE_OWNER_PID_ALL,
    161         TCP_TABLE_OWNER_MODULE_LISTENER,
    162         TCP_TABLE_OWNER_MODULE_CONNECTIONS,
    163         TCP_TABLE_OWNER_MODULE_ALL
    164     }
    165     /// <summary> 
    166     /// TCP当前状态
    167     /// </summary> 
    168     public enum ConnectionState : int
    169     {
    170         /// <summary> All </summary> 
    171         All = 0,
    172         /// <summary> Closed </summary> 
    173         Closed = 1,
    174         /// <summary> Listen </summary> 
    175         Listen = 2,
    176         /// <summary> Syn_Sent </summary> 
    177         Syn_Sent = 3,
    178         /// <summary> Syn_Rcvd </summary> 
    179         Syn_Rcvd = 4,
    180         /// <summary> Established </summary> 
    181         Established = 5,
    182         /// <summary> Fin_Wait1 </summary> 
    183         Fin_Wait1 = 6,
    184         /// <summary> Fin_Wait2 </summary> 
    185         Fin_Wait2 = 7,
    186         /// <summary> Close_Wait </summary> 
    187         Close_Wait = 8,
    188         /// <summary> Closing </summary> 
    189         Closing = 9,
    190         /// <summary> Last_Ack </summary> 
    191         Last_Ack = 10,
    192         /// <summary> Time_Wait </summary> 
    193         Time_Wait = 11,
    194         /// <summary> Delete_TCB </summary> 
    195         Delete_TCB = 12
    196     }
    197 
    198 
    199     /// <summary>
    200     /// TCP列结构(行)
    201     /// </summary>
    202     [StructLayout(LayoutKind.Sequential)]
    203     public struct TcpRow
    204     {
    205         // DWORD is System.UInt32 in C#
    206         public ConnectionState state;
    207         public uint localAddr;
    208         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    209         public byte[] localPort;
    210         public uint remoteAddr;
    211         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    212         public byte[] remotePort;
    213         public int owningPid;
    214         public System.Net.IPAddress LocalAddress
    215         {
    216             get
    217             {
    218                 return new System.Net.IPAddress(localAddr);
    219             }
    220         }
    221         public ushort LocalPort
    222         {
    223             get
    224             {
    225                 return BitConverter.ToUInt16(
    226                 new byte[2] { localPort[1], localPort[0] }, 0);
    227             }
    228         }
    229         public System.Net.IPAddress RemoteAddress
    230         {
    231             get
    232             {
    233                 return new System.Net.IPAddress(remoteAddr);
    234             }
    235         }
    236         public ushort RemotePort
    237         {
    238             get
    239             {
    240                 return BitConverter.ToUInt16(
    241                 new byte[2] { remotePort[1], remotePort[0] }, 0);
    242             }
    243         }
    244     }
    245 
    246     /// <summary>
    247     /// TCP表结构
    248     /// </summary>
    249     [StructLayout(LayoutKind.Sequential)]
    250     public struct TcpTable
    251     {
    252         public uint dwNumEntries;
    253         TcpRow table;
    254     }
    255     #endregion
    256 
    257 
    258 
    259 
    260     #region UDP结构
    261 
    262     /// <summary>
    263     /// UDP表类型
    264     /// </summary>
    265     public enum UDP_TABLE_CLASS
    266     {
    267         UDP_TABLE_BASIC,
    268         UDP_TABLE_OWNER_PID,
    269         UDP_TABLE_OWNER_MODULE
    270     }
    271 
    272 
    273 
    274     /// <summary>
    275     /// TCP列结构(行)
    276     /// </summary>
    277     [StructLayout(LayoutKind.Sequential)]
    278     public struct UdpRow
    279     {
    280         public uint localAddr;
    281         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    282         public byte[] localPort;
    283         public int owningPid;
    284         public System.Net.IPAddress LocalAddress
    285         {
    286             get
    287             {
    288                 return new System.Net.IPAddress(localAddr);
    289             }
    290         }
    291         public ushort LocalPort
    292         {
    293             get
    294             {
    295                 return BitConverter.ToUInt16(
    296                 new byte[2] { localPort[1], localPort[0] }, 0);
    297             }
    298         }
    299     }
    300 
    301 
    302     /// <summary>
    303     /// UDP表结构
    304     /// </summary>
    305     [StructLayout(LayoutKind.Sequential)]
    306     public struct UdpTable
    307     {
    308         public uint dwNumEntries;
    309         UdpRow table;
    310     }
    311     #endregion
    312 
    313 
    314 }

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

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

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Diagnostics;
     4 using System.Drawing;
     5 using System.Runtime.InteropServices;
     6 using System.Text;
     7 
     8 namespace ProcessViewer
     9 {
    10 
    11     /// <summary>
    12     /// 通过API获取进程图标
    13     /// </summary>
    14     public class ProcessAPI
    15     {
    16         [DllImport("Shell32.dll")]
    17         private static extern int SHGetFileInfo
    18         (
    19         string pszPath,
    20         uint dwFileAttributes,
    21         out SHFILEINFO psfi,
    22         uint cbfileInfo,
    23         SHGFI uFlags
    24         );
    25 
    26         [StructLayout(LayoutKind.Sequential)]
    27         private struct SHFILEINFO
    28         {
    29             public SHFILEINFO(bool b)
    30             {
    31                 hIcon = IntPtr.Zero; iIcon = 0; dwAttributes = 0; szDisplayName = ""; szTypeName = "";
    32             }
    33             public IntPtr hIcon;
    34             public int iIcon;
    35             public uint dwAttributes;
    36             [MarshalAs(UnmanagedType.LPStr, SizeConst = 260)]
    37             public string szDisplayName;
    38             [MarshalAs(UnmanagedType.LPStr, SizeConst = 80)]
    39             public string szTypeName;
    40         };
    41 
    42         private enum SHGFI
    43         {
    44             SmallIcon = 0x00000001,
    45             LargeIcon = 0x00000000,
    46             Icon = 0x00000100,
    47             DisplayName = 0x00000200,
    48             Typename = 0x00000400,
    49             SysIconIndex = 0x00004000,
    50             UseFileAttributes = 0x00000010
    51         }
    52         //获取进程图标
    53         public static Icon GetIcon(string strPath, bool bSmall)
    54         {
    55             SHFILEINFO info = new SHFILEINFO(true);
    56             int cbFileInfo = Marshal.SizeOf(info);
    57             SHGFI flags;
    58             if (bSmall)
    59                 flags = SHGFI.Icon | SHGFI.SmallIcon | SHGFI.UseFileAttributes;
    60             else
    61                 flags = SHGFI.Icon | SHGFI.LargeIcon | SHGFI.UseFileAttributes;
    62 
    63             SHGetFileInfo(strPath, 256, out info, (uint)cbFileInfo, flags);
    64             return Icon.FromHandle(info.hIcon);
    65         }
    66 
    67 
    68         //获取进程图标
    69         public static Icon GetIcon(int pid, bool bSmall)
    70         {
    71 
    72             try
    73             {
    74                 var p = System.Diagnostics.Process.GetProcessById(pid);
    75 
    76                 return GetIcon(p.MainModule.FileName, bSmall);
    77             }
    78             catch (Exception ex)
    79             {
    80                 return null;
    81             }
    82         }
    83 
    84         //获取进程名称
    85         public static string GetProcessNameByPID(int processID)
    86         {
    87             //could be an error here if the process die before we can get his name
    88             try
    89             {
    90                 Process p = Process.GetProcessById((int)processID);
    91                 return p.ProcessName;
    92             }
    93             catch (Exception ex)
    94             {
    95                 return "Unknown";
    96             }
    97         }
    98     }
    99 }

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

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

     1         private void loadProcess()
     2         {
     3             dataGridProcess.Rows.Clear();
     4             //tcp
     5             foreach (var p in NetProcessAPI.GetAllTcpConnections())
     6             {
     7                 var icon=ProcessAPI.GetIcon(p.owningPid, true);
     8                 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() });
     9             }
    10             //udp
    11             foreach (var p in NetProcessAPI.GetAllUdpConnections())
    12             {
    13                 var icon = ProcessAPI.GetIcon(p.owningPid, true);
    14                 dataGridProcess.Rows.Add(new object[] { icon == null ? Properties.Resources.app : icon, ProcessAPI.GetProcessNameByPID(p.owningPid), "UDP", p.LocalAddress.ToString(), p.LocalPort.ToString(), "-", "-" });
    15             }
    16         }

    好了就写到这里了

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

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

     

  • 相关阅读:
    单选、复选框控制表格行高亮 JQuery
    java内存泄露处理的方法
    spring几种Dao支持配置
    遇见你,是我最美丽的意外
    JavaClassLoader的一些热运用
    CSS Sprites 图片整合技术
    关于前端工程师与其他岗位协作的想法
    JAVA断言使用
    dreamover 模板
    javascriptdom学习笔记
  • 原文地址:https://www.cnblogs.com/twzy/p/5389173.html
Copyright © 2011-2022 走看看