就这段代码了,执行后ProcessSOCKETBuf里有开端口进程的pID和端口信息。
ps:这个和QQ有冲突,不知道QQ用了什么东西,一旦枚举端口就重启。其他程序一切正常。
可能需要uses ShellAPI, WinSock ,PsAPI, TLHelp32;
type
ProcessSocket_Info = record
pID:Cardinal; //记录进程ID
A_SocketInfo:String;
end;
const
szSockType : Array[0..5] of string[4] =('NUL','TCP','UDP','RAW','RDM','SEQ');
var
ProcessSOCKETCount:Short;
ProcessSOCKETBuf:array of ProcessSocket_Info; //存储Socket信息用
// GetPortInfo 将SOCKET端口与程序对应起来
procedure GetPortInfo;
var
iRet,namelen,sockType,optlen: integer;
wsaData: Winsock.WSADATA; //打开并初始化WinSock 用
hProc,hMyHandle : THANDLE; //hProc := OpenProcess | hMyHandle用于DuplicateHandle的返回
//这往下是调用 NtQuerySystemInformation 用的
hNtdll : HMODULE;
NtQuerySystemInformation : TNTQUERYSYSTEMINFORMATION;
i,dwNumBytes,dwNumBytesRet,dwNumEntries : Cardinal;
pdwHandleList
DWORD;
pHInfo: PHANDLEINFO;
//以下两个是获取Socket信息时用的
name,remote : sockaddr_in;
s : TSOCKET;
begin
WSAStartup(MAKEWORD(1,1), wsaData );//WinSock初始化
hNtdll := LoadLibrary( 'ntdll.dll' );
NtQuerySystemInformation := TNTQUERYSYSTEMINFORMATION(GetProcAddress(hNtdll,'NtQuerySystemInformation'));
if not Assigned(NtQuerySystemInformation) then
begin
Showmessage('ntdll.dll版本不对!');
Exit;
end;
dwNumBytes := MAX_HANDLE_LIST_BUF;
GetMem(pdwHandleList,dwNumBytes);
dwNumBytesRet := 0;
NtQuerySystemInformation(NT_HANDLE_LIST,pdwHandleList,dwNumBytes,@dwNumBytesRet);
dwNumEntries := pdwHandleList^;
pHInfo := PHANDLEINFO((DWORD(pdwHandleList) + sizeof(pdwHandleList)));
ProcessSOCKETCount:=0; //将Socket记数清零
for i := 0 to dwNumEntries -1 do
begin
if (phInfo^.ObjType=$1C) then
begin
//根据 ProcessID 打开相应的进程
hProc := OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, true,phInfo.dwPid );
//获取Socket句柄
DuplicateHandle(hProc,THANDLE(phInfo^.HndlOffset),GetCurrentProcess,@hMyHandle,STANDARD_RIGHTS_REQUIRED,true,0 );
CloseHandle( hProc );
//开始获取IP和Port
ZeroMemory(@name,sizeof(name));
name.sin_family := AF_INET;
namelen := sizeof(sockaddr_in);
s := TSOCKET(hMyHandle);
//获得SOCKET的本地名
iRet := getsockname(s,name,namelen );
if iRet <> SOCKET_ERROR then
begin
//获取目标IP和Port
ZeroMemory(@remote,sizeof(remote));
remote.sin_family := AF_INET;
Getpeername(s,remote,namelen);
//取端口类型
sockType := 0; optlen := 4;
getsockopt(s,SOL_SOCKET,SO_TYPE,@sockType,optlen);//取得端口类型
inc(ProcessSOCKETCount); //找到一个Socket就加一
setlength(ProcessSOCKETbuf,ProcessSOCKETCount);
ProcessSOCKETbuf[ProcessSOCKETCount-1].pID:=phInfo^.dwPid;
ProcessSOCKETbuf[ProcessSOCKETCount-1].A_SocketInfo:=
format('%s:%-6d %s:%-6d',
[inet_ntoa(name.sin_addr),name.sin_port,
inet_ntoa(remote.sin_addr),remote.sin_port]);
end;
if s<>0 then closesocket(s);
end; //end -for
pHInfo := PHANDLEINFO(DWORD(phInfo)+sizeOf(HANDLEINFO));
end;
if Assigned(pdwHandleList) then freeMem( pdwHandleList );
if hMyHandle <> 0 then CloseHandle(hMyHandle);
freeLibrary(hNtdll);
WSACleanup;
end;