SysInfo主要是通过WMI来获取系统信息的,但是WMI获取的操作系统信息中没有Windows操作系统是32位还是64位的内容,所以需要另外想办法编程获取,比较常见的方法是调用Windows API函数GetNativeSystemInfo()或IsWow64Process()。之前分别用MASM32和VC分别编写了调用GetNativeSystemInfo()的代码。
今天把32or64.asm中的相关代码移植到SysInfo中来显示,主要是把32or64.asm中的相关代码改为一个函数showOsType(),原来的一些全局变量相应改成函数内部的局部变量,代码如下:
g_szOsType db "系统类型:", 0 g_sz32Bit db "32位",0 g_sz64Bit db "64位",0 g_szGetNativeSystemInfo db "GetNativeSystemInfo", 0 g_szkernel32Dll db "kernel32.dll", 0 g_szFailGetModuleHandle db "GetModuleHandle失败", 0 g_szFailGetProcAddress db "GetProcAddress失败", 0 g_szFailGetNativeSystemInfo db "GetNativeSystemInfo失败", 0 showOsType proc LOCAL lpSI: dword LOCAL lpfnGetNativeSystemInfo: _LPFNGetNativeSystemInfo invoke editCatStr, OFFSET g_szOsType invoke GetModuleHandle, OFFSET g_szkernel32Dll .if eax==NULL push OFFSET g_szFailGetModuleHandle .else invoke GetProcAddress, eax, OFFSET g_szGetNativeSystemInfo .IF eax==NULL push OFFSET g_szFailGetProcAddress ; for call editCatStr() .ELSE mov lpfnGetNativeSystemInfo, eax invoke lpfnGetNativeSystemInfo, ADDR lpSI lea eax, lpSI movzx eax, (_SYSTEM_INFO ptr [eax]).wProcessorArchitecture .if (eax==PROCESSOR_ARCHITECTURE_IA64) || (eax==PROCESSOR_ARCHITECTURE_AMD64) || (eax==PROCESSOR_ARCHITECTURE_ARM64) push OFFSET g_sz64Bit .else push OFFSET g_sz32Bit .endif .ENDIF .endif call editCatStr ;invoke editCatStr, eax ret showOsType endp
修改的程序汇编连接正常,运行时可以正常显示Windows操作系统类型是32位还是64位的,但显示完这行信息后停滞了一下,随后SysInfo窗口就没有任何提示地自动关闭了。
用OllyDbg跟踪了代码运行情况,代码运行正常,可以获得正确的操作系统类型信息,但是在函数执行结束返回时出现了访问异常。
还是第一次遇到这种情况,为了弄清楚原因,把showOsType()代码拿出来单独测试,代码如下:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; FileName: WinBit.asm ; Function: Show windows bit with API GetNativeSystemInfo ; Author: PurpleEndurer ; DevEnv: Windows 10 + MASM32 ; ; Log: ;--------------------------------------------------------------- ; 20221216 Created ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .586 .model flat, stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss ;proto ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss _GetNativeSystemInfo TYPEDEF proto :DWORD _LPFNGetNativeSystemInfo TYPEDEF Ptr _GetNativeSystemInfo showOsType proto ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss ;.const ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss ;PROCESSOR_ARCHITECTURE_INTEL equ 0 ;x86 ;PROCESSOR_ARCHITECTURE_ARM equ 5 ;ARM ;PROCESSOR_ARCHITECTURE_IA64 equ 6 ;基于 Intel Itanium 的 ;PROCESSOR_ARCHITECTURE_AMD64 equ 9 ;x64 (AMD 或 Intel) PROCESSOR_ARCHITECTURE_ARM64 equ 12 ;ARM64 ;PROCESSOR_ARCHITECTURE_UNKNOWN equ 0ffffh ;未知体系结构。 ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss ;.data ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss .code ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss g_szOsType db "系统类型:", 0 g_sz32Bit db "32位",0 g_sz64Bit db "64位",0 g_szGetNativeSystemInfo db "GetNativeSystemInfo", 0 g_szkernel32Dll db "kernel32.dll", 0 g_szFailGetModuleHandle db "GetModuleHandle失败", 0 g_szFailGetProcAddress db "GetProcAddress失败", 0 g_szFailGetNativeSystemInfo db "GetNativeSystemInfo失败", 0 showOsType proc LOCAL lpSI: dword LOCAL lpfnGetNativeSystemInfo: _LPFNGetNativeSystemInfo invoke GetModuleHandle, OFFSET g_szkernel32Dll .if eax==NULL mov eax, OFFSET g_szFailGetModuleHandle .else invoke GetProcAddress, eax, OFFSET g_szGetNativeSystemInfo .IF eax==NULL mov eax, OFFSET g_szFailGetProcAddress .ELSE mov lpfnGetNativeSystemInfo, eax invoke lpfnGetNativeSystemInfo, ADDR lpSI lea eax, lpSI movzx eax, (SYSTEM_INFO ptr [eax]).wProcessorArchitecture .if (eax==PROCESSOR_ARCHITECTURE_IA64) || (eax==PROCESSOR_ARCHITECTURE_AMD64) || (eax==PROCESSOR_ARCHITECTURE_ARM64) mov eax, OFFSET g_sz64Bit ; push OFFSET g_sz64Bit .else mov eax, OFFSET g_sz32Bit ; push OFFSET g_sz32Bit .endif .ENDIF .endif push eax invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK pop eax ret showOsType endp main proc invoke showOsType invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK invoke ExitProcess, NULL main endp end main
代码汇编连接成功,运行时正常显示showOsType()中
invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK
然后就出现问题了:
E xception 000006BA . exception is non-continuable
main()函数中的
invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK
1.
并没有得到执行,显示出信息框来。
开始百思不得其解,后面重新研究了GetNativeSystemInfo的参数说明:
参数
[out] lpSystemInfo
指向接收信息的 SYSTEM_INFO 结构的指针。
我代码中传递GetNativeSystemInfo()的参数dword类型变量lpSI,其值没有初始化,而不是指向一个SYSTEM_INFO结构的地址(指针)。这样GetNativeSystemInfo函数返回的SYSTEM_INFO结构信息数据覆盖了函数返回信息数据,导致函数结束返回时跳到了错误的地址,引发异常。
原来如此,看来lpSI定义为全局变量没有出现问题纯属侥幸。写代码一定要看清楚函数原型和说明。
参考:
GetNativeSystemInfo 函数 (sysinfoapi.h)