首页
社区
课程
招聘
[原创] x64通过用导出公开函数偏移的方式获取SSDT表基址
发表于: 2024-11-17 01:42 1637

[原创] x64通过用导出公开函数偏移的方式获取SSDT表基址

2024-11-17 01:42
1637

通过ZwSetEvent导出公开函数一层一层偏移到KeServiceDescriptorTable


不止ZwSetEvent函数,还可以用ZwOpenThread,ZwOpenProcess等函数。只要内部调用了KiServiceInternal函数的的都可以偏移到SSDT基址

代码如下:

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
54
55
56
57
58
59
60
61
#include <ntifs.h>
 
#pragma pack(1)
typedef struct _SERVICE_DESCIPTOR_TABLE
{
    PULONG ServiceTableBase;        // SSDT基址,8字节大小
    PVOID ServiceCounterTableBase;  // SSDT中服务被调用次数计数器,8字节大小
    ULONGLONG NumberOfService;      // SSDT服务函数的个数,8字节大小
    PVOID ParamTableBase;           // 系统服务参数表基址,8字节大小。实际指向的数组是以字节为单位的记录着对应服务函数的参数个数
}SSDTEntry, * PSSDTEntry;
#pragma pack()
 
 
NTSTATUS Unload(PDRIVER_OBJECT pDriverObj)
{
    return STATUS_SUCCESS;
}
 
 
NTSTATUS DriverEntry(PDRIVER_OBJECT  pDriverObj, PUNICODE_STRING pReg)
{
    pDriverObj->DriverUnload = Unload;
 
//测试系统:WIN10_22H2_X64
//还未测试过其它版本的偏移是否一样
 
    /*
        * 获取SSDT表
        * ZwSetEvent()+0x19 -> KiServiceInternal()+5A -> KiSystemServiceStart()+0x14 -> KeServiceDescriptorTable
        * 系统调用对应的内核函数地址 = SSDT基地址 + ((*(ULONG*)(SSDT基地址 + 调用号 * 4)) >> 4)
    */
    //获取指令
    PVOID KiServiceInternal_temp = NULL;
    PVOID KiSystemServiceStart_temp = NULL;
    PVOID KeServiceDescriptorTable = NULL;
    UCHAR jmp_KiServiceInternal[5] = { 0 };
    UCHAR lea_KiSystemServiceStart[7] = { 0 };
    UCHAR lea_KeServiceDescriptorTable[7] = { 0 };
 
    //获取跳转到KiServiceInternal的指令
    for (size_t i = 0; i < sizeof(jmp_KiServiceInternal); i++)
        jmp_KiServiceInternal[i] = *(PUCHAR)((PUCHAR)ZwSetEvent + 0x19 + i);
    //计算KiServiceInternal函数地址 (指令RIP+跳转偏移(例:E9后面的4个字节XXXXXXXX))+指令长度 = 跳转的内存地址
    KiServiceInternal_temp = (PVOID)((((PUCHAR)ZwSetEvent + 0x19) + *(ULONG*)(jmp_KiServiceInternal + 0x1)) + sizeof(jmp_KiServiceInternal));
 
    //获取跳转到KiSystemServiceStart的指令
    for (size_t i = 0; i < sizeof(lea_KiSystemServiceStart); i++)
        lea_KiSystemServiceStart[i] = *(PUCHAR)((PUCHAR)KiServiceInternal_temp + 0x5A + i);
    //计算KiSystemServiceStart函数地址 (指令RIP+跳转偏移(例:E9后面的4个字节XXXXXXXX))+指令长度 = 跳转的内存地址
    KiSystemServiceStart_temp = (PVOID)((((PUCHAR)KiServiceInternal_temp + 0x5A) + *(ULONG*)(lea_KiSystemServiceStart + 0x3)) + sizeof(lea_KiSystemServiceStart));
 
    //获取KeServiceDescriptorTable的指令
    for (size_t i = 0; i < sizeof(lea_KeServiceDescriptorTable); i++)
        lea_KeServiceDescriptorTable[i] = *(PUCHAR)((PUCHAR)KiSystemServiceStart_temp + 0x14 + i);
    //计算KeServiceDescriptorTable地址 (指令RIP+跳转偏移(例:E9后面的4个字节XXXXXXXX))+指令长度 = 跳转的内存地址
    KeServiceDescriptorTable = (PVOID)((((PUCHAR)KiSystemServiceStart_temp + 0x14) + *(ULONG*)(lea_KeServiceDescriptorTable + 0x3)) + sizeof(lea_KeServiceDescriptorTable));
 
    PSSDTEntry pSSDT = KeServiceDescriptorTable;
 
    return STATUS_SUCCESS;
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2024-11-17 21:47 被胖虎404编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//