第3章进程

2026/4/29 8:44:32

MIB_UDPEXROWtable[ANY_SIZE];

}MIB_UDPEXTABLE,*PMIB_UDPEXTABLE; //函数声明:

typedefDWORD(WINAPI*PALLOCATE_AND_GET_TCPEXTABLE_FROM_STACK)( PMIB_TCPEXTABLE*pTcpTable, BOOLbOrder, HANDLEheap, DWORDzero, DWORDflags );

typedefDWORD(WINAPI*PALLOCATE_AND_GET_UDPEXTABLE_FROM_STACK)( PMIB_UDPEXTABLE*pUdpTable, BOOLbOrder,HANDLEheap, DWORDzero, DWORDflags );

//定义函数事例入口指针,初始化为NULL

staticPALLOCATE_AND_GET_TCPEXTABLE_FROM_STACK pAllocateAndGetTcpExTableFromStack=NULL;

staticPALLOCATE_AND_GET_UDPEXTABLE_FROM_STACK pAllocateAndGetUdpExTableFromStack=NULL;

staticcharTcpState[][32]={\\

\\

//辅助函数

PCHARGetPort(unsignedintport,char*pPort) {

sprintf(pPort,\returnpPort; }

PCHARGetIp(unsignedintipaddr,char*pIP) {

unsignedintnipaddr; nipaddr=htonl(ipaddr);

sprintf(pIP,\(nipaddr>>16)&0xFF,(nipaddr>>8)&0xFF, (nipaddr)&0xFF); returnpIP; }

//加载API函数 BOOLLoadAPI() {

pAllocateAndGetTcpExTableFromStack=(PALLOCATE_AND_GET_TCPEXTABLE_

FROM_STACK)GetProcAddress(LoadLibrary(\, \if(!pAllocateAndGetTcpExTableFromStack) returnFALSE;

pAllocateAndGetUdpExTableFromStack=

(PALLOCATE_AND_GET_UDPEXTABLE_FROM_STACK) GetProcAddress(LoadLibrary(\, \if(!pAllocateAndGetUdpExTableFromStack) returnFALSE; }

intmain(intargc,char*argv[]) {

intnRetCode; DWORDi;

WSADATAWSAData; HANDLEhProcessSnap;

PMIB_TCPEXTABLETCPExTable; PMIB_UDPEXTABLEUDPExTable; charszProcessName[MAX_PATH];

charszLocalName[HOSTNAMELEN],szRemoteName[HOSTNAMELEN]; charszRemotePort[PORTNAMELEN],szLocalPort[PORTNAMELEN]; charszLocalAddress[ADDRESSLEN],szRemoteAddress[ADDRESSLEN]; nRetCode=LoadAPI(); if(nRetCode==FALSE) {

printf(\return0; }

if(WSAStartup(MAKEWORD(1,1),&WSAData)) {

printf(\return0; }

nRetCode=pAllocateAndGetTcpExTableFromStack(&TCPExTable,TRUE, GetProcessHeap(),2,2); if(nRetCode) {

printf(\return0; }

nRetCode=pAllocateAndGetUdpExTableFromStack(&UDPExTable,TRUE, GetProcessHeap(),2,2); if(nRetCode)

{

printf(\return-1; }

//GetTCPList

printf(\Address\

for(i=0;idwNumEntries;i++) {

sprintf(szLocalAddress,\,

GetIp(TCPExTable->table[i].dwLocalAddr,szLocalName), GetPort(TCPExTable->table[i].dwLocalPort,szLocalPort) );

sprintf(szRemoteAddress,\

GetIp(TCPExTable->table[i].dwRemoteAddr,szRemoteName), GetPort(TCPExTable->table[i].dwRemotePort,szRemotePort) );

printf(\szLocalAddress,szRemoteAddress,

TcpState[TCPExTable->table[i].dwState],

GetProcessNameFromPID(TCPExTable->table[i].dwProcessId), TCPExTable->table[i].dwProcessId ); }

//GetUDPList

for(i=0;idwNumEntries;i++) {

sprintf(szLocalAddress,\

GetIp(UDPExTable->table[i].dwLocalAddr,szLocalName), GetPort(UDPExTable->table[i].dwLocalPort,szLocalPort) );

sprintf(szRemoteAddress,\printf(\szLocalAddress,szRemoteAddress,

GetProcessNameFromPID(TCPExTable->table[i].dwProcessId), TCPExTable->table[i].dwProcessId ); }

WSACleanup(); return0; }

注意:

这段代码不能在WindowsNT/2000上运行,这是因为这两个版本的

IPHelpAPI.DLL文件没有输出上面的两个函数,采用动态加载得到的函数指针为

NULL。也许用户会想当然地说我把这个文件从XP复制到2000不就得了?值得注意 的是WindowsXP下的IPHelpAPI.DLL文件支持IPv6,这个潜在支持是借助于

NTDLL.DLL文件实现的。而Windows2000下的这个文件没有输出该库需要的IPv6 输出函数。

也许用户会问Fport是怎么实现的,可以这么说,这个程序调用了未公开的系统 接口。

还有另外一种方法是这样实现的:我们知道当一个程序创建一个socket,并开始

侦听的时候,它确定会创建一个进程句柄和打开端口的句柄。注意socket和文件句柄、 进程句柄一样也是一种系统对象。通过使用特殊的参数调用NtDeviceIoControlFile函 数,就会知道如何得知端口是哪一个进程句柄打开的。尽管系统中存在着大量的开放 句柄,但是这里只关心\\Device\\Tcp和\\Device\\Udp。

当我们对iphlpapi.dll反汇编的时候会发现,上面这些函数实际上是调用

NtDeviceIoControlFile实现的,这个函数会把系统中得到的所有开放端口列表发送到 一个特别的缓冲区中。

由于socket和窗口句柄、文件句柄、进程句柄等句柄一样都是系统对象,都被统 一保存在一个系统的内核结构定义里面,分别具有不同的句柄类型,因此可以通过调 用NtQuerySystemInformation函数遍历给定类型的所有句柄信息。这里我们只关心 OBJECT_TYPE_SOCKET类型和进程标识不为空的情况。对于得到每一个套接字句

柄,我们可以通过把它转化成套接字,然后调用getsockname和getsockopt函数反向 得到其端口协议和地址信息。对于状态信息,可以借助于调用上面的GetUdpTable和 GetTcpTable实现。

值得注意的是,上面得到的套接字(socket)句柄都属于其他的进程。根据NT内核

进程保护的原则,一个进程是不能直接得到其他进程的各种信息的,特别是句柄。因 为所谓的句柄只是一个相对于当前进程虚拟地址空间的地址偏移量,它只对当前进程 有效。不同进程中的同一句柄(数值相同)指向的是不同的内容,甚至是无效的,根本 就不是同样的东西。因此,必须进行进程的上下文切换,把其他进程句柄切换为当前 进程句柄,以便获得该进程的信息。切换工作只要调用DuplicateHandle函数就可以。 其实现思路是:

(1)得到当前进程的句柄,打开当前进程的令牌环,提升到调试权限。 (2)动态加载ntdll.dll的NtQuerySystemInformation函数获得系统信息。

(3)从得到的句柄列表中,查询ObjType类型为OBJECT_TYPE_SOCKET和进程 标识不为NULL的情况。

(4)打开遍历中的每一个进程句柄,调用DuplicateHandle函数实现进程上下文切换。 (5)当切换到套接字所在的进程后,调用getsockname和getsockopt函数得到映射 信息。

例3-8实现WindowsNT/2000下端口进程关联。 DWORDdwNumBytesRet=0;

iRet=(*NtQuerySystemInformation)(NT_HANDLE_LIST, pdwHandleList,dwNumBytes, &dwNumBytesRet); DWORDdwNumEntries; PHANDLEINFOpHandleInfo; if(iRet) {


第3章进程.doc 将本文的Word文档下载到电脑
搜索更多关于: 第3章进程 的文档
相关推荐
相关阅读
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 10

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219