进程和端口 ( 积分: 100 )

  • 主题发起人 主题发起人 hhjjhhjj
  • 开始时间 开始时间
H

hhjjhhjj

Unregistered / Unconfirmed
GUEST, unregistred user!
怎样通过一个已经开放的网络端口得到开放该端口的进程id?
 
只能反过来,得到某进程使用的端口,然后遍历所有进程,就可以得到全部已开放的端口。
 
netstat -ano可以得到打开端口列表 最后一列就是PID
 
谢谢。大家用过TCPView吧。我就是想要实现那种效果。
我找到一些资料,有点接近了,但出了一个问题:
在刷新列表后,本机上有Socketserver的程序的端口状态会变为Close_Wait,就自动关闭了。
我对Socket编程不是很了解,希望得到帮助。
代码如下。
 
unit Unit1;

interface

uses
windows,Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,Tlhelp32,ShellAPI, PSAPI,winsock, ComCtrls,
ExtCtrls, Buttons;

const
SYSTEMTIMEINFORMATION = 3;
NT_HANDLE_LIST = 16;
OBJECT_TYPE_SOCKET = 28;
MAX_HANDLE_LIST_BUF = $200000;
szSockType : Array[0..5] of string[4] =('NUL','TCP','UDP','RAW','RDM','SEQ');
{定义HanleInfo数据结构}
type
pHandleInfo = ^HandleInfo;
HandleInfo = record
dwPid : SHORT;
CreatorBackTraceIndex : SHORT;
ObjType : BYTE;
HandleAttributes : BYTE;
HndlOffset : SHORT;
dwKeObject : DWORD;
GrantedAccess : ULONG;
end;

PTSystemTimeInfo = ^TSystemTimeInfo;
TSystemTimeInfo = record
liKeBootTime : TLargeInteger;
liKeSystemTime : TLargeInteger;
liExpTimeZoneBias : TLargeInteger;
uCurrentTimeZoneId : ULONG;
dwReserved : DWORD;
end;

TNTQUERYSYSTEMINFORMATION =
function(dwRecordType: DWORD; pdwHandleList: pDWORD;
dwNumBytes: DWORD; pdwNumBytesRet: pDWORD): DWORD; stdcall;
type
TForm1 = class(TForm)
Button1: TButton;
ListView1: TListView;
procedure Button1Click(Sender: TObject);
private

{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{GetProcessPath 根据进程ID得到进程全路径名称}
function GetProcessPath(PID : Integer): String;
var hProcess: THandle;
hMod : hModule;
cbNeeded: DWORD;
szProcessName: array[0..1024] of Char;
begin
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION OR PROCESS_VM_READ,
FALSE, PID );
szProcessName := 'unknown';
if (hProcess<>0) then begin
if(EnumProcessModules(hProcess,@hMod,sizeof(hMod),cbNeeded)) then
begin
GetModuleFileNameEx(hProcess,hMod,szProcessName,sizeof(szProcessName));
Result := StrPas(szProcessName);
end;
end;
CloseHandle(hProcess);
end;

{SetPrivilege 函数用来提升本进程的特权}
function SetPrivilege():BOOL;
const
ADJUST_PRIV = TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES;
PRIV_SIZE = SizeOf(TTokenPrivileges);
var
Len : DWORD;
TokenPriv, Dummy : TTokenPrivileges;
Token : THandle;
begin
Result:=False;
try
if not OpenProcessToken(GetCurrentProcess(), ADJUST_PRIV, Token) then Exit;
if not LookupPrivilegeValue(
nil,
'SeDebugPrivilege',
TokenPriv.Privileges[0].Luid) then exit;
TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
TokenPriv.PrivilegeCount := 1;
if not AdjustTokenPrivileges(Token, False, TokenPriv, PRIV_SIZE,Dummy, Len) then Exit;
Result:=True;
except
end;
end;

{GetPortInfo 将SOCK端口与程序对应起来}
function GetPortInfo: string;
var
iRet: integer;
wsaData: Winsock.WSADATA;
hCurrentProc,hToken : THANDLE;
hNtdll : HMODULE;
NtQuerySystemInformation : TNTQUERYSYSTEMINFORMATION;
dwNumBytes : DWORD;
pdwHandleList :pDWORD;
dwNumBytesRet : DWORD;
dwNumEntries: DWORD;
pHInfo: PHANDLEINFO;
hProc: THANDLE;
i : DWORD;
hMyHandle : THandle;
name,remote : sockaddr_in;
s : TSOCKET;
namelen : integer;
sockType : integer;
optlen : integer;
begin
s := 0;
iRet := WSAStartup(MAKEWORD(1,1), wsaData );
if iRet<>0 then
begin
Result := format('WSAStartup Error:%d', [GetLastError]);
exit;
end;
hCurrentProc := GetCurrentProcess;

if (not OpenProcessToken(hCurrentProc,TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES,hToken)) then
begin
Result := Result + format('OpenProcessToken Error:%d', [GetLastError]);
WsaCleanUp;
exit;
end
else
if (not SetPrivilege()) then
begin
Result := Result + format('SetPrivleges SE_DEBUG_NAME Error:%d', [GetLastError]);
WsaCleanUp;
exit;
end;

