R3获取ShadowSSDT原始地址

我们知道ShadowSSDT的实现存在于win32k.sys中,所以我们只要分析win32k.sys文件就能获取原始的ShadowSSDT地址。

A primary default array table, KeServiceDescriptorTable, defines the core executive system services implemented in Ntosrknl.exe. The other table array, KeServiceDescriptorTableShadow, includes the Windows USER and GDI services implemented in the kernel-mode part of the Windows subsystem, Win32k.sys. The first time a Windows thread calls a Windows USER or GDI service, the address of the thread’s system service table is changed to point to a table that includes the Windows USER and GDI services. The KeAddSystemServiceTable function allows Win32k.sys to add a system service table.

上面是摘自深入解析Windows 操作系统里面的一段话,说的是win32k.sys会调用KeAddSystemServiceTable 这个方法来初始化ShadowSSDT。

那么我们用IDA来打开win32k.sys这个文件,找到KeAddSystemServiceTable 这个函数。

image

 

我们可以看到,确实使用KeAddSystemServiceTable来初始化ShadowSSDT的。而且第一个参数就是W32pServiceTable也就是我们所要找的ShadowSSDT原始函数数组。

是不是我们跟进去看一下就知道了。。。

image

确实是。。。

所以我们就可以根据KeAddSystemServiceTable这个函数来找到W32pServiceTable的地址,然后根据这个地址,分别取得函数的地址。那么KeAddSystemServiceTable要怎么获取,其实我们可以在导入表中找到这个函数,所以只要解析PE文件,从导入表中找到这个函数的地址即可。

从导入表获取KeAddSystemServiceTable的地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
ULONG GetKeAddSTAddress(HANDLE hWin32k)
{
    PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)hWin32k;
    PIMAGE_NT_HEADERS pImageNtHeader = (PIMAGE_NT_HEADERS)((ULONG)hWin32k + (ULONG)pImageDosHeader->e_lfanew);
    PIMAGE_IMPORT_DESCRIPTOR pImageImportDir = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG)hWin32k + pImageNtHeader->OptionalHeader.DataDirectory[1].VirtualAddress);
    PIMAGE_IMPORT_DESCRIPTOR pImageImportDesc;
    PULONG pOriginalThunkData;
    PULONG pFirstThunkData;
    PIMAGE_IMPORT_BY_NAME pImageImportByName;
    ULONG uRetAddress;
    CHAR buf[8];
    BOOL bStop = FALSE;

    if(pImageNtHeader->OptionalHeader.DataDirectory[1].VirtualAddress == 0 && pImageNtHeader->OptionalHeader.DataDirectory[1].Size == 0)
    {
        return -1;
    }

    __try
    {
        for (pImageImportDesc = pImageImportDir; pImageImportDesc->Name; pImageImportDesc++)
        {
            for (pOriginalThunkData = (PULONG)((DWORD)hWin32k + pImageImportDesc->OriginalFirstThunk), pFirstThunkData = (PULONG)((DWORD)hWin32k + pImageImportDesc->FirstThunk);*pOriginalThunkData && *pFirstThunkData; pOriginalThunkData++,pFirstThunkData++)
            {
                if((*pOriginalThunkData) & IMAGE_ORDINAL_FLAG)
                {
                    sprintf_s(buf, "#%d", (*pOriginalThunkData) & 0x7fffffff);
                    if(_stricmp(buf, "KeAddSystemServiceTable") == 0)
                    {
                        uRetAddress = (ULONG)pFirstThunkData;
                        bStop = TRUE;
                        break;
                    }
                }
                else
                {
                    pImageImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)hWin32k + ((PIMAGE_THUNK_DATA)pOriginalThunkData)->u1.AddressOfData);
                    if(_stricmp((PCHAR)pImageImportByName->Name, "KeAddSystemServiceTable") == 0)
                    {
                        uRetAddress = (ULONG)pFirstThunkData;
                        bStop = TRUE;
                        break;
                    }
                }
            }
            if(bStop)break;
        }
    }
    __except(1)
    {
        return -1;
    }
}

根据KeAddSystemServiceTable和特征码来得到W32pServiceTable的地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
hWin32k = ::LoadLibraryEx(L"win32k.sys", 0, DONT_RESOLVE_DLL_REFERENCES);
        PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)hWin32k;
        PIMAGE_NT_HEADERS pImageNtHeader = (PIMAGE_NT_HEADERS)((ULONG)hWin32k + (ULONG)pImageDosHeader->e_lfanew);

        uImageBase = pImageNtHeader->OptionalHeader.ImageBase;
        uImageEntryPoint= pImageNtHeader->OptionalHeader.AddressOfEntryPoint;
        uWin32kBase = GetModuleBaseR3(szWin32kName);

        uKeAddSystemServiceTableVA = GetKeAddSTAddress(hWin32k);
        uKeAddSystemServiceTableRVA = uKeAddSystemServiceTableVA - (ULONG)hWin32k;
        uMagicAddr = uKeAddSystemServiceTableRVA + uImageBase;
        uImageEntry = (ULONG)((DWORD)hWin32k + uImageEntryPoint);
        for (i = 0; i < 0x10000; i++)
        {
            pShadowSsdtMagic = (PSHADOW_SSDT_MAGIC)(uImageEntry + i);
            if(pShadowSsdtMagic->uMagic == 0x15ff)
            {
                if(pShadowSsdtMagic->uMagicNum == uMagicAddr)
                {
                    pWin32ServiceTable = (PULONG)(*(PULONG)(uImageEntry + i - 4));
                    break;
                }
            }
        }

        pWin32ServiceTable = (PULONG )((ULONG)pWin32ServiceTable - uImageBase + (DWORD)hWin32k);

下面是我在win7 32位下面获取shadowssdt当前地址和原始地址的效果图:

wps_clip_image-18484

本文链接:http://www.alonemonkey.com/get-original-shadowssdt.html