天天看點

解讀 RtlGetVersion解讀 RtlGetVersion

解讀 RtlGetVersion

獲得系統版本号。

NTSTATUS RtlGetVersion(OSVERSIONINFOW &VersionInformation)
{
    UINT_PTR pfn = CalcFunctionAddress(phWCP, pfb_RtlGetVersion);

    typedef signed int(__stdcall * fnRtlGetVersion)(OSVERSIONINFOW&);

    fnRtlGetVersion g_fnRtlGetVersion = (fnRtlGetVersion)*(UINT_PTR*)pfn;

    VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    memset(&VersionInformation.dwMajorVersion, ,
        sizeof(VersionInformation.szCSDVersion));
    NTSTATUS result = g_fnRtlGetVersion(VersionInformation);

    return result;
}

這個函數比較特别的是,屬
           

于導入函數,在 WCP.dll 中隻有函數的位址。

在 64 位版本下有個備注,可以知道其位址:

1802449C0: using guessed type int __fastcall RtlGetVersion(_QWORD);

32 位版本卻沒有任何資訊。

從 ida 中找到導入函數:

584904D0 RtlGetVersion ntdll

再減去 wcp.dll 的起始位址:

using load address 58210000

得到 RtlGetVersion 在 wcp.dll 中的函數的偏移位址,0x102804D0。

這樣就可以用與本地函數基本相同的方法通路導入函數了。

既然是基本相同,那就肯定有不同了。

本地函數,用偏移位址經過計算出來的位址就是函數位址了,可以直接進行調用。

而導入函數,用偏移位址經過計算出來的位址并不是該函數的真正位址,而是,原函數在本地統一編址的位址,這個位址中儲存的值才是原函數的真正位址,0x7753bd40。可以看到,這明顯是另外一

相比較本地函數,導入函數要多取一次位址值的過程,(UINT_PTR):

本地函數:

fnRtlGetVersion g_fnRtlGetVersion = (fnRtlGetVersion)pfn;

導入函數:

fnRtlGetVersion g_fnRtlGetVersion = (fnRtlGetVersion)(UINT_PTR)pfn;

當然,這個函數并不需要通過這種方法進行調用,隻是為了熟悉函數的調用方法而已。

繼續閱讀