木马编程DIY第10篇之网络进程监视

进程管理程序大家都不陌生,通过CreateToolhelp32Snapshot/Process32First/Process32Next系列函数或者PSAPI库不难探出
其中的信息,但对进程是否有网络操作,监听的端口,远程地址,远程端口却力不从心了。然而这种监视对于分析某些恶意软
又十分必要,所以我们的目标就是打操,具有网络监视功能的最终梦幻版本。实现效果如图1所示。


实现方法


NETSTAT -A -N 这条命令可以打印出本地的TCP和UDP连接信息,在06年的杂志上古开元在《解析网络执法官》系列文章中实现
了NETSTAT的功能,方法是使用GetTcpTable和GetUdpTable两个函数得到信息列表,但它却无法实现连接信息与进程的对照,
所以我们还要找其它方法。不能用你还说,给你一顿暴K,当然我也没是没事找刺激,因为在它的基础上MS提供了住处另外的
函数可以达到我们的目得。他们是AllocateAndGetTcpExTableFromStack和AllocateAndGetUdpExTableFromStack,与
GetTcpTable和GetUdpTable相比,扩展函数包含了正在使用当前连接进程的ID号,有了进程ID我们就可以做事了。



版本要求

在开始之前还有些事情要做,请确认一下自己操作系统的版本,因为扩展函数是在WINDOWS XP 和更高版本中所提供的
IP帮助函数,而在WINDOWS2000中是无法使用的。不过如果你的WIN2000上安装了VS2003或VS20005那么就可以使用了(包括编写和运行)。
此扩展函数的原形定义在Iphipapi.h文件中,在使用时,必须链接到Iphlpapi.lib库。





函数原型和结构

因为函数所需的结构是没有公开的,使用时要自己定义。我们从函数本身开始介绍
AllocateAndGetTcpExTableFromStack和AllocateAndGetUdpExTableFromStack函数在使用时要用iphlpapi.dll中
动态获取扩展函数的入口地址,其示例代码如下:
复制内容到剪贴板
代码:
        HMODULE hModule = ::LoadLibrary("iphlpapi.dll");
        //获取TCP列表
        pAllocateAndGetTcpExTableFromStack =
                        (PFNAllocateAndGetTcpExTableFromStack)::GetProcAddress(hModule,
                                                                        "AllocateAndGetTcpExTableFromStack");
        //获取UDP列表
        pAllocateAndGetUdpExTableFromStack =
                        (PFNAllocateAndGetUdpExTableFromStack)::GetProcAddress(hModule,
                                                                        "AllocateAndGetUdpExTableFromStack");
        其中pAllocateAndGetTcpExTableFromStack 和pAllocateAndGetUdpExTableFromStack 是扩展函数指针如下
       
        PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;
        PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;
        而PFNAllocateAndGetTcpExTableFromStack和PFNAllocateAndGetUdpExTableFromStack则是
        由我们自己定义扩展函数原型代码如下:
       
        typedef DWORD (WINAPI *PFNAllocateAndGetTcpExTableFromStack)(
          PMIB_TCPEXTABLE *pTcpTable,
          BOOL bOrder,            
          HANDLE heap,
          DWORD zero,
          DWORD flags
        );

        typedef DWORD (WINAPI *PFNAllocateAndGetUdpExTableFromStack)(
          PMIB_UDPEXTABLE *pUdpTable,  
          BOOL bOrder,              
          HANDLE heap,
          DWORD zero,
          DWORD flags
        );
在成功得到函数入口后就可以获取TCP/UDP进程和网络信息列表了其代码如下
复制内容到剪贴板
代码:
        PMIB_TCPEXTABLE pTcpExTable;
        PMIB_UDPEXTABLE pUdpExTable;

        if(pAllocateAndGetTcpExTableFromStack(&pTcpExTable, TRUE, GetProcessHeap(), 2, 2) != 0)
        {
                        MessageBox(" TCP列表失败/n");
        }
        if(pAllocateAndGetUdpExTableFromStack(&pUdpExTable, TRUE, GetProcessHeap(), 2, 2) != 0)
        {
                        MessageBox(" UPD列表失败/n");
        }
其中        PMIB_TCPEXTABLE和PMIB_UDPEXTABLE是自己定义的结构,用来接受列表信息,它们的原形如下
复制内容到剪贴板
代码:
        typedef struct
        {
          DWORD   dwState;                // 连接状态
          DWORD   dwLocalAddr;            // 本地地址
          DWORD   dwLocalPort;            // 本地端口
          DWORD   dwRemoteAddr;           // 远程地址
          DWORD   dwRemotePort;           // 远程端口
          DWORD          dwProcessId;                // 进程ID号
        } MIB_TCPEXROW, *PMIB_TCPEXROW;

        typedef struct
        {
                DWORD                        dwNumEntries;
                MIB_TCPEXROW        table[ANY_SIZE];
        } MIB_TCPEXTABLE, *PMIB_TCPEXTABLE;

        typedef struct
        {
          DWORD   dwLocalAddr;            // 本地地址
          DWORD   dwLocalPort;            // 本地端口
          DWORD          dwProcessId;                // 进程ID号
        } MIB_UDPEXROW, *PMIB_UDPEXROW;

        typedef struct
        {
                DWORD                        dwNumEntries;
                MIB_UDPEXROW        table[ANY_SIZE];
        } MIB_UDPEXTABLE, *PMIB_UDPEXTABLE;
