MASM32编程调用 API函数RtlIpv6AddressToString,Windows 10 容易,Windows 7 折腾
一、需求分析
最近用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 STRUCTucLocalAddr 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 STRUCTdwNumEntries 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 conflictAssembly 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, :DWORDlpfnRtlIpv6AddressToString TYPEDEF ptr _RtlIpv6AddressToString;ssssssssssssssssssssssssssssssssssssssssssssssssssss
.data
;ssssssssssssssssssssssssssssssssssssssssssssssssssssg_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 !=NULLinvoke GetProcAddress, eax, OFFSET g_szRtlIpv6AddressToString.if eax!=NULLmov 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 Addedmov esi, pTable invoke g_lpfnRtlIpv6AddressToString, addr (MIB_TCP6ROW_OWNER_MODULE ptr [esi]).ucLocalAddr, offset g_szBuf128a.elsemov 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 != NULLmov esi, pTable invoke g_lpfnRtlIpv6AddressToString, addr (MIB_TCP6ROW_OWNER_MODULE ptr [esi]).ucRemoteAddr, offset g_szBuf128b.elsemov byte ptr g_szBuf128b, 0.endif
六、参考资料
RtlIpv6AddressToString
七、其它问题
RtlIpv6AddressToString函数支持的最低客户端是 Windows Vista,支持的最低服务器 Windows Server 2008,在Windows XP上用不了。