天天看點

NTDLL未文檔化函數RtlGetNtVersionNumbers擷取作業系統版本

作為新手,對擷取作業系統版本号好奇過,因為曾經假象過一個場景:自己的程式在windows xp環境下編譯,在windows 2003,

windows 7,windows 8是否需要提權或者相容處理,如果程式在windows 7以上版本需要特殊處理又該怎樣判斷作業系統版本呢。

帶着這個好奇也了解過​​GetVersion​​​和​​GetVersionEx​​函數,他們的最低使用需求是Windows 2000,以下是一些官方的測試代碼。

GetVersion function

#include <windows.h>
#include <stdio.h>

void main()
{
    DWORD dwVersion = 0; 
    DWORD dwMajorVersion = 0;
    DWORD dwMinorVersion = 0; 
    DWORD dwBuild = 0;
    
    dwVersion = GetVersion();
    
    // Get the Windows version.
    
    dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
    dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
    
    // Get the build number.
    
    if (dwVersion < 0x80000000)              
        dwBuild = (DWORD)(HIWORD(dwVersion));
    
    printf("Version is %d.%d (%d)\n", 
        dwMajorVersion,
        dwMinorVersion,
        dwBuild);
}      

運作結果:

Version is 5.1 (2600)

GetVersionEx function

#include <windows.h>
#include <stdio.h>

void main()
{
    OSVERSIONINFO osvi;
    BOOL bIsWindowsXPorLater;
    
    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    
    GetVersionEx(&osvi);
    
    bIsWindowsXPorLater = 
        ( (osvi.dwMajorVersion > 5) ||
        ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) ));
    
    if(bIsWindowsXPorLater)
        printf("The system meets the requirements.\n");
    else printf("The system does not meet the requirements.\n");
}      

運作結果:

The system meets the requirements.

今天偶然看見一個文章(GetVersionEx 如何區分win8和win8.1​)和部落格(Windows系統版本判定那些事兒)介紹這兩個函數,說是在判斷 Win8和Win8.1的時候有問題,可以正常傳回值:

對于一個未加特殊處理的應用程式用GetVersionEx擷取win8和win8.1系統版本,一律都是6.2

這是多麼的坑人啊,令人敬畏。

從以上内容了解到了一個ntdll未公開的函數RtlGetNtVersionNumbers,了解到這個函數以後,我用工具檢視了ntdll.dll導出函數,的确還真有這個呢。

檢視導出函數可以用exescope/pexplorer/CFF explorer,選擇導出-->ntdll.dll/導出表檢視器/導出目錄就可以找到導出位址了。

網友公布的函數使用方法我也在本地編譯了一次

#include <stdio.h>
#include <windows.h>

typedef void (__stdcall *NTPROC)(DWORD*,DWORD*,DWORD*);

void GetWinVer()
{
    HINSTANCE hinst = LoadLibrary("ntdll.dll");
    DWORD dwMajor,dwMinor,dwBuildNumber;
    NTPROC proc = (NTPROC)GetProcAddress(hinst,"RtlGetNtVersionNumbers");
    proc(&dwMajor,&dwMinor,&dwBuildNumber);
    dwBuildNumber&=0xffff;
    printf("OS:%d.%d.%d\n",dwMajor,dwMinor,dwBuildNumber);
    FreeLibrary(hinst);
}

void main(void)
{
    GetWinVer();
}      

運作結果:

ver
Microsoft Windows XP [版本 5.1.2600]