上面的结构信息的说明十分详细,也是程序的核心,这样子我们就可以得进程的ID和其它信息了,下面我再 讨论其具体实现.



细节实现


跟据上文所返回的结构我们可以从中提取需要的信息,包括本地/远程IP,端口状态,进程名称,进程路径等等

各个信息定义如下
复制内容到剪贴板
代码:
        char        szLocalAddr[128];
        char        szRemoteAddr[128];
        char        szProcessName[128];
        in_addr inadLocal;
        in_addr        inadRemote;
        char    strState[128];
        DWORD   dwRemotePort = 0;       
本地IP地址
复制内容到剪贴板
代码:
        inadLocal.s_addr = pTcpExTable->table[i].dwLocalAddr;
远程端口
复制内容到剪贴板
代码:
        if(strcmp(strState, "LISTEN") != 0)
        {
                dwRemotePort = pTcpExTable->table[i].dwRemotePort;
        }
        else
                dwRemotePort = 0;
远程IP地址
复制内容到剪贴板
代码:
        inadRemote.s_addr = pTcpExTable->table[i].dwRemoteAddr;
格式化地址+端口
复制内容到剪贴板
代码:
        sprintf(szLocalAddr, "%s:%u", inet_ntoa(inadLocal),
                        ntohs((unsigned short)(0x0000FFFF & pTcpExTable->table[i].dwLocalPort)));
        sprintf(szRemoteAddr, "%s:%u", inet_ntoa(inadRemote),
                        ntohs((unsigned short)(0x0000FFFF & dwRemotePort)));
连接状态
复制内容到剪贴板
代码:
        switch (pTcpExTable->table[i].dwState)
        {
        case MIB_TCP_STATE_CLOSED:
                strcpy(strState, "CLOSED");
                break;
        case MIB_TCP_STATE_TIME_WAIT:
                strcpy(strState, "TIME_WAIT");
                break;
        case MIB_TCP_STATE_LAST_ACK:
                strcpy(strState, "LAST_ACK");
                break;
        case MIB_TCP_STATE_CLOSING:
                strcpy(strState, "CLOSING");
                break;
        case MIB_TCP_STATE_CLOSE_WAIT:
                strcpy(strState, "CLOSE_WAIT");
                break;
        case MIB_TCP_STATE_FIN_WAIT1:
                strcpy(strState, "FIN_WAIT1");
                break;
        case MIB_TCP_STATE_ESTAB:
                strcpy(strState, "ESTAB");
                break;
        case MIB_TCP_STATE_SYN_RCVD:
                strcpy(strState, "SYN_RCVD");
                break;
        case MIB_TCP_STATE_SYN_SENT:
                strcpy(strState, "SYN_SENT");
                break;
        case MIB_TCP_STATE_LISTEN:
                strcpy(strState, "LISTEN");
                break;
        case MIB_TCP_STATE_DELETE_TCB:
                strcpy(strState, "DELETE");
                break;
        default:
                printf("Error: unknown state!/n");
                break;
        }
进程名称/路径
复制内容到剪贴板
代码:
        hProcess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,false,pTcpExTable->table[i].dwProcessId);
        EnumProcessModules(hProcess, &hModule, sizeof(hModule), &needed);                        //枚举进程模块
        GetModuleFileNameEx(hProcess, hModule, Path, sizeof(Path));                                //得到进程路径
        GetModuleBaseName  (hProcess, hModule, Name, sizeof(Name));                                //得到进程名称
   

        在上的实现都应该在以下的循环内进行

        for(UINT i = 0; i < pTcpExTable->dwNumEntries; ++i)
        {
                .........//实现代码
        }
UDP的进程信息


与TCP进程相比UDP是无连接的协议,所以它只有本地IP/端口/进程ID三项,比TCP简单很多,实现上也相差无几,在里就不
再详细说明了,详细实现可以看原代码。


这样整个程序就完工了,因为关注重点是对网络进程的监视,所没有添加结束进程,或查看进程模快的部分,不过有兴趣
的话可以自己进行扩展,来打操真正的梦幻版本。本文参考了张越著的《VC网络程序设计》中的实例,如果有问题可以到
客黑防线的论坛或我的BLOG Http://blog.csdn.net/chinafe上讨论不论是鼓励还是暴K我都很高兴......。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值