if hToken <> 0 then
CloseHandle( hToken );

hNtdll := LoadLibrary( 'ntdll.dll' );
if (hNtdll = 0) then
begin
Result := Result + format('LoadLibrary( NTDLL.DLL ) Error:%d', [GetLastError]);
WSACleanup;
exit;
end;

NtQuerySystemInformation := TNTQUERYSYSTEMINFORMATION(GetProcAddress(hNtdll,
'NtQuerySystemInformation'));

if not Assigned(NtQuerySystemInformation)then
begin
Result := Result + format('GetProcess( NtQuerySystemInformation ) Error:%d', [GetLastError]);
WSACleanup;
exit;
end;

dwNumBytes := MAX_HANDLE_LIST_BUF;
GetMem(pdwHandleList,dwNumBytes);
if not Assigned(pdwHandleList) then
begin
Result := Result + format('Malloc for Handle List Error:%d'#13#10, [GetLastError]);
WSACleanup;
exit;
end;

dwNumBytesRet := 0;
iRet := NtQuerySystemInformation(NT_HANDLE_LIST,pdwHandleList,dwNumBytes,@dwNumBytesRet);
if iRet <> 0 then
begin
Result := Result +
format('NtQuerySystemInformation return %d, Error:%d'#13#10,
[dwNumBytesRet, GetLastError]);
end
else
begin
dwNumEntries := pdwHandleList^;
pHInfo := PHANDLEINFO((DWORD(pdwHandleList) + sizeof(pdwHandleList) ));
for i := 0 to dwNumEntries -1 do
begin
application.ProcessMessages;
//此进程含有SOCKET对象 OK
//if phInfo^.dwPid=432 then form1.Memo2.Lines.Add(inttostr(phInfo^.ObjType));
if ((phInfo^.ObjType = OBJECT_TYPE_SOCKET) and (phInfo^.dwPid <> 0)) then
begin
hProc := OpenProcess(WRITE_DAC,false,phInfo.dwPid );
if hProc <> 0 then
begin
CloseHandle(hProc);
end
else
Result := Result +format('OpenProcess(WRITE_DAC) %d Error:%d'#13#10,
[phInfo^.dwPid,GetLastError]);
hMyHandle := 0;
//根据 ProcessID 打开相应的进程
hProc := OpenProcess(
PROCESS_DUP_HANDLE or
PROCESS_QUERY_INFORMATION or
PROCESS_VM_READ,true, phInfo.dwPid );
if hProc <>0 then
begin
//获取Socket句柄 //源进程句柄 //源SOCKET对象 //本进程句柄 //复制到这里
DuplicateHandle(hProc,THANDLE(phInfo^.HndlOffset),hCurrentProc,
@hMyHandle,STANDARD_RIGHTS_REQUIRED,true, 0);
//0: 使用 DUPLICATE_CLOSE_SOURCE 则关闭源socket
// DUPLICATE_SAME_ACCESS 象源进程一样操作SOCKET
CloseHandle(hProc);
end
else
Result := Result +
format('OpenProcess %d Error:%d'#13#10,[phInfo.dwPid,GetLastError]);
if hMyHandle <> 0 then
begin
ZeroMemory(@name,sizeof(name));
name.sin_family := AF_INET;
namelen := sizeof(sockaddr_in);
s := TSOCKET(hMyHandle);
//获得SOCKET的本地名
iRet := getsockname(s,name,namelen); //s: SOCKET , name:返回 name
ZeroMemory(@remote,sizeof(remote));
remote.sin_family := AF_INET;
getpeername(s,remote,namelen);
//form1.Memo1.Lines.Add(inttostr(hMyHandle)+' '+inttostr(pHInfo^.dwPid)+' '+inttostr(phInfo^.HndlOffset)+' '+inttostr(iRet));
if iRet <> SOCKET_ERROR then
begin
sockType := 0;
optlen := 4;
//取得端口类型
getsockopt(S,SOL_SOCKET,SO_TYPE,@sockType,optlen);
With Unit1.Form1.ListView1.Items.Add Do
Begin
CAption := Format('%d', [pHInfo^.dwPid]);
Subitems.Add(GetProcessPath(pHInfo^.dwPid));
Subitems.Add(Format('%s', [inet_ntoa(name.sin_addr)]));
Subitems.Add(Format('%5d',[ntohs(name.sin_port)]));
Subitems.Add(Format('%s', [inet_ntoa(remote.sin_addr)]));
Subitems.Add(Format('%5d',[ntohs(remote.sin_port)]));
Subitems.Add(Format('%s', [(szSockType[sockType])]));
End;
end;
end;
end;
pHInfo := PHANDLEINFO(DWORD(phInfo) + sizeOf(HANDLEINFO));
if s<>0 then closesocket(s);
end;
end;
if Assigned(pdwHandleList) then
freeMem( pdwHandleList );
if hCurrentProc <> 0 then
CloseHandle( hCurrentProc );
freeLibrary(hNtdll);
WSACleanup;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ListView1.Items.BeginUpdate;
ListView1.Clear;
ListView1.Items.EndUpdate;
GetPortInfo;
end;

end.
 
好代码,收藏!
 
不就跟我说的一样吗.
 
后退
顶部