一、需求分析
最近用MASM32编程更新SysInfo,增加对IPv6连接信息的收集功能,其中涉及到 MIB_TCP6ROW_OWNER_MODULE 结构体:
;typedef struct _MIB_TCP6ROW_OWNER_MODULE { ; UCHAR ucLocalAddr[16]; ; DWORD dwLocalScopeId; ; DWORD dwLocalPort; ; UCHAR ucRemoteAddr[16]; ; DWORD dwRemoteScopeId; ; DWORD dwRemotePort; ; DWORD dwState; ; DWORD dwOwningPid; ; LARGE_INTEGER liCreateTimestamp; ; ULONGLONG OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE]; ;} MIB_TCP6ROW_OWNER_MODULE, *PMIB_TCP6ROW_OWNER_MODULE; MIB_TCP6ROW_OWNER_MODULE STRUCT ucLocalAddr UCHAR 16 dup (?) dwLocalScopeId DWORD ? dwLocalPort DWORD ? ucRemoteAddr UCHAR 16 dup (?) dwRemoteScopeId DWORD ? dwRemotePort DWORD ? dwState DWORD ? dwOwningPid DWORD ? liCreateTimestamp LARGE_INTEGER <> OwningModuleInfo ULONGLONG TCPIP_OWNING_MODULE_SIZE dup(?) MIB_TCP6ROW_OWNER_MODULE ENDS PMIB_TCP6ROW_OWNER_MODULE typedef ptr MIB_TCP6ROW_OWNER_MODULE ;typedef struct _MIB_TCP6TABLE_OWNER_MODULE { ; DWORD dwNumEntries; ; MIB_TCP6ROW_OWNER_MODULE table[ANY_SIZE]; ;} MIB_TCP6TABLE_OWNER_MODULE, *PMIB_TCP6TABLE_OWNER_MODULE; MIB_TCP6TABLE_OWNER_MODULE STRUCT dwNumEntries DWORD ? table MIB_TCP6ROW_OWNER_MODULE ANY_SIZE dup(<?>) MIB_TCP6TABLE_OWNER_MODULE ENDS PMIB_TCP6TABLE_OWNER_MODULE typedef ptr MIB_TCP6TABLE_OWNER_MODULE
其中的成员
ucLocalAddr UCHAR 16 dup (?) ucRemoteAddr UCHAR 16 dup (?)
其值是IPv6格式的IP地址,需要转换成字符串。微软官网上提到可以使用API函数RtlIpv6AddressToString()来完成这个转换:
RtlIpv6AddressToString is a convenience function that does not require that the Windows Sockets DLL be loaded to access a function provided in Windows Sockets to perform IP address to string conversion.
即
RtlIpv6AddressToString 是一个方便的函数,它不需要加载 Windows 套接字 DLL 来访问 Windows 套接字中提供的函数来执行 IP 地址到字符串的转换。
用grep命令搜索了MASM32安装文件夹中includes文件夹中的.inc文件,发现有以下.inc文件包含了RtlIpv6AddressToString函数的声明:
\masm32\include\dnslib.inc
\masm32\include\ntdll.inc
\masm32\include\ntoskrnl.inc
\masm32\include\wdmsec.inc
二、代码在Windows 10上汇编连接运行正常
编写了调用代码:
include \masm32\include\ntoskrnl.inc ;RtlIpv6AddressToStringA includelib \masm32\lib\ntoskrnl.lib .code ; Get Local Addr ip mov esi, pTable invoke RtlIpv6AddressToString, addr (MIB_TCP6ROW_OWNER_MODULE ptr [esi]).ucLocalAddr, offset g_szBuf128a
代码在使用Windows 10的电脑上汇编、连接、运行正常:
三、代码在Windows 7 上汇编连接成功,运行出错
但是把生成的EXE程序复制到使用Windows 7的电脑上运行,就出错:
把程序源代码复制到使用Windows 7的电脑上,汇编连接都行,但是运行时仍然出现上面的故障。
四、换文件头测试
那就换个头文件来试试:
(一)dnslib
include \masm32\include\dnslib.inc
includelib \masm32\lib\dnslib.lib
在windows 10 和 windows 7上可以顺利完成汇编、连接,但运行时均提示:
二)wdmsec
include \masm32\include\wdmsec.inc
includelib \masm32\lib\wdmsec.lib
在windows 10 和 windows 7上汇编时出错:
***********
ASCII build
***********
----------------------------------------
WARNING Duplicate include file winextra.inc
----------------------------------------
\masm32\include\wdnsec.inc(1511) : error A2111: conflicting parameter definition
\masm32\include\wdnsec.inc(1511) : error A2112: PROC and prototype calling corventions conflict
\masm32\include\wdmsec.inc(1513) : error A2111: conflicting parameter definition
\masm32\include\wdmsec.inc(1513) : error A2112: PROC and prototype callig conventions conflict
\masm32\include\wdmsec.inc(1516) : error A2111: conflicting parameter definition
\Masm32\include\wdmsec.inc(1516) : error A2112: PROC and prototype callig conventions conflict
Assembly Error
请按任意键继续. . .
三)ntdll
include \masm32\include\ntdll.inc ;RtlIpv6AddressToStringA
includelib \masm32\lib\ntdll.lib
在windows 10 和 windows 7上可以顺利完成汇编、连接和运行。
在Windows 7中,对网络连接关连进程信息获取和显示得要比Windows 10中完善。
五、跳过头文件,自己GetModuleHandle 和 GetProcAddress 后调用
微软网站也提到:
An application could also use the GetModuleHandle and GetProcAddress functions to retrieve the function pointer from the Ntdll.dll and call this function.
即
应用程序还可以使用 GetModuleHandle 和 GetProcAddress 函数从 Ntdll 检索函数指针.dll并调用此函数。
相关的代码的代码如下:
;ssssssssssssssssssssssssssssssssssssssssssssssssssss ;proto ;ssssssssssssssssssssssssssssssssssssssssssssssssssss _RtlIpv6AddressToString TYPEDEF proto :DWORD, :DWORD lpfnRtlIpv6AddressToString TYPEDEF ptr _RtlIpv6AddressToString ;ssssssssssssssssssssssssssssssssssssssssssssssssssss .data ;ssssssssssssssssssssssssssssssssssssssssssssssssssss g_szNtDll db "Ntdll.dll", 0 ;20230828 Added g_szRtlIpv6AddressToString db "RtlIpv6AddressToStringA", 0 ;20230828 Added g_lpfnRtlIpv6AddressToString lpfnRtlIpv6AddressToString NULL ;20230828 Added ;ssssssssssssssssssssssssssssssssssssssssssssssssssss .code ;ssssssssssssssssssssssssssssssssssssssssssssssssssss ;……其它代码 invoke GetModuleHandle, offset g_szNtDll .if eax !=NULL invoke GetProcAddress, eax, OFFSET g_szRtlIpv6AddressToString .if eax!=NULL mov g_lpfnRtlIpv6AddressToString, eax .endif .endif ;……其它代码 ; Get Local Addr ip ;mov esi, pTable ;invoke RtlIpv6AddressToString, addr (MIB_TCP6ROW_OWNER_MODULE ptr [esi]).ucLocalAddr, offset g_szBuf128a .if g_lpfnRtlIpv6AddressToString != NULL ;20230828 Added mov esi, pTable invoke g_lpfnRtlIpv6AddressToString, addr (MIB_TCP6ROW_OWNER_MODULE ptr [esi]).ucLocalAddr, offset g_szBuf128a .else mov byte ptr g_szBuf128a, 0 .endif ;……其它代码 ; Get remote Addr IP ;mov esi, pTable ;invoke RtlIpv6AddressToString, addr (MIB_TCP6ROW_OWNER_MODULE ptr [esi]).ucLocalAddr, offset g_szBuf128b .if g_lpfnRtlIpv6AddressToString != NULL mov esi, pTable invoke g_lpfnRtlIpv6AddressToString, addr (MIB_TCP6ROW_OWNER_MODULE ptr [esi]).ucRemoteAddr, offset g_szBuf128b .else mov byte ptr g_szBuf128b, 0 .endif
六、参考资料
RtlIpv6AddressToString
七、其它问题
RtlIpv6AddressToString函数支持的最低客户端是 Windows Vista,支持的最低服务器 Windows Server 2008,在Windows XP上用不了。