检测一个软件话不多说,查看编程语言,C/C++
查看区段,发现多了一个区段
导入OD,MSG提示,有壳
进入OEP,看到这个直接ESP定理
我这里下了一个硬件断点
结果发现什么都没发生直接跑飞
估计有断点检测,查看日志
用最后一次异常法, 0x0047108E, 成功到达OEP
但是它是如何处理硬件断点的呢?若是我想用硬件断点呢?所以我决定查看它的反硬件断点的实现
一般反调试技术都是写在SEH,或者hook 系统API, 其中最常见的就是HOOK KiUserExceptionDispatcher 异常分发函数
对其下CC断点, 再对ESP定律下硬件访问断点
成功断下, 查看 [ESP + 0x4] 处, 其是储存硬件访问断点地址的结构体
发现当其运行指定CALL后,硬件断点的地址被清空
那么知道情况就好办了,我们可以编写OD脚本来实现越过检测
在这里需要知道, 在 KiUserExceptionDispatcher 函数入口处:
[ESP + 0x4] 地址内容开始后5个4字节是一个结构体, 其中后4个4字节存储的是硬件断点的地址
[ESP + 0x14] 存储的是当前异常的地址
[ESP + 0x4] + 0xB8 地址里存储的是异常处理完毕后要返回的用户空间代码地址
|
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
|
// 手动设置 KiUserExceptionDispatcher 入口点CC断点// ntdll.ZwContinue 还有这个位置// HengXi.orgvar 返回地址bphws 4271B5, "x"开始:eob 判断run判断:cmp eip,7C92E47Cje 删除硬件断点cmp eip,7C92E493je 设置CCcmp eip,返回地址je 设置硬件断点jmp 结果删除硬件断点:bphwc 4271B5jmp 开始设置CC:mov 返回地址,[esp]add 返回地址,0b8mov 返回地址,[返回地址]bp 返回地址jmp 开始设置硬件断点:bphws 4271B5, "x"jmp 开始结果:MSGYN "继续?"cmp $RESULT,1je 开始ret |
成功到达OEP
然后, 其实仔细的看下就会发现存在OEP窃取的情况
所以为了恢复OEP,我们需要寻找原始OEP的代码,在最后一次异常处对壳代码下内存访问断点
成功断下
在OEP处设置硬件执行断点
接下来我们利用Run跟踪来记录到达OEP之前的代码
(1)添加记录文件
(2)勾上所有异常忽略
(3)打开Run跟踪
(4)跟踪步入
等待3~4分钟, 到达OEP,数了一下将近一万行代码,我们搜索关键OEP字段:push ebp
或者手动排查,去除pushad/popad无用的花指令代码段
找到原OEP代码
获取硬编码, 将其粘贴到现OEP
将其Dump下来, 然后我们直接运行是无法打开的,需要修复IAT表
查看目标IAT表发现存在IAT重定位
我们先定位壳代码中重定位IAT表的代码
重新加载,在壳OEP处, 随便在IAT中找一个重定位地址, 这里是0x460974,利用之前的OD脚本下硬件写入断点
|
1
2
|
// 修改OD脚本bphws 4271B5, "x" 改写为 bphws 460974, "w" |
成功断下
观察发现此时的EAX是重定位的地址, [ESP – 0C] 位置恰巧是重定位系统函数的真实地址
于是利用OD的脚本修复IAT表的思路也就理清楚了
|
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
|
// 手动设置 KiUserExceptionDispatcher 入口点CC断点// ntdll.ZwContinue 还有这个位置// HengXi.orgvar 函数地址var 返回地址bphws 4743D5, "x"bphws 4271B5, "x"开始:eob 判断run判断:cmp eip,7C92E47Cje 删除硬件断点cmp eip,7C92E493je 设置CCcmp eip,返回地址je 设置硬件断点cmp eip, 4743D5je 修复IATjmp 结果删除硬件断点:bphwc 4743D5bphwc 4271B5jmp 开始设置CC:mov 返回地址,[esp]add 返回地址,0b8mov 返回地址,[返回地址]bp 返回地址jmp 开始设置硬件断点:bphws 4743D5, "x"bphws 4271B5, "x"jmp 开始修复IAT:cmp eax, 500000jg 开始mov 函数地址, [esp - 0C]mov [edi], 函数地址jmp 开始结果:MSGYN "继续?"cmp $RESULT,1je 开始ret |
修改成功, 重新Dump下来
但是通过Import REC发现一个无效的地址
在OD中查看, 发现是一处奇怪的函数调用
来到OEP处, 对46BD5B下CC断点
它迟早需要调用函数,进入到系统领空,所以设置Run跟踪条件
成功断下,找到其调用的函数
在Import REC中修改
发现还是打不开软件,导入OD查看发现OEP不对, 默认为 4271B5
修改OEP
修改成功然而双击还是没用
查看堆栈窗口
第一行第三列就是最后调用的函数的地方,也就是异常的地址
跟进来看似乎又是一个类似IAT表的跳转
然而现在 0x167054 内容为空, 所以触发了异常
我们在原程序中查看这个地址,发现是类似函数调用的代码,格式一致均为6字节一段调用
正巧这个跳转表代码也为6个字节
那我们只需要将这个所有6字节调用的代码覆盖现在跳转表即可
保存下来,成功运行
最后还要感谢恒大老师的教导



































