Delphi下获取进程连接端口
[转] Windows操作系统提供了一个iphlpapi.dll文件,全称IP帮助API,通过这个函数库可以获取和修改电脑的网络配置、获取网络状态信息、管理网络活动,利用这个文件中两个未公开的函数AllocateAndGetTcpExTableFromStack和AllocateAndGetUdpExTableFromStack可以获得一个TCP连接表和一个UDP连接表,这两个连接表中包含了正在使用当前连接的进程ID号。 有的资料称只有Windows XP及以上操作系统才提供了这些扩展IP帮助函数,但是在我的系统(Windows2000+SP4)中程序可以正常运行,我系统中的iphlpapi.dll文件版本号为5.0.2195.7097,程序使用Delphi7.0编写,对于不同的系统这个程序不知是否可以正常运行。 网上查到的很多例子都是VC++的,在VC++中调用这两个函数需要动态的从DLL文件中载入,因为对应的iphlpapi.lib文件中没有对这两个函数进行声明,但是在Delphi下没必要这么复杂,Delphi下调用DLL文件中的函数不需要对应的LIB文件,只要对函数进行声明再进行调用就可以了。这两个函数的声明如下: //获取TCP连接表的IP帮助函数声明 function AllocateAndGetTcpExTableFromStack( var pTcpTable; bOrder : Bool; heap : THandle; zero : DWORD; flags : DWORD ): DWORD; stdcall; external 'iphlpapi.dll' name 'AllocateAndGetTcpExTableFromStack'; //获取UDP连接表的IP帮助函数声明 function AllocateAndGetUdpExTableFromStack( var pUdpTable; bOrder : Bool; heap : THandle; zero : DWORD; flags : DWORD ): DWORD; stdcall; external 'iphlpapi.dll' name 'AllocateAndGetUdpExTableFromStack'; 在调用函数前还要自己定义几个结构,及enum函数TCP连接表和UDP连接表,代码如下: //相关数据结构的定义 const ANY_SIZE=256; type MIB_TCPEXROW = record dwState : DWORD; //连接状态 dwLocalAddr : DWORD; //本地地址 dwLocalPort : DWORD; //本地端口 dwRemoteAddr : DWORD; //远程地址 dwRemotePort : DWORD; //远程端口 dwProcessId : DWORD; //进程ID号 end; MIB_TCPEXTABLE = record dwNumEntries : DWORD; //端口数量 table : array [0..ANY_SIZE-1] of MIB_TCPEXROW; end; PMIB_TCPEXTABLE = ^MIB_TCPEXTABLE; MIB_UDPEXROW = record dwLocalAddr : DWORD; //本地地址 dwLocalPort : DWORD; //本地端口 dwProcessId : DWORD; //进程ID号 end; MIB_UDPEXTABLE = record dwNumEntries : DWORD; //端口数量 table : array [0..ANY_SIZE-1] of MIB_UDPEXROW; end; PMIB_UDPEXTABLE = ^MIB_UDPEXTABLE; 这两个函数的调用代码如下: AllocateAndGetTcpExTableFromStack(pTcpTab,true,GetProcessHeap(),2,2); //获取TCP连接表 AllocateAndGetUdpExTableFromStack(pUdpTab,true,GetProcessHeap(),2,2); //获取UDP连接表 仅有进程ID号是不够的,还要获得进程对应可执行文件名,这个可以使用CreateToolhelp32Snapshot函数获得系统进程快照,利用Process32First函数和Process32Next函数从中查出对应的进程,在Delphi中调用这几个函数要引用TlHelp32.pas单元,相关代码如下: //根据进程ID查可执行文件名 function IdToExeFile(hSnapshot : THandle; dwProcessId : DWORD): String; var lppe : TProcessEntry32; b : BOOL; begin lppe.dwSize:=SizeOf(lppe); //取第1个进程数据 b:=Process32First(hSnapshot,lppe); result:=''; while b do begin if lppe.th32ProcessID=dwProcessId then begin result:=lppe.szExeFile; break; end; //取下一个进程 b:=Process32Next(hSnapshot,lppe); end; end; 利用上面这个方法只能获得单一的可执行文件名,而无法获得可执行文件的路径,最好是获得可执行文件完整的路径,以判断可执行文件到底位于哪个文件夹,利用EnumProcessModules函数返回一个进程中的句柄,再调用GetModuleFileNameEx函数就可以获得可执行文件完整的路径,在Delphi下调用这两个函数要引用PsAPI.pas单元,相关代码如下: //根据进程ID查可执行文件路径 function IdToExeDir(dwProcessId : DWORD): String; var cbNeeded : DWORD; hProcess : THandle; hModules : HMODULE; lpFilename : array [0..1024-1] of Char; begin result:=''; hProcess:=OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,false,dwProcessId); if hProcess=0 then exit; EnumProcessModules(hProcess,@hModules,sizeof(hModule),cbNeeded); GetModuleFileNameEx(hProcess,hModules,lpFilename,1024); result:=lpFilename; CloseHandle(hProcess); end; 获得了可执行文件完整的路径最好还要获得文件版本的相关信息,这样才能更好的判断文件是系统文件、应用程序文件、还是木马。获得文件版本信息可以调用GetFileVersionInfo函数和VerQueryValue函数,以下代码只提取文件版本信息中的文件说明和公司名称,用以对可执行文件的判断,相关代码如下: //根据文件名查文件信息 function ExeDirToFileInfo(Filename : String): String; var NameLen,BufLen,ValLen : DWORD; pBuf,pVal : Pointer; LangCode : String; begin result:=''; NameLen:=Length(Filename); if NameLen=0 then exit; //获取版本信息 BufLen:=GetFileVersionInfoSize(PChar(Filename),NameLen); pBuf:=AllocMem(BufLen); if pBuf=nil then exit; if GetFileVersionInfo(PChar(Filename),0,BufLen,pBuf)=false then begin FreeMem(pBuf); exit; end; //获取代码页信息 if VerQueryValue(pBuf,'\VarFileInfo\Translation',pVal,ValLen)=false then begin FreeMem(pBuf); exit; end; LangCode:=Format('%.2x%.2x%.2x%.2x',[ BYTE(PChar(pVal)[1]), BYTE(PChar(pVal)[0]), BYTE(PChar(pVal)[3]), BYTE(PChar(pVal)[2])]); //获取文件说明 if VerQueryValue(pBuf,PChar('\StringFileInfo\'+LangCode+'\FileDescription'),pVal,ValLen)=false then begin FreeMem(pBuf); exit; end; result:=PChar(pVal); //获取公司名称 if VerQueryValue(pBuf,PChar('\StringFileInfo\'+LangCode+'\CompanyName'),pVal,ValLen)=false then begin FreeMem(pBuf); exit; end; result:=result+' / '+PChar(pVal); FreeMem(pBuf); end; 最后做出来的程序如图所示: 这个程序可以获取当前系统中的网络活动,可以看到有哪些TCP和UDP连接,是哪些进程在进行这些活动,还可以看到进程ID、可执行文件名、文件路径、文件说明、公司名称。单击“保存”按纽可以将当前连接表的信息保存到文件中,完整的源代码可以参考项目文件。 项目下载:点击下载 |
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论