上周改写的TcpStatC,使用了API函数 GetTcpTable,不能显示网络端口关联的进程ID和进程名或进程对应文件说明符。周末抽空改进了一下。

要获取和显示网络端口关联的进程ID和进程名,可以改用API函数GetExtendedTcpTable,获取MIB_TCPROW_OWNER_PID 或 MIB_TCPTABLE_OWNER_MODULE,但是MASM32中没有对这两个结构体进行预定义。需要DIY:

MIB_TCPROW_OWNER_PID 的相关定义如下:

; typedef struct _MIB_TCPROW_OWNER_PID {
; DWORD dwState;
; DWORD dwLocalAddr;
; DWORD dwLocalPort;
; DWORD dwRemoteAddr;
; DWORD dwRemotePort;
; DWORD dwOwningPid;
; } MIB_TCPROW_OWNER_PID, *PMIB_TCPROW_OWNER_PID;

MIB_TCPROW_OWNER_PID struct
dwState DWORD ?
dwLocalAddr DWORD ?
dwLocalPort DWORD ?
dwRemoteAddr DWORD ?
dwRemotePort DWORD ?
dwOwningPid DWORD ? ;进程ID
MIB_TCPROW_OWNER_PID ends
PMIB_TCPROW_OWNER_PID typedef ptr MIB_TCPROW_OWNER_PID


; typedef struct _MIB_TCPTABLE_OWNER_PID {
; DWORD dwNumEntries;
; MIB_TCPROW_OWNER_PID table[ANY_SIZE];
; } MIB_TCPTABLE_OWNER_PID, *PMIB_TCPTABLE_OWNER_PID;
;

MIB_TCPTABLE_OWNER_PID struct
dwNumEntries DWORD ?
table MIB_TCPROW_OWNER_PID ANY_SIZE dup(<?>)
MIB_TCPTABLE_OWNER_PID ends
PMIB_TCPTABLE_OWNER_PID typedef ptr MIB_TCPTABLE_OWNER_PID

MIB_TCPROW_OWNER_PID中的成员dwOwningPid包含了端口对应的进程ID。

MIB_TCPTABLE_OWNER_MODULE 的相关定义如下: 

; typedef struct _MIB_TCPROW_OWNER_MODULE {
; DWORD dwState;
; DWORD dwLocalAddr;
; DWORD dwLocalPort;
; DWORD dwRemoteAddr;
; DWORD dwRemotePort;
; DWORD dwOwningPid;
; LARGE_INTEGER liCreateTimestamp;
; ULONGLONG OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE];
; } MIB_TCPROW_OWNER_MODULE, *PMIB_TCPROW_OWNER_MODULE

MIB_TCPROW_OWNER_MODULE struct
dwState DWORD ?
dwLocalAddr DWORD ?
dwLocalPort DWORD ?
dwRemoteAddr DWORD ?
dwRemotePort DWORD ?
dwOwningPid DWORD ? ;进程ID
liCreateTimestamp LARGE_INTEGER <>
OwningModuleInfo ULONGLONG TCPIP_OWNING_MODULE_SIZE dup(?)
MIB_TCPROW_OWNER_MODULE ends
PMIB_TCPROW_OWNER_MODULE typedef ptr MIB_TCPROW_OWNER_MODULE

; typedef struct _MIB_TCPTABLE_OWNER_MODULE {
; DWORD dwNumEntries;
; MIB_TCPROW_OWNER_MODULE table[ANY_SIZE];
; } MIB_TCPTABLE_OWNER_MODULE, *PMIB_TCPTABLE_OWNER_MODULE

MIB_TCPTABLE_OWNER_MODULE struct
dwNumEntries DWORD ?
table MIB_TCPROW_OWNER_MODULE ANY_SIZE dup(<?>)
MIB_TCPTABLE_OWNER_MODULE ends

PMIB_TCPTABLE_OWNER_MODULE typedef ptr MIB_TCPTABLE_OWNER_MODULE

MIB_TCPROW_OWNER_MODULE 中的成员dwOwningPid包含了端口对应的进程ID。

先试试MIB_TCPROW_OWNER_PID。

invoke GetExtendedTcpTable, g_pTcpTable, addr dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0

取得PID后,通过依次调用API函数 OpenProcess、EnumProcessModules、GetModuleBaseName来获取进程名。

如果要取得进程对应的文件说明符,可以将GetModuleBaseName改为另外一个API函数GetModuleFileNameEx。

我是先尝试GetModuleFileNameEx,如果不成功,再使用GetModuleBaseName。代码如下:

;=================================================
;Function: Get process name with process id
; Input: dwPid: process id
; Output: if eax = 0 then fail
; else eax = the length of the string copied to the buffer
;==================================================
getProcNameById proc dwPid:DWORD
local hMod, hProc: HANDLE
local dwNeeded: DWORD

invoke OpenProcess, PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, dwPid
.if eax!=NULL
mov hProc, eax
invoke GetModuleFileNameEx, hProc, NULL, offset g_szProcFileSpec, sizeof g_szProcFileSpec
.IF eax==0
invoke EnumProcessModules, hProc, addr hMod, sizeof hMod, addr dwNeeded
.if eax!=0
invoke GetModuleBaseName, hProc, hMod, offset g_szProcFileSpec, sizeof g_szProcFileSpec;
.endif
.ENDIF
push eax
invoke CloseHandle, hProc
pop eax
.endif

ret
getProcNameById endp

在Windows 10上运行时,会发现有不少进程不能获取文件说明符,解决的办法是一要以具有管理员权限的帐号来运行程序,二要提升程序的特权,我尝试了获取SeDebugPrivilege,代码如下:

;=================================================
;Function: Let current process get the privilege
; Input: (none)
; Output: eax = 0 Success
; eax = 1 , fail to OpenProcessToken
; eax = 2 , fail to LookupPrivilegeValue
;==================================================
EnableDebugPriv proc
LOCAL hToken: HANDLE
;LOCAL sedebugnameValue: LUID ;An LUID is a 64-bit value
LOCAL sedebugnameValue[2]: DWORD
LOCAL tkp: TOKEN_PRIVILEGES

invoke GetCurrentProcess
mov ebx, eax

invoke OpenProcessToken, ebx, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, addr hToken
.if (eax == 0)
mov eax, 1
ret
.endif

invoke LookupPrivilegeValue, NULL, offset g_szSE_DEBUG_NAME, addr sedebugnameValue
.if (eax == 0)
invoke CloseHandle, hToken
mov eax, 2
ret
.endif

mov tkp.PrivilegeCount, 1
lea eax, tkp.Privileges
m_m2m [eax], sedebugnameValue
m_m2m [eax+4], [sedebugnameValue+1]

mov ( LUID_AND_ATTRIBUTES ptr [eax]).Attributes, SE_PRIVILEGE_ENABLED

invoke AdjustTokenPrivileges, hToken, FALSE, addr tkp, sizeof tkp, NULL, NULL
.if (eax == 0)
invoke CloseHandle, hToken
.endif

xor eax, eax
ret
EnableDebugPriv endp

生成的EXE文件信息如下:

文件说明符 : K:\TcpStatC.exe
属性 : A---
数字签名:否
PE文件:是
获取文件版本信息大小失败!
创建时间 : 2022-8-14 22:13:51
修改时间 : 2022-8-14 22:18:8
大小 : 5120 字节 5.0 KB
MD5 : a17a53ab06707808ba456ba90374a9ee
SHA1: 156A74E1E5BB56D00383E926F9983D8DBE480753
CRC32: 901593e7

下载地址:http://endurer.ys168.com/  tools工具/网络工具 下

程序运行效果如下:

MASM32编写TcpStatC再进阶 显示PID和对应进程说明符_网络

  netstat 命令显示如下:

MASM32编写TcpStatC再进阶 显示PID和对应进程说明符_windows_02

参考:

​枚举所有进程 - Win32 apps | Microsoft Docs​

​GetModuleFileNameExA function (psapi.h) - Win32 apps | Microsoft Docs​

​EnumProcessModules function (psapi.h) - Win32 apps | Microsoft Docs​​ 

​GetModuleBaseNameA function (psapi.h) - Win32 apps | Microsoft Docs​