首页 » 技术分享 » 一篇学会脱壳——06.exe脱壳

一篇学会脱壳——06.exe脱壳

 

花指令混淆,IAT加密和反调试,是一个很好的教学练习壳,这里详细写下脱壳步骤。
壳的IAT加密原理:一般壳代码会申请一段堆空间,用来执行解密代码解密出来真正的API地址,把程序的IAT表改成申请的堆空间地址。程序在正常运行的时候CALL会到这个堆空间执行解密,这样才能正确获取API地址。壳相当于给程序套上了头箍。

对于IAT加密壳我们要找三个关键点:获取API函数地址位置、加密IAT位置(不是必须)、填充IAT位置。
我们的思路:在壳获取API函数地址时,把它偷走拷贝一份到变量中,当壳忙活一顿加密操作之后,准备填充加密后的地址(壳申请的堆空间)到IAT中时,我们把它给换成原来的API函数地址。这样,壳代码等于没加密。
实现方法:OD脚本。因为IAT加密是个工作量很大的循环,我们也只能写代码改变它。
在这里插入图片描述
首先拖进OD,发现稍微移动紫色光标,代码就会变形。
在这里插入图片描述
这是由于OD对数据和代码有多个解析结果导致的,遇到这种情况最好不要乱动,按ctrl+up键微调
F7一步,看到了popad,ESP下硬件断点先试试ESP定律吧,F9运行发现跑完了,于是就应该想到硬件断点可能被干掉了。
我们需要更详细的信息。

1.关闭OD的自动忽略异常功能
2.关闭OD中strongOD的skip some execptions(跳过某些异常)
在这里插入图片描述
F9跑起来,注意查看OD左下角断下来的原因。
为了查出究竟在哪个异常中我们的硬件断点被干掉了,需要每一次都要在异常的SEH链中前后下硬件断点,只要在异常SEH链前硬件断点还在,而后一个异常中硬件断点没了,就断不下来。这样说明这个异常中把硬件断点干掉了。
第一次访问违规 这时需要shift+f9忽略异常继续运行
第二次整数除零
在这里插入图片描述
第三次 特权指令
在这里插入图片描述
第四次 访问违规
在这里插入图片描述
通过前面的方法可以确信我们的硬件断点是在sti特权指令的SEH链中被干掉了

点击查看SEH链内函数信息
在这里插入图片描述

到了这一步我们可以确信脱壳有了很大一步突破,因为找到了干掉硬件断点的地方。看上图的代码特征,如果了解CONTEXT结构体的话,很容易看出这是清楚DR0——DR7设置的代码。
看下C++中CONTEXT结构的定义:
typedef struct
_CONTEXT {
DWORD ContextFlags; +0X00

DWORD  Dr0;                    +0X04
DWORD  Dr1;                    +0X08
DWORD  Dr2;                    +0X0C
DWORD  Dr3;                    +0X10
DWORD  Dr6;                    +0X14 
DWORD  Dr7;                    +0X18

FLOATING_SAVE_AREA FloatSave;
DWORD  SegGs;
DWORD  SegFs;
DWORD  SegEs;
DWORD  SegDs;

DWORD  Edi;
DWORD  Esi;
DWORD  Ebx;

DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
// MUST BESANITIZED

DWORD  EFlags;             // MUST BESANITIZED
DWORD  Esp;
DWORD  SegSs;
BYTE   ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];

} CONTEXT;

其中DR0-DR3调试地址寄存器设置的是四个硬件断点的地址,比如我们现在在0X401000处有一个硬件断点,那么DR0=0X401000,DR7是调试控制寄存器,控制对应硬件断点的模式、掌控全局断点与局部断点的开关。
显然这里把DR0-DR7全部置为0了,我们的硬件断点在这里被干掉了,不多说,nop掉。

在这里插入图片描述
delete键NOP掉,对应脚本 fill dwSEHAddr,1A,90 //fill填充的意思,1A代表73-59这些代码字节数,90是nop的机器码
在0X431F59这里下个硬件执行断点,注意不要下软件断点,因为这里会弹出如下界面:
在这里插入图片描述
1.保持下硬件断点的好习惯,硬件断点比软件断点更好用
2.把反调试已经找到了之后,还把设置还原成原来的默认忽略异常,OD调试要养成随手擦屁股的好习惯。但是要保留之前ESP定律下的硬件断点,因为我们还是要用ESP定律出壳的。
在这里插入图片描述
废话少说,下了硬件断点直接F9就到这里了,选中NOP,继续F9
在这里插入图片描述
来到了这里继续F7,OEP应该不远了。
在这里插入图片描述
柳暗花明又一村,突然就变正常了,这就是OEP了啊,因为这是典型的C++反汇编代码的开头。在这下硬件断点3。

