Win64 Driver开发问题记录(二)

Win64 driver开发中遇到的第二个问题是如何通过SSDT表引用系统服务内核函数。

MS在64系统中引入了全新的PatchGuard技术,使得原本在32位下可轻易hook的SSDT表在64位系统中无法再patch(会引发BSOD).

当然,目前我并非是要hook SSDT表,而是需要使用到SSDT表中的一个未导出的系统服务内核函数。在32位driver中可以通过extern "C" 外部声明来直接获得SSDT表KeServiceDescriptorTable的引用。在64位driver下虽然KeServiceDescriptorTable仍然被ntoskrnl.exe导出,但驱动程序已无法通过extern “C"外部声明来获得。因此目前的做法只能是通过特征码搜索找出KeServiceDescriptorTable的地址。

 

KiSystemServiceRepeat()函数对于KeServiceDe  script  orTable有直接的引用(win7 64为例)

nt!KiSystemServiceRepeat:
fffff800`0268eff2 4c8d1547782300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`028c6840)]
fffff800`0268eff9 4c8d1d80782300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`028c6880)]


然而KiSystemServiceRepeat()本身就是一个未导出函数,要找到KiSystemServiceRepeat()本身就不是一件容易的事。因此目前方法采用了通过另一个导出函数KeAddSystemServiceTable()来搜索KeServiceDescriptorTable的地址, 导出函数地址可以通过MmGetSystemRoutineAddress()来获得

 

[WINXP 32]
nt!KeAddSystemServiceTable+0xb:
805a1319 8b4518          mov     eax,dword ptr [ebp+18h]
805a131c c1e004          shl     eax,4
805a131f 83b800c7558000  cmp     dword ptr nt!KeServiceDescriptorTable (8055c700)[eax],0
805a1326 7551            jne     nt!KeAddSystemServiceTable+0x6b (805a1379)

nt!KeAddSystemServiceTable+0x1a:
805a1328 8d88c0c65580    lea     ecx,nt!KeServiceDescriptorTableShadow (8055c6c0)[eax]
805a132e 833900          cmp     dword ptr [ecx],0

 

[WIN7 64]

nt!KeAddSystemServiceTable+0x9:
fffff800`02a00cd9 4c8bd0          mov     r10,rax
fffff800`02a00cdc 4c8d1d1dd3c1ff  lea     r11,[nt!MmIsSessionAddress <PERF> (nt+0x0) (fffff800`0261e000)]
fffff800`02a00ce3 49c1e205        shl     r10,5
fffff800`02a00ce7 4b83bc1a40882a0000 cmp   qword ptr [r10+r11+2A8840h],0
fffff800`02a00cf0 7553            jne     nt!KeAddSystemServiceTable+0x75 (fffff800`02a00d45)

nt!KeAddSystemServiceTable+0x22:
fffff800`02a00cf2 4b83bc1a80882a0000 cmp   qword ptr [r10+r11+2A8880h],0

 

对比32位系统,可以发现该函数会判断KeServiceDescriptorTable是否为0. 在win7 64位下KeServiceDescriptorTable地址其实隐藏在如下两条指令中

fffff800`02a00cdc 4c8d1d1dd3c1ff  lea     r11,[nt!MmIsSessionAddress <PERF> (nt+0x0) (fffff800`0261e000)]
fffff800`02a00ce7 4b83bc1a40882a0000 cmp   qword ptr [r10+r11+2A8840h],0


查询Intel® 64 and IA-32 Architectures Software Developer's Manual,解释如下两条指令:

 

fffff800`02a00cdc 4c8d1d1dd3c1ff  lea     r11,[nt!MmIsSessionAddress <PERF> (nt+0x0) (fffff800`0261e000)]

LEA – Load Effective Address
in qwordregister 0100 1RXB : 1000 1101 : modA qwordreg r/m

                                 4        c         8        d               1d                1dd3c1ff

计算出基地址是EIP+ff3c1d=fffff800`02a00ce3+ffc1d31d=fffff800`0261e000

 

fffff800`02a00ce7 4b83bc1a40882a0000 cmp   qword ptr [r10+r11+2A8840h],0

CMP – Compare Two Operands
immediate8 with memory64 0100 1RXB 1000 0011 : mod 111 r/m : imm8

                                                      4       b       8       3           bc       40882a00  00                   

偏移地址就是2a8840

所以计算出来的KeServiceDescriptorTable地址就是fffff800`0261e000+2a8840=fffff800`028c6840

kd> dd KeServiceDescriptorTable
fffff800`028c6840  02690b00 fffff800 00000000 00000000

 

在实际的driver中,只需要将lea(0x8d4c)和cmp(0x834b)作为特征码,就可以通过内存搜索的方式来获取KeServiceDescriptorTable的地址了

经过测试,在2k以后各版本win64(不包含win8)上均正常工作

本实例由VS2008开发,在提供了一套驱动开发框架的同时,又演示了如何获取Shadow SSDT表函数原始地址的办法。 主要函数:ULONG GetShadowSSDT_Function_OriAddr(ULONG index); 原理说明: 根据特征索导出函数KeAddSystemServiceTable来获取Shadow SSDT基址,以及通过ZwQuerySystemInformation()函数获取win32k.sys基址,然后解析PE定位到Shadow SSDT在win32k.sys的偏移地址,并通过进一步计算来得到Shadow SSDT表函数的原始地址。 这里只测试了三个函数:(460)NtUserMessageCall、(475)NtUserPostMessage和(502)NtUserSendInput,具体使用时可以举一反三,网上完整的源代实例并不太多,希望可以帮到真正有需要的朋友。 系统环境: 在WinXP SP3系统 + 瑞星杀毒软件 打印输出: [ LemonInfo : Loading Shadow SSDT Original Address Driver... ] [ LemonInfo : 创建“设备”值为:0 ] [ LemonInfo : 创建“设备”成功... ] [ LemonInfo : 创建“符号链接”状态值为:0 ] [ LemonInfo : 创建“符号链接”成功... ] [ LemonInfo : 驱动加载成功... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 开始... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP Enter IRP_MJ_DEVICE_CONTROL... ] [ LemonInfo : 获取ShadowSSDT表 (460)NtUserMessageCall 函数的“当前地址”为:0xB83ECFC4,“起源地址”为:0xBF80EE6B ] [ LemonInfo : 获取ShadowSSDT表 (475)NtUserPostMessage 函数的“当前地址”为:0xB83ECFA3,“起源地址”为:0xBF8089B4 ] [ LemonInfo : 获取ShadowSSDT表 (502)NtUserSendInput 函数的“当前地址”为:0xBF8C31E7,“起源地址”为:0xBF8C31E7 ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP_MJ_DEVICE_CONTROL 成功执行... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 结束... ] [ LemonInfo : UnLoading Shadow SSDT Original Address Driver... ] [ LemonInfo : 删除“符号链接”成功... ] [ LemonInfo : 删除“设备”成功... ] [ LemonInfo : 驱动卸载成功... ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值