上周改写的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工具/网络工具 下
程序运行效果如下:

netstat 命令显示如下:

参考:
枚举所有进程 - 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