天天看点

解读 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;

当然,这个函数并不需要通过这种方法进行调用,只是为了熟悉函数的调用方法而已。

继续阅读