-
-
[原创] 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编辑
,原因:
赞赏
看原图
赞赏
雪币:
留言: