实验环境
操作系统:Windows 7 旗舰版 Sp1工具:OllyDbg、CheatEngine 6.5
前言: 对于某P,我已经研究了将近4年时间,但一直没有把自己所知贡献过一丁点给大家,在这里我表示非常抱歉!
正文: 废话我就不多说了 直接进入正题,这次给大家贡献关于某P对硬件断点的保护是如何进行并且如何绕过的。 首先,过掉驱动层保护,开Ollydbg附加好某P保护的游戏,这里我就拿XF来做个演示
既然是硬件断点,那少不了跟异常打交道,附加好XF后直接跳到KiUserExceptionDispatcher(异常分发函数),发现如下图: 为什么他会在这里下一个HOOK? 因为异常发生后 会先经过驱动层 然后驱动层无法处理这个异常直接往下面抛 到了应用层后会直接走KiUserExceptionDispatcher(异常分发函数),所以某P在这里下HOOK是为了接管应用层所有异常 然后我们继续,先看下他自己给自己占的坑,如下图:
如图我们看到DR0、1、2、3全部都被下了断点,DR7=553(XP下面看到是455) 他既然占了坑 那肯定要产生异常 不然的话 做这个硬件断点占坑根本没必要! 所以我们跟进他在异常分发的HOOK: [Asm] 纯文本查看 复制代码101F8260 FC CLD101F8261 51 PUSH ECX101F8262 8B0C24 MOV ECX,DWORD PTR SS:[ESP]101F8265 51 PUSH ECX101F8266 8B0C24 MOV ECX,DWORD PTR SS:[ESP]101F8269 898C24 04000000 MOV DWORD PTR SS:[ESP+4],ECX101F8270 8B8C24 0C000000 MOV ECX,DWORD PTR SS:[ESP+C]101F8277 890C24 MOV DWORD PTR SS:[ESP],ECX101F827A 8B0C24 MOV ECX,DWORD PTR SS:[ESP]101F827D 898C24 04000000 MOV DWORD PTR SS:[ESP+4],ECX101F8284 53 PUSH EBX101F8285 8B9C24 04000000 MOV EBX,DWORD PTR SS:[ESP+4]101F828C 53 PUSH EBX101F828D 8B9C24 04000000 MOV EBX,DWORD PTR SS:[ESP+4]101F8294 899C24 08000000 MOV DWORD PTR SS:[ESP+8],EBX101F829B 8B8C24 10000000 MOV ECX,DWORD PTR SS:[ESP+10]101F82A2 898C24 04000000 MOV DWORD PTR SS:[ESP+4],ECX101F82A9 E9 F8440C00 JMP crossf_1.102BC7A6
因为这里是乱序(某P大多数代码都是乱序 基本上没有VM 所以很好分析),所以继续往下跟:
[Asm] 纯文本查看 复制代码102C48F2 8B1C24 MOV EBX,DWORD PTR SS:[ESP]102C48F5 899C24 04000000 MOV DWORD PTR SS:[ESP+4],EBX102C48FC 8B9C24 04000000 MOV EBX,DWORD PTR SS:[ESP+4]102C4903 891C24 MOV DWORD PTR SS:[ESP],EBX102C4906 8B1C24 MOV EBX,DWORD PTR SS:[ESP]102C4909 899C24 0C000000 MOV DWORD PTR SS:[ESP+C],EBX102C4910 8B9C24 04000000 MOV EBX,DWORD PTR SS:[ESP+4]102C4917 891C24 MOV DWORD PTR SS:[ESP],EBX102C491A 8F0424 POP DWORD PTR SS:[ESP]102C491D 5B POP EBX102C491E 9D POPFD102C491F E8 3F0FF7FF CALL crossf_1.10235863 ; 某P的异常处理函数,我们可以称之他为RtlDispatchException102C4924 50 PUSH EAX102C4925 8B0424 MOV EAX,DWORD PTR SS:[ESP]102C4928 50 PUSH EAX102C4929 8B0424 MOV EAX,DWORD PTR SS:[ESP]102C492C 898424 04000000 MOV DWORD PTR SS:[ESP+4],EAX102C4933 8B8424 04000000 MOV EAX,DWORD PTR SS:[ESP+4]102C493A 51 PUSH ECX
跟进这个CALL 我们继续:
[Asm] 纯文本查看 复制代码101EF52D 58 POP EAX101EF52E 58 POP EAX101EF52F 9C PUSHFD101EF530 50 PUSH EAX101EF531 8B0424 MOV EAX,DWORD PTR SS:[ESP]101EF534 310424 XOR DWORD PTR SS:[ESP],EAX101EF537 8B8424 0C000000 MOV EAX,DWORD PTR SS:[ESP+C]101EF53E 010424 ADD DWORD PTR SS:[ESP],EAX101EF541 58 POP EAX101EF542 9D POPFD101EF543 50 PUSH EAX101EF544 9C PUSHFD101EF545 33C0 XOR EAX,EAX101EF547 038424 04000000 ADD EAX,DWORD PTR SS:[ESP+4]101EF54E 9D POPFD101EF54F 8138 04000080 CMP DWORD PTR DS:[EAX],80000004 ; 判断异常是否为0x80000004(硬件断点异常)101EF555 8B8424 04000000 MOV EAX,DWORD PTR SS:[ESP+4]101EF55C 890424 MOV DWORD PTR SS:[ESP],EAX101EF55F 8F0424 POP DWORD PTR SS:[ESP]101EF562 E8 526D0000 CALL crossf_1.101F62B9
为什么要判断? 因为他自己占的坑需要处理,不然的话直接崩溃!
我们继续跟看他是如何处理这个异常的
[Asm] 纯文本查看 复制代码101EB857 C78424 04000000>MOV DWORD PTR SS:[ESP+4],crossf_1.0F0DA392 ; 上面那个异常地址判断我直接跑飞了 到了这里 这句代码的意思是修改当前EIP为0F0DA392101EB862 57 PUSH EDI101EB863 8BBC24 04000000 MOV EDI,DWORD PTR SS:[ESP+4]101EB86A 57 PUSH EDI101EB86B 8BBC24 04000000 MOV EDI,DWORD PTR SS:[ESP+4]101EB872 89BC24 08000000 MOV DWORD PTR SS:[ESP+8],EDI101EB879 8B9424 0C000000 MOV EDX,DWORD PTR SS:[ESP+C]101EB880 899424 04000000 MOV DWORD PTR SS:[ESP+4],EDX101EB887 8B9424 04000000 MOV EDX,DWORD PTR SS:[ESP+4]101EB88E 52 PUSH EDX101EB88F 8B1424 MOV EDX,DWORD PTR SS:[ESP]101EB892 899424 08000000 MOV DWORD PTR SS:[ESP+8],EDX101EB899 8BBC24 0C000000 MOV EDI,DWORD PTR SS:[ESP+C]101EB8A0 893C24 MOV DWORD PTR SS:[ESP],EDI101EB8A3 8B3C24 MOV EDI,DWORD PTR SS:[ESP]101EB8A6 89BC24 10000000 MOV DWORD PTR SS:[ESP+10],EDI101EB8AD 8BBC24 08000000 MOV EDI,DWORD PTR SS:[ESP+8]101EB8B4 50 PUSH EAX101EB8B5 E8 01000000 CALL crossf_1.101EB8BB
[Asm] 纯文本查看 复制代码1021FEF9 04 24 ADD AL,241021FEFB 59 POP ECX1021FEFC 9D POPFD1021FEFD FF15 1CF72C0F CALL DWORD PTR DS:[F2CF71C] ; 然后直接调用ZwContinue 这个异常就处理完毕了1021FF03 E9 E10B0100 JMP crossf_1.10230AE9
最近我看到很多人在问 为什么自己HOOK了异常分发函数 接管了所有异常 并且处理了ZwGetContextThread还是被检测到
这里我给你们一个答案:
1、替换了某P占的坑 从而某P自己下的断点没有触发 原来的代码直接往下执行 并没有实现某P自己用硬件断点做的JMP 所以会被检测。(继续往下执行的代码可能是直接往服务器发送数据请求封号 这里我没有往下分析)
解决方案:在某P下的4个断点位置自己直接写JMP 跳转到他异常分发处理后的EIP地址(如果怕CRC,可以直接修改游戏英文名称+base.dll这个文件 据我所知目前这个文件没有文件校验 修改了物理文件 CRC就不会报异常 因为他是直接根据文件内容来比对的)
2、有些线程某P是没有下断点的 但大部分都下了断点,如果是这样 那么在ZwGetContextThread这个函数处理的同时需要注意:清空某P的断点之前 记录好他在哪些线程下了断点 那些线程没下断点 ,他自己在Get的同时恢复之前的DR数据即可,还有就是需要在这里判断一下eax 有时候
没有Get成功的话 不要返回数据 不然一样被检测!
3、RtlDispatchException这里return的时候需要注意Context里面的DR寄存器也要还原成原来线程的DR 不然一样被检测!
按照上面处理方式来直接处理 某P对硬件断点的保护基本上就废了
本篇文章就到这里 希望大家可以对某P实现保护的方式建立起新的认识。
本文仅供技术研究,请勿用于商业用途!
如需转载 请注明原文出处:Poner Blog
原创:Poner
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |