三年前面朝黄土背朝天的我,写了一篇如何在Windows 7
系统下枚举内核SSDT
表的文章《驱动开发:内核读取SSDT表基址》
三年过去了我还是个单身狗
,开个玩笑,微软的Windows 10
系统已经覆盖了大多数个人PC终端,以前的方法也该进行迭代更新了,或许在网上你能够找到类似的文章,但我可以百分百肯定都不能用,今天LyShark
将带大家一起分析Win10 x64
最新系统SSDT
表的枚举实现 。
看一款闭源ARK工具的枚举效果:
文章插图
直接步入正题,首先
SSDT
表中文为系统服务描述符表,SSDT表的作用
是把应用
层与内核
层联系起来
起到桥梁
的作用,枚举SSDT表
也是反内核
工具最基本的功能,通常在64位
系统中要想找到SSDT
表,需要先找到KeServiceDescriptorTable
这个函数,由于该函数没有被导出,所以只能动态的查找它的地址,庆幸的是我们可以通过查找msr(c0000082)
这个特殊的寄存器来替代查找KeServiceDescriptorTable
这一步,在新版系统中查找SSDT可以归纳为如下这几个步骤 。- rdmsr c0000082 -> KiSystemCall64Shadow -> KiSystemServiceUser -> SSDT
rdmsr C0000082
MSR寄存器得到KiSystemCall64Shadow
的函数地址,计算KiSystemCall64Shadow
与KiSystemServiceUser
偏移量,如下图所示 。- 得到相对偏移
6ed53180(KiSystemCall64Shadow) - 6ebd2a82(KiSystemServiceUser) = 1806FE
- 也就是说
6ed53180(rdmsr) - 1806FE = KiSystemServiceUser
文章插图
如上当我们找到了
KiSystemServiceUser
的地址以后,在KiSystemServiceUser
向下搜索可找到KiSystemServiceRepeat
里面就是我们要找的SSDT
表基址 。其中
fffff8036ef8c880
则是SSDT表
的基地址,紧随其后的fffff8036ef74a80
则是SSSDT表
的基地址 。【驱动开发:Win10内核枚举SSDT表基址】
文章插图
那么如果将这个过程通过代码的方式来实现,我们还需要使用
《驱动开发:内核枚举IoTimer定时器》
中所使用的特征码定位技术,如下我们查找这段特征 。// 署名权// right to sign one's name on a piece of work// PowerBy: LyShark// Email: me@lyshark.com#include <ntifs.h>#pragma intrinsic(__readmsr)ULONGLONG ssdt_address = 0;// 获取 KeServiceDescriptorTable 首地址ULONGLONG GetLySharkCOMKeServiceDescriptorTable(){ // 设置起始位置 PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082) - 0x1806FE; // 设置结束位置 PUCHAR EndSearchAddress = StartSearchAddress + 0x100000; DbgPrint("[LyShark Search] 扫描起始地址: %p --> 扫描结束地址: %p \n", StartSearchAddress, EndSearchAddress); PUCHAR ByteCode = NULL; UCHAR OpCodeA = 0, OpCodeB = 0, OpCodeC = 0; ULONGLONG addr = 0; ULONG templong = 0; for (ByteCode = StartSearchAddress; ByteCode < EndSearchAddress; ByteCode++) {// 使用MmIsAddressValid()函数检查地址是否有页面错误if (MmIsAddressValid(ByteCode) && MmIsAddressValid(ByteCode + 1) && MmIsAddressValid(ByteCode + 2)){OpCodeA = *ByteCode;OpCodeB = *(ByteCode + 1);OpCodeC = *(ByteCode + 2);// 对比特征值 寻找 nt!KeServiceDescriptorTable 函数地址/*nt!KiSystemServiceRepeat:fffff803`6ebd2b94 4c8d15e59c3b00lear10,[nt!KeServiceDescriptorTable (fffff803`6ef8c880)]fffff803`6ebd2b9b 4c8d1dde1e3a00lear11,[nt!KeServiceDescriptorTableShadow (fffff803`6ef74a80)]fffff803`6ebd2ba2 f7437880000000testdword ptr [rbx+78h],80hfffff803`6ebd2ba9 7413jent!KiSystemServiceRepeat+0x2a (fffff803`6ebd2bbe)Branch*/if (OpCodeA == 0x4c && OpCodeB == 0x8d && OpCodeC == 0x15){// 获取高位地址fffff802memcpy(&templong, ByteCode + 3, 4);// 与低位64da4880地址相加得到完整地址addr = (ULONGLONG)templong + (ULONGLONG)ByteCode + 7;return addr;}} } return0;}VOID UnDriver(PDRIVER_OBJECT driver){ DbgPrint(("驱动程序卸载成功! \n"));}NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){ DbgPrint("hello lyshark.com"); ssdt_address = GetLySharkCOMKeServiceDescriptorTable(); DbgPrint("[LyShark] SSDT = %p \n", ssdt_address); DriverObject->DriverUnload = UnDriver; return STATUS_SUCCESS;}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 烟雾保护头怎么调(win10cf烟雾保护头怎么调)
- 新版烟雾保护头怎么调(win10烟雾保护头怎么调)
- 驱动开发:内核特征码扫描PE代码段
- 驱动开发:内核枚举Minifilter微过滤驱动
- 软件开发工程师工资一般多少 收入高吗
- 软件开发需要学什么 都有哪些课程
- Vue3 JS 与 SCSS 变量相互使用
- 24 Node.js躬行记——低代码
- 驱动开发:内核枚举PspCidTable句柄表
- 驱动开发:内核枚举DpcTimer定时器