PESpin加密壳分析

转载自https://www.cnblogs.com/KIDofot/p/8641385.html

KIDofot大神

手工脱壳之 PESpin加密壳【SHE链硬件反调试】【IAT重定向】【混淆+花指令】

阅读目录(Content)

回到顶部

一、工具及壳介绍

使用工具:Ollydbg,PEID,ImportREC,LoadPE,IDA,Universal Import Fixer,OllySubScript

此篇是加密壳的第二篇,更详细的步骤和思考,请查看第一篇:手工脱壳之 未知加密壳 【IAT加密+混淆+花指令】

PESpin壳:

1341905-20180324204819353-1955130359.png

1341905-20180324204819823-51846296.png

回到顶部

二、脱壳之寻找OEP

1、硬件断点失效

尝试ESP定律,但硬件断点未断下。

(原因其实是壳做了反调试,后面部分介绍)

1341905-20180324204820181-349758070.png

1341905-20180324204820877-288925442.png

2、采用API断点+单步跟踪

API下断:

壳导入了LoadLibrary 和 GetProAddress,可以从API下手。

1341905-20180324204821917-1642084832.png

1341905-20180324204822735-1711554442.png

1341905-20180324204823093-1005137150.png

1341905-20180324204823548-1664822083.png

1341905-20180324204823952-1912617697.png

按照经验来说,跟踪GDI32.dll的基地址。因为其它DLL,如kernel32.dll取出的函数,壳有可能用于自己的代码而非修复IAT。

跟踪GDI32的基地址。多观察寄存器窗口堆栈窗口

1341905-20180324204824487-1211965995.png

1341905-20180324204824825-1526486127.png

DLL导出表:

1341905-20180324204825138-1995870757.png

1341905-20180324204825612-1637662379.png

DLL INT:

1341905-20180324204826187-744937809.png

1341905-20180324204826711-1626044425.png

DLL IAT:

1341905-20180324204827214-1522824596.png

1341905-20180324204827794-1681008667.png

DLL 序号表:

1341905-20180324204828427-662160114.png

1341905-20180324204829154-970283136.png

通过RVA取得函数名:

1341905-20180324204829523-1727006967.png

1341905-20180324204829973-337385904.png

1341905-20180324204830572-918332727.png

跟踪字符串,接下来可能有字符串循环。

1341905-20180324204831101-695152137.png

函数名 首个字节跟0x53比。0x53 == ' S '。

1341905-20180324204831753-1665792427.png

1341905-20180324204832148-1207658317.png

而且每次的值都不一样。可见是取对应字母开头的函数名。

1341905-20180324204834048-636621024.png

1341905-20180324204835035-770579018.png

查看首个H开头的函数名,下条件断点。

1341905-20180324204835479-1970078681.png

1341905-20180324204835880-796244561.png

1341905-20180324204836446-1822721946.png

1341905-20180324204836777-152115779.png

字符串在减少,疑似于计算哈希值,

预判:根据上一篇加密壳的经验,这样的循环可能跟哈希加密,IAT加密有关。

预操作:记录从DLL IAT取出函数地址的 指令地址 和 存放进exe IAT 指令的地址。

3、确定目标

确定循环的判断临界点,跳出循环,跟踪最后的结果。

3.1、API Address

目标1:寻取出DLL IAT的函数地址。

字符串循环条件临界点:

1341905-20180324204840878-263633932.png

跳出循环,疑似哈希值。

1341905-20180324204842867-209513949.png

交换寄存器。

1341905-20180324204844717-222546055.png

的确是进行哈希值比较。

1341905-20180324204845709-1592077936.png

在条件成立的下一条指令下断点。

1341905-20180324204846997-699398297.png

跟踪哈希值,得到取函数地址的指令地址

1341905-20180324204849206-2079223793.png

取DLL IAT函数地址的指令地址 :

记录下一条指令地址:0x438F9F

3.2、Put EXE IAT

目标2:寻 把DLL IAT函数地址 存放进 exe IAT 的指令地址。

此处还不知道exe IAT的位置,所以只能跟踪函数地址EAX了。

多观察带方括号 MOV [xxx], xxx 之类的指令。

代码中做了大量的混淆和花指令,如下,纯粹无意义的指令,干扰分析。

(混淆和花指令具体见后面部分)

1341905-20180324204850755-1220835147.png

记录PESpin壳特征:

1341905-20180324204855088-1158027878.png

【跳过0043933E循环到00439340】

0043933E 73 F6 JNB SHORT 06.00439336 00439340 8A47 FF MOV AL,BYTE PTR DS:[EDI-0x1]

记录壳的一些操作:

取API函数前部分字节,并判断。

1341905-20180324204856874-1978403865.png

1341905-20180324204858542-1621574686.png

对取出的字节 做一些操作。

1341905-20180324204859423-2088510902.png

1341905-20180324204900002-658443642.png

1341905-20180324204900553-1948943091.png

最终拷贝进指定地址,数据窗口跟随反汇编看出点端倪。

1341905-20180324204902533-1944111065.png

1341905-20180324204903384-183102102.png

1341905-20180324204903743-1912241245.png

1341905-20180324204904262-1953019372.png

推测壳是在 IAT引用真正API调用 之间增加代码屏障,还是带混淆的屏障。

这样做顺便可以对IAT进行加密,阻止ImportREC解析。

3.3、IAT加密

流程:偷取函数前部分字节,申请空间,制造混淆代码块。

CALL(IAT引用) ->> 内存代码(混淆) -->> API

以下跟踪证明推测正确:

再逐步取出字节。

1341905-20180324204906076-1675466177.png

1341905-20180324204907892-439532184.png

1341905-20180324204910662-112852233.png

构造混淆,IAT引用CALL进来就是这个样子。

1341905-20180324204912264-1518578743.png

1341905-20180324204913114-1182157467.png

1341905-20180324204913634-2057141584.png

【00439079要实现】

跳到0043910F.0043910F的地方被花指令挡住了,所以在00439109按1.

00439079 0F84 90000000 JE 06.0043910F

1564839729869

观察内存空间首地址0x200000。推测可能准备填入exe IAT。

因为混淆和花指令,很多仔细分析都会做无用功,不知哪条真那条假。所以要确定目标,定点分析。

存进IAT指令:

1341905-20180324204914266-1078660219.png

1341905-20180324204914660-1142459188.png

存进exe IAT 指令的地址:

记录下一条指令地址:0x43918C

3.4、IAT重定向

现在,存在IAT的位置的是 申请出来的内存地址,内存的地址 –>> API的地址。

查看数据窗口,仔细一看你会发现,IAT被重定向了

1341905-20180324204915863-1871780923.png

API的地址用0隔开,这明显不是IAT结构,是壳自己建立的IAT,ImportREC无法解析。

3.5、IAT重定向解决方案:
  1. 用OD脚本修复内存地址为真正API地址

  2. 用Universal Import Fixer重建IAT

  3. 接着用ImportREC重建导入表。

3.6、OEP

接下来就是跳出修复IAT的循环,找到OEP了。

多注意 比较指令 和 远跳。

找OEP的过程,感觉就是在"花"海里遨游~~.....

1341905-20180324204917323-519179365.png

跨区段远跳,一般是跳到OEP。

1341905-20180324204919136-1943717219.png

1341905-20180324204920163-947260553.png

OEP:

1341905-20180324204921185-1526770663.png

1341905-20180324204921705-2029000730.png

记录OEP地址:0x409486

3.7、记录分支

查看调用模块:

1341905-20180324204923774-632231555.png

IAT引用,有些加密,有些未加密。

可见在壳修复IAT时,有些函数地址并没有做相关加密处理,直接放回去了。

这就意味着在存进exe IAT 的循环中,多了一条分支,这像是有意扰乱分析者的脚步。

找一块地址密集的地方,在首部,下硬件断点,跟踪分析出分支位置。

1341905-20180324204924313-425499427.png

1341905-20180324204926644-750486939.png

1341905-20180324204927405-1806817504.png

1341905-20180324204927894-2123158143.png

此处存进exe IAT的指令地址跟上一处的不同,地址正好可以做为分支的条件判断。

记录分支指令:

跳过call下一条指令地址: 0x439101

回到顶部

四、快速定位OEP

特征码搜索:

在壳解密TEXT段后,可以按各个版本的编译器的OEP特征码,进行逐个搜索。

如:

VC++的OEP特征码:

55 8B EC 6A FF

1341905-20180324204928540-703931324.png

如果做了OEP特征偷取,可以针对某一条OEP相关指令,对内存进行暴力搜索。

回到顶部

五、 SEH异常链反调试

壳操作:利用SEH异常链清理硬件断点,进行反调试。

很多情况下,要么就硬件断点断不下,要么就断下的位置不正确。

怀疑硬件断点被清除了。

按经验,首先推测在异常处理里进行反调试。

OD取消忽略异常。

1341905-20180324204929157-1438680002.png

1341905-20180324204929640-1595451813.png

Shift+F9 忽略异常运行,总共触发9处异常,列出首几处。

1341905-20180324204930077-2045145981.png

1341905-20180324204930575-1981227551.png

1341905-20180324204930948-980443924.png

1341905-20180324204931334-1943916342.png

1341905-20180324204931812-1105769183.png

第三处第四处断在了同一个地方,但异常处理函数不同。

1341905-20180324204932106-495744572.png

1341905-20180324204932513-1556649527.png

方案:通过在后方异常点 设置硬件断点,来判断前方异常点的异常处理 是否做了反调试。

逐个排查,确定是第3个异常点,清理了硬件断点。

1341905-20180324204932806-1471044438.png

查看异常处理函数,可以在反调试函数前下硬件执行断点。

1341905-20180324204934117-667384778.png

这里为了进行更好的分析,在此处Dump下来,采用IDA分析。

1341905-20180324204934709-1084975243.png

1341905-20180324204936059-1716045188.png

的确是对Dr1、2、3、4清理为零了,并且对Dr6、7进行了操作。

反反调试:编写OD脚本时,下硬件断点在此函数,并去掉反调试指令。

记录地址:0x43AF59,NOP掉字节0x1A。

回到顶部

六、OD脚本及修复

copycode.gif

//清除所有硬件断点

BPHWC

//清除所有软件断点

BC

//清除所有内存断点

BPMC

  

//IAT地址

VAR IATAddress

  

//OEP断点

BPHWS 409486,"x"

//取IAT指令

BPHWS 438F9F,"x"

//存IAT指令

BPHWS 43918C,"x"

//硬件反调试代码

BPHWS 43AF59,"x"

  

_LOOP:


RUN


//去掉硬件反调试代码

cmp eip,43AF59

JNZ _Sign1

fill 43AF59,1A,90

//清除反调试硬件断点

BPHWC 43AF59


_Sign1:

  
//取IAT判断

CMP eip,438F9F

JNZ _Sign2

  
MOV IATAddress,eax

  
_Sign2:

  

//分支判断

CMP eip,439101

JNZ _Sign3

//不作操作

BPHWS 43AF59,"x"


_Sign3:

  

//存IAT的地方

CMP eip,43918C

JNZ _Sign4

  
MOV [edi],IATAddress


_Sign4:


//OEP

CMP eip,409486

JNZ _LOOP

  

MSG "到达OEP"

copycode.gif

OD脚本修复加密:

1341905-20180324204936545-673420731.png

使用Universal Import Fixer 重定向修复IAT表:

从上面的壳代码的运行地址可以看出,壳的代码是运行在最后一个区段的,可以推断最后一个区段是壳的区段。

当Dump下来的时候,最后一个区段就没用了,所以可以重定向到此区段。

1341905-20180324204937153-686339945.png

1341905-20180324204938187-1411198777.png

再用ODDump,ImportREC新建导入表:

1341905-20180324204938690-232099927.png

1341905-20180324204939748-1087289761.png

回到顶部

七、脱壳成功

1341905-20180324204940179-2115204796.png

1341905-20180324204940663-1182137185.png

回到顶部

八、混淆花指令

分析经验:

混淆:无意义的垃圾指令,干扰分析,干扰反汇编引擎,使指令产生多种解释。

花指令:无意义的大量跳转,干扰分析。

花指令块:无意义跳转。

1341905-20180324204941693-914437436.png

1341905-20180324204942173-1119735785.png

1341905-20180324204942647-1960076233.png

跳转指令被截断。

1341905-20180324204943660-807402889.png

混淆让反汇编出错。

1341905-20180324204944204-763455274.png

1341905-20180324204944748-348189165.png

下硬件读写断点,会难确定上一条是什么指令。

1341905-20180324204945261-1327910614.png

1341905-20180324204945671-1601731470.png

混淆使同样意思的指令被肢解成多条。

1341905-20180324204946226-1687805283.png

一个混淆和花指令结合的循环,就是上面的字符串处理循环。

1341905-20180324204947154-641378624.png

通过STC设置进位标志 和 CMC进位标志求补 控制跳转,花指令。

1341905-20180324204948013-75725724.png

1341905-20180324204948979-1305849989.png

个人总结:

附件:

PESpin加密壳

KID

转载于:https://www.cnblogs.com/ltyandy/p/11296454.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值