接下来检查下IAT表有没有加密,因为IAT加密的话我们dump下来还是没法运行。
在这里插入图片描述
随便找一个FF15机器码的CALL,因为FF15是系统调用函数,可以找到IAT,而E8的CALL不行。右键跟随数据窗口。
在这里插入图片描述
IAT果然加密了,老规矩,右键-硬件写入断点,重新运行,捕捉到什么时候加密的IAT。此时硬件写入断点是硬件断点4。
当第二次断下来的时候,ctrl+up微调两次出现mov dword ptr ds:[edi],eax这种四字节写入操作的时候,可以判定这里是IAT填充的位置。
在这里插入图片描述
向下单步F7,应该很快就会去获取下一个系统函数的地址。不要F8,因为壳代码混淆太厉害,可能会跑飞。F7进入了一个循环中出不来了,并且右边一直有系统函数的ASCII码,分析代码
在这里插入图片描述
在这里插入图片描述
这里EBX值是9B25E,放在EDI中又加上Kernel32.dll的基址775C0000,得到了地址7765B25E,这是系统函数ActivateActCtx的导入函数名称地址。由此可见9B25E是导入函数名称NameOfFunctions的RVA。
cmp byte ptr ds:[edi],0x6c 判断首字母是不是小写L,如果不是继续找函数,是的话跳转,这里分析直接F4到下面找到了l的情况继续往下分析。(能遵循它规律,尽量不要改跳转)
在这里插入图片描述
第一个函数是lstract函数。我们继续F7发现花指令混淆的实在太厉害了,但是看右边寄存器值也是很有价值信息的。
在这里插入图片描述
接下来的循环在循环读取字符串,根据以往逆向经验,这里是计算或者拷贝,遇见循环不用怕,一直F4到跳转下面就行了,一会儿计算完毕,再F7又来到了红色代码。
在这里插入图片描述
分析代码,发现cmp eax,0xF9B697A2判断哈希值,打起十万个精神
在这里插入图片描述
这里右上角出现kernel32.lstrcatA时就证明这个地址就是获取系统函数地址的地方。和上面获取系统函数地址方法一样,它把取出来的RVA放到EAX存放的地址中,然后加上[ebp+0x40421E]kernel32的基地址,得到函数VA地址。

至此我们已经分析完了,把地址都记录下来,并写成OD脚本,就可以实现脱壳。
但是要提醒的是:思路是上面的思路,但是调试方法有很多种,比如刚开始就知道[ebp+0x40421E]存放的是kernel32的基地址时候,可以直接搜索机器码1E424000看看哪些地方又用到这个基地址。
2.我们在IAT加密的循环中可以使用RUN跟踪,从后往前寻找一些有用的信息,譬如7开头的就是系统函数地址,可以观察到438F9F这里一直都有EAX为77XXXXXX的地址。
3.写OD脚本并不难,可以用OdbgScript来调试脚本,熟练了以后直接改下地址就可以用了。



MOV dwSEHAddr, 0043AF59          
MOV dwGetProcAddress, 438f9f
MOV dwWriteIAT, 43918C
MOV dwOEP,00409486
MOV dwEAX,0

// 清除所有硬件断点
BPHWCALL
// 清除所有内存断点
BPMC
// 异常处理函数,清除硬件断点的地方
BPHWS dwSEHAddr, "x"
// 下断点
BPHWS dwGetProcAddress, "x"      //GetProcAddress 后面,保存 EAX
BPHWS dwWriteIAT, "x" // 填充 IAT 后面,将保存的 EAX 写入到[EDI]
// 在 OEP 处下硬件执行断点
BPHWS dwOEP, "x" // OEP,弹出信息框,成功到达 OEP


LOOP0:
RUN
CMP eip, dwSEHAddr
JNZ LOOP0
fill dwSEHAddr,1A,90 //NOP 10h 个字节  90是Nop的机器码
 size选中后下面提示大小
// F9
LOOP1:
RUN
CMP eip, dwGetProcAddress
JNZ JMP1
MOV dwEAX,eax
JMP LOOP1
JMP1:
CMP eip, dwWriteIAT
JNZ JMP2
MOV [edi],dwEAX
JMP LOOP1
JMP2:
CMP eip, dwOEP
JNZ LOOP1
MSG "到达 OEP,恭喜可以 dump 了!"


首先,感谢任何一个阅读,关注或点赞我博客的朋友!! 当然博客中的任何问题都欢迎大家随时指出! 欢迎有兴趣的人私信留下你的联系方式,我们可以一起沟通,一起学习哦!我的学习交流QQ群366469549。 再次感谢大家的支持!!! 我会再接再厉的!!!

转载自原文链接, 如需删除请联系管理员。

原文链接:一篇学会脱壳——06.exe脱壳,转载请注明来源!

0