程序在附件中,后续会更新基于SEH的动态反调和动静结合的反调
学知识ing
该实例是利用异常机制检查PEB的BeingDebugged(+0x2)从而实现反调试
先大致运行和调试一下
就是弹出一个窗口
拖入x32dbg中进行调试
程序除了拖入之后在入口的断点处停下,再次F9的时候,会在如下地方停下,然后我们shift+F9,将程序发生的异常派发给程序自身处理
之后就会弹出窗口
可以发现这和我们之前正常运行时产生的代码不同(其实这是正常程序自己发生异常后,先调用了自生的SEH异常处理器处理的结果,在处理该异常的那个异常处理器中含有反调试代码,会造成程序有不同的结果)
使用PEview查看代码的入口点(是程序关键代码,不是EP)
得到为0x401000(对于exe来说一般这个默认的基地址是对的)
然后我们将程序拖入,从代码入口处开始分析(OD颜色好看些,这里就用OD吧)
首先这三行,是在安装SEH新的SEH异常处理器
先压入这一个SEH异常处理器的地址,然后再压入原先程序SEH链的第一个SEH处理器的地址,最后将esp栈顶地址设置为新的SEH链的首地址
再往下
这两行向地址0(非法地址)处写入1,触发了内存访问异常(0xC0000005)
再往下
这里是调用那个调试时弹出的窗口的代码
跳转到0x0040104D
这里是程序正常运行的时候调用的MessageBoxA弹出的窗口代码
前两行就是删除SEH链的第一个SEH异常处理器
弹出第一个异常处理器(_EXCEPTION_REGISTERATION_RECORD)结构体的第一个成员,即指向下一个SEH异常处理器的指针,然后add esp,0x4,删除了异常处理函数的地址
最后retn退出程序
这里就是安装的那个SEH异常处理器的异常处理函数
mov esi,dword ptr ss:[esp+0xC] 将异常处理函数第三个参数:指向CONTEXT结构体的指针mov给esi
mov eax,dword ptr fs:[0x30] 将PEB地址给eax
cmp byte ptr ds:[eax+0x2],0x1 将PEB的偏移为0x2的BeingDebugged成员和1进行比较
(如果是1代表在调试,如果是0代表没调试)
下面就分别对应调试了和没调试的两种情况
[esi+0xB8]这个就是CONTEXT结构体偏移0xB8的成员,代表的EIP
执行完这个异常之后,会返回程序的这个地址处继续执行
汇编至此分析完毕(其实就是一个安装SEH中的检测PEB.BeingDebugged的反调试)
将程序拖入,调试器会暂停在EP处,这里调试器暂停在EP处就是利用了int3(0xCC)
然后再次F9,直达那个内存访问异常处(程序处于调试状态,会将异常先派发给调试器处理,调试器会先暂停在异常地址处)
x32dbg和od都可以查看程序的SEH链
这里找到第一个SEH异常处理器(我们在代码入口处安装的那个),地址为0x40105A
我们分析汇编代码之后,在这个cmp的地方下个断点
让程序执行完 0040105E | 64:A1 30000000 | mov eax,dword ptr fs:[30]
之后我们将异常派发给程序之后,在断点处停下后,查看eax的值便可以得到PEB的地址
我们按shift+f9将异常派发给程序,然后就会停在第一个SEH异常处理函数我们下的断点处
查看eax的值
0x240000
内存窗口中跳转到PEB然后修改BeingDebugged(+0x2)的值
改为0即可
然后我们F9运行程序
就可以发现已经恢复到正常运行时弹出的窗口
00401000
$
68
5A104000
push static_s.
0040105A
00401005
.
64
:FF35
00000
>push dword ptr fs:[
0
]
0040100C
.
64
:
8925
00000
>mov dword ptr fs:[
0
],esp
00401000
$
68
5A104000
push static_s.
0040105A
00401005
.
64
:FF35
00000
>push dword ptr fs:[
0
]
0040100C
.
64
:
8925
00000
>mov dword ptr fs:[
0
],esp
栈如下:
(esp)原先seh首地址
0x0040105A
栈如下:
(esp)原先seh首地址
0x0040105A
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-5-2 23:35
被SYJ-Re编辑
,原因: