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
并没有得到执行,显示出信息框来。
开始百思不得其解,后面重新研究了GetNativeSystemInfo的参数说明:
参数
[out] lpSystemInfo
指向接收信息的 SYSTEM_INFO 结构的指针。
我代码中传递GetNativeSystemInfo()的参数dword类型变量lpSI,其值没有初始化,而不是指向一个SYSTEM_INFO结构的地址(指针)。这样GetNativeSystemInfo函数返回的SYSTEM_INFO结构信息数据覆盖了函数返回信息数据,导致函数结束返回时跳到了错误的地址,引发异常。
原来如此,看来lpSI定义为全局变量没有出现问题纯属侥幸。写代码一定要看清楚函数原型和说明。
参考: