易语言教程_易语言源码_易语言视频教程_易语言论坛

 找回密码
 点击注册

Vip新手入门区
新手学习指南  学员作品展示 Vip课程总纲  Vip绝密课程系列

Vip相关下载区
Vip模块下载   Vip模块绑定   Vip模块例子 魔鬼插件下载  魔鬼插件例子  教程工具下载

Vip论坛服务区
教程问题提问区   模块问题提问区 技术交流区   魔鬼插件建议   忘记密码找回

VIP会员办理QQ: 8643245   
【请先加好友,然后到好友列表双击联系客服,办理VIP会员。】
【基础篇】易语言辅助入门基础教程
VIP模块办理QQ: 7189694 办理正版魔鬼作坊VIP模块 【基础篇】OD与CE入门基础教程
办理【终身VIP会员】“秒杀价” 仅需 RMB278.00元… 【基础篇】零基础绝密汇编语言入门课程 (共26课已完成)…
办理VIP详情…猛击这里查看详情 【基础篇】VIP辅助入门基础教程-新手必学 已发布10课 ……
VIP教程免费试看章节…猛击下载 【第1款】制作“辅助挂”教程目录查看(共107+16_x64下更新课已完成)…
亲爱的VIP学员,请到此写下你学习的感受与发布作品截图… 【第2款】制作“任务挂”教程目录查看(共77+1_x64下更新课已完成)…
卍解吧!不用bp send类封包断点找CALL的各种通杀思路 【第3款】驱动过保护技术课程(共38课已完成)…
【绝密教程】VIP绝密教程系列---注意:随时会更新! 【第4款】VIP邪恶二叉树辅助课程 (共31+17_x64下更新课已完成)…
【精品第13款】3D射击游戏与页游透视 智辅课程 已完成17课… 【第5款】零基础易语言按键辅助教程 (30课已完成)…
【精品第14款】变态功能辅助是如何炼成的 已完成36课… 【第6款】从零开始学习封包辅助技术教程(20课已完成) …
【精品第15款】DNF商业变态辅助的修炼之路 已完成27课… 【第7款】大杀特杀分析来源与CALL吸血鬼课程 (56课已完成)
【精品第16款】中控台多线程多开自动化商业辅助课程 已完成66课… 【第8款】完全零基础网页辅助课程(40课已完成)
【全新精品第17款】检测原理与过游戏内存检测技术课程 已发布9课… 【第9款】自动登录与操控LUA技术课程 (共46+8_x64下更新课已完成)…
【全新精品第18款】手游全自动化任务脚本辅助课程 已发布25课…… 【第10款】网页辅助封包脱机进阶课程 已完成30课…
【全新精品第19款】D3D方框骨骼透视与自瞄辅助课程进阶篇 已发布34课…… 【第11款】VC++ Lua脚本辅助课程 已完成112课…
【全新精品第20款】 X64模拟器吃鸡游戏方框透视自瞄辅助课程 发布中... 【第12款】网游脱机封包智辅课程 已完成35课…
查看: 1614|回复: 0

WINDOWS 64位SSDT定位思路

[复制链接]

14

主题

3

回帖

23

积分

编程入门

Rank: 1

魔鬼币
512
发表于 2011-4-28 16:16:30 | 显示全部楼层 |阅读模式
在32位Windows中我们有很多定位SSDT的方法,最直接的就是利用导出符号来找到SSDT。再有就是通过在nt!KeAddSystemServiceTable函数中进行反汇编搜索。可是在64位WINDOWS中这两种方法都行不通。在64位Windows中不在导出SSDT了,同时nt!KeAddSystemServiceTable中也不再出SSDT了(此处说明有误,应该为不出现直接的SSDT地址了,个人水平有限感觉计算太麻烦。)。
这样要HOOK SSDT表就出现了第一个问题如何找到它?我想了三种思路。

思路1:
对每种版本的系统确定一个ntoskrnl到SSDT的硬编码偏移。呵呵,这种方法可能比较傻但最简单直接有效。就是维护起来比较非常麻烦,要对每一个版本进单独处理,如果不同补丁版本有变化也要处理。

思路2:
64位WINDOWS中存放着每个服务例程的入口偏移(这个偏移是相对于SSDT的开始地址的)。我取一个一般不被HOOK的服务例程入口偏移,然后从ntoskrnl的开始地址一直搜索到结束来查找这四个字节,然后根据服务例程的索引定位到SSDT的开始位置。可能对不同版本的操作系统其偏移和索引是不同的需要分别进行处理,但是相比第一种思路要通用一些。

思路3:
还是利用反汇编的方法,但是nt!KeAddSystemServiceTable函数中已经找不到直接的SSDT地址了。后来我想能不能映像搜索到SSDT的地址。
kd> dq nt!KeServiceDescriptorTable
fffff800`03eab840  fffff800`03c75b00 00000000`00000000
fffff800`03eab850  00000000`00000191 fffff800`03c7678c
fffff800`03eab860  00000000`00000000 00000000`00000000
fffff800`03eab870  00000000`00000000 00000000`00000000
fffff800`03eab880  fffff800`03c75b00 00000000`00000000
fffff800`03eab890  00000000`00000191 fffff800`03c7678c
fffff800`03eab8a0  fffff960`00111c00 00000000`00000000
fffff800`03eab8b0  00000000`0000033b fffff960`0011391c
kd> lm m nt
start             end                 module name
fffff800`03c03000 fffff800`041e0000   nt         (pdb symbols)
kd> s -q fffff800`03c03000 l600000 fffff800`03eab840

很不幸我没有找到任何相关的信息。呵呵,但是我贼心不是死,相信肯定在某处会有引用的。于是我搜索了一下所有名称中含有Service单词的符号。

kd> x nt!Ki*Service*
fffff800`03c73e40 nt!KiServiceInternal = <no type information>
fffff800`03c7415b nt!KiSystemServiceExit = <no type information>
fffff800`03c73fde nt!KiSystemServiceStart = <no type information>
fffff800`03c76788 nt!KiServiceLimit = <no type information>
fffff800`03c73b00 nt!KiDebugServiceTrap = <no type information>
fffff800`03c74140 nt!KiSystemServiceCopyEnd = <no type information>
fffff800`03c75b00 nt!KiServiceTable = <no type information>
fffff800`03c74037 nt!KiSystemServiceGdiTebAccess = <no type information>
fffff800`03c73ff2 nt!KiSystemServiceRepeat = <no type information>
fffff800`03c740d0 nt!KiSystemServiceCopyStart = <no type information>
fffff800`03c706f0 nt!KiServiceLinkage = <no type information>
fffff800`03c73d40 nt!KiSystemServiceHandler = <no type information>

终于在nt!KiSystemServiceRepeat 中找到SSDT的信息。

nt!KiSystemServiceRepeat:
fffff800`03c73ff2 4c8d1547782300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`03eab840)]
fffff800`03c73ff9 4c8d1d80782300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`03eab880)]
fffff800`03c74000 f7830001000080000000 test dword ptr [rbx+100h],80h
fffff800`03c7400a 4d0f45d3        cmovne  r10,r11
fffff800`03c7400e 423b441710      cmp     eax,dword ptr [rdi+r10+10h]
fffff800`03c74013 0f83e9020000    jae     nt!KiSystemServiceExit+0x1a7 (fffff800`03c74302)
fffff800`03c74019 4e8b1417        mov     r10,qword ptr [rdi+r10]
fffff800`03c7401d 4d631c82        movsxd  r11,dword ptr [r10+rax*4]

但是一个新的问题也同时产生了,nt!KiSystemServiceRepeat并不是系统的一个导出函数。那我怎么找到它呢?后来一想虽然它不导出但应该至少存在一条从外部到它的一个调用路径吧!那我就通过这条路径找到它不就行了。想到此就对它下了个断点看看都是谁会调用它。结果和我想的一样,不过发现我真是一个菜鸟,找到SSDT值太高兴竟没有仔细看它的汇编代码。nt!KiSystemServiceRepeat就是完成根据调用号从SSDT中获得服务例程入口并调用的。那就说每一个ZwXXX类的函数都会调用到它,而Zw类的函数是系统导出的这样我们可以通过任何一个Zw类的函数来找到nt!KiSystemServiceRepeat从而定位到SSDT。于是我手工尝试了一下。下面是尝试的过程。

kd> u nt!ZwClose l20
nt!ZwClose:
fffff800`03c6d640 488bc4          mov     rax,rsp
fffff800`03c6d643 fa              cli
fffff800`03c6d644 4883ec10        sub     rsp,10h
fffff800`03c6d648 50              push    rax
fffff800`03c6d649 9c              pushfq
fffff800`03c6d64a 6a10            push    10h
fffff800`03c6d64c 488d059d300000  lea     rax,[nt!KiServiceLinkage (fffff800`03c706f0)]
fffff800`03c6d653 50              push    rax
fffff800`03c6d654 b80c000000      mov     eax,0Ch
fffff800`03c6d659 e9e2670000      jmp     nt!KiServiceInternal (fffff800`03c73e40)
fffff800`03c6d65e 6690            xchg    ax,ax

在ZwClose中(其它类似)跳转到了nt!KiServiceInternal 我们再跟踪nt!KiServiceInternal

nt!KiServiceInternal:
fffff800`03c73e40 4883ec08        sub     rsp,8
fffff800`03c73e44 55              push    rbp
fffff800`03c73e45 4881ec58010000  sub     rsp,158h
fffff800`03c73e4c 488dac2480000000 lea     rbp,[rsp+80h]
fffff800`03c73e54 48899dc0000000  mov     qword ptr [rbp+0C0h],rbx
fffff800`03c73e5b 4889bdc8000000  mov     qword ptr [rbp+0C8h],rdi
fffff800`03c73e62 4889b5d0000000  mov     qword ptr [rbp+0D0h],rsi
fffff800`03c73e69 fb              sti
fffff800`03c73e6a 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]
fffff800`03c73e73 0f0d8bd8010000  prefetchw [rbx+1D8h]
fffff800`03c73e7a 0fb6bbf6010000  movzx   edi,byte ptr [rbx+1F6h]
fffff800`03c73e81 40887da8        mov     byte ptr [rbp-58h],dil
fffff800`03c73e85 c683f601000000  mov     byte ptr [rbx+1F6h],0
fffff800`03c73e8c 4c8b93d8010000  mov     r10,qword ptr [rbx+1D8h]
fffff800`03c73e93 4c8995b8000000  mov     qword ptr [rbp+0B8h],r10
fffff800`03c73e9a 4c8d1d3d010000  lea     r11,[nt!KiSystemServiceStart (fffff800`03c73fde)]
fffff800`03c73ea1 41ffe3          jmp     r11
fffff800`03c73ea4 666666666666660f1f840000000000 nop word ptr [rax+rax]
fffff800`03c73eb3 66666666660f1f840000000000 nop word ptr [rax+rax]

在这个函数中又跳转到了nt!KiSystemServiceStart,这里4c8d1d3d010000 这条指令需要参考一下x64汇编中有关Rex.w前缀及Mod r/m寻址方面的知识来解释这个偏移。在这里就是fffff800`03c73ea1+013d就是nt!KiSystemServiceStart入口地址。接下来再从这个地址开始反汇编。

nt!KiSystemServiceStart:
fffff800`03c73fde 4889a3d8010000  mov     qword ptr [rbx+1D8h],rsp
fffff800`03c73fe5 8bf8            mov     edi,eax
fffff800`03c73fe7 c1ef07          shr     edi,7
fffff800`03c73fea 83e720          and     edi,20h
fffff800`03c73fed 25ff0f0000      and     eax,0FFFh
nt!KiSystemServiceRepeat:
fffff800`03c73ff2 4c8d1547782300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`03eab840)]
fffff800`03c73ff9 4c8d1d80782300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`03eab880)]
fffff800`03c74000 f7830001000080000000 test dword ptr [rbx+100h],80h
fffff800`03c7400a 4d0f45d3        cmovne  r10,r11
fffff800`03c7400e 423b441710      cmp     eax,dword ptr [rdi+r10+10h]
fffff800`03c74013 0f83e9020000    jae     nt!KiSystemServiceExit+0x1a7 (fffff800`03c74302)
fffff800`03c74019 4e8b1417        mov     r10,qword ptr [rdi+r10]
fffff800`03c7401d 4d631c82        movsxd  r11,dword ptr [r10+rax*4]
fffff800`03c74021 498bc3          mov     rax,r11
fffff800`03c74024 49c1fb04        sar     r11,4
fffff800`03c74028 4d03d3          add     r10,r11
fffff800`03c7402b 83ff20          cmp     edi,20h
fffff800`03c7402e 7550            jne     nt!KiSystemServiceGdiTebAccess+0x49 (fffff800`03c74080)
fffff800`03c74030 4c8b9bb8000000  mov     r11,qword ptr [rbx+0B8h]

终于找到我们要找到函数了,4c8d1547782300,4c8d1d80782300根据这两条指令我就可以定位到SSDT的位置了。终于拨云见日了。这两条指令都加了REX.W前缀的根据具体字段的意义解释它就可找到SSDT,4c8d1547782300这条指令的64立即数寻址应该是fffff800`03c73ff9+237847这样来扩展,就是RIP+偏移。相类似4c8d1d80782300指令中的立即数应该被扩展成fffff800`03c74000+237880,通过DQ命令查看就是SSDT的内容。

kd> dq fffff800`03c74000+237880
fffff800`03eab880  fffff800`03c75b00 00000000`00000000
fffff800`03eab890  00000000`00000191 fffff800`03c7678c
fffff800`03eab8a0  fffff960`00111c00 00000000`00000000
fffff800`03eab8b0  00000000`0000033b fffff960`0011391c
fffff800`03eab8c0  00000000`7771fdd6 00000000`00000000
fffff800`03eab8d0  fffff800`00a01400 fffff800`00a013b0
fffff800`03eab8e0  00000000`00000002 00000000`00005bdb
fffff800`03eab8f0  00000000`00023f05 00000000`00000000

kd> dq nt!KeServiceDescriptorTableShadow
fffff800`03eab880  fffff800`03c75b00 00000000`00000000
fffff800`03eab890  00000000`00000191 fffff800`03c7678c
fffff800`03eab8a0  fffff960`00111c00 00000000`00000000
fffff800`03eab8b0  00000000`0000033b fffff960`0011391c
fffff800`03eab8c0  00000000`7771fdd6 00000000`00000000
fffff800`03eab8d0  fffff800`00a01400 fffff800`00a013b0
fffff800`03eab8e0  00000000`00000002 00000000`00005bdb
fffff800`03eab8f0  00000000`00023f05 00000000`00000000

两种方法找到位置一样。我这里的输出都针对WIN7 64位系统的调用,通过对2003进行调试发现这样的方法也适用。因为没有暂时没有其它版本操作系统。在其它操作系统上的适用性怎么样就无从知道了。个人推测XP,VISTA也应该差不多但需要事实证明。不过Win7与2003中SSDT表项内容略有不同,虽然都是四个节最后四位是例程的参数个数,但在2003上偏移的计算是SSDT基址+表项值&0xFFFFFFF0,而win7上则变成了SSDT基址+表项值>>4。如果HOOK表项还是要做一个分别对待。我是第一次发帖,大家轻拍啊。上面阐述如有错误请个位大侠多多指教,小弟不胜感激。
您需要登录后才可以回帖 登录 | 点击注册

本版积分规则

魔鬼作坊|易语言教程|易语言源码|易语言论坛|易语言视频教程| 论坛导航|免责申明|手机版||网站地图
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表魔鬼作坊立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2010-2019 All Right Reserved.
快速回复 返回顶部 返回列表