转载自http://www.javashuo.com/article/p-qeqnukdq-cv.htmlhtml
KIDofot大神函数
阅读目录(Content)工具
1、工具及壳介绍加密
使用工具:Ollydbg,PEID,ImportREC,LoadPE,IDA,Universal Import Fixer,OllySubScript
此篇是加密壳的第二篇,更详细的步骤和思考,请查看第一篇:手工脱壳之 未知加密壳 【IAT加密+混淆+花指令】
PESpin壳:
尝试ESP定律,但硬件断点未断下。
(缘由实际上是壳作了反调试,后面部分介绍)
API下断:
壳导入了LoadLibrary 和 GetProAddress,能够从API下手。
按照经验来讲,跟踪GDI32.dll的基地址。由于其它DLL,如kernel32.dll取出的函数,壳有可能用于本身的代码而非修复IAT。
跟踪GDI32的基地址。多观察寄存器窗口和堆栈窗口。
DLL导出表:
DLL INT:
DLL IAT:
DLL 序号表:
经过RVA取得函数名:
跟踪字符串,接下来可能有字符串循环。
函数名 首个字节跟0x53比。0x53 == ' S '。
并且每次的值都不同。可见是取对应字母开头的函数名。
查看首个H开头的函数名,下条件断点。
字符串在减小,疑似于计算哈希值,
预判:根据上一篇加密壳的经验,这样的循环可能跟哈希加密,IAT加密有关。
预操做:记录从DLL IAT取出函数地址的 指令地址 和 存放进exe IAT 指令的地址。
肯定循环的判断临界点,跳出循环,跟踪最后的结果。
目标1:寻取出DLL IAT的函数地址。
字符串循环条件临界点:
跳出循环,疑似哈希值。
交换寄存器。
的确是进行哈希值比较。
在条件成立的下一条指令下断点。
跟踪哈希值,获得取函数地址的指令地址。
取DLL IAT函数地址的指令地址 :
记录下一条指令地址:0x438F9F
目标2:寻 把DLL IAT函数地址 存放进 exe IAT 的指令地址。
此处还不知道exe IAT的位置,因此只能跟踪函数地址EAX了。
多观察带方括号 MOV [xxx], xxx 之类的指令。
代码中作了大量的混淆和花指令,以下,纯粹无心义的指令,干扰分析。
(混淆和花指令具体见后面部分)
记录PESpin壳特征:
【跳过0043933E循环到00439340】
0043933E 73 F6 JNB SHORT 06.00439336 00439340 8A47 FF MOV AL,BYTE PTR DS:[EDI-0x1]
记录壳的一些操做:
取API函数前部分字节,并判断。
对取出的字节 作一些操做。
最终拷贝进指定地址,数据窗口跟随反汇编看出点端倪。
推测壳是在 IAT引用 与 真正API调用 之间增长代码屏障,仍是带混淆的屏障。
这样作顺即可以对IAT进行加密,阻止ImportREC解析。
流程:偷取函数前部分字节,申请空间,制造混淆代码块。
CALL(IAT引用) ->> 内存代码(混淆) -->> API
如下跟踪证实推测正确:
再逐步取出字节。
构造混淆,IAT引用CALL进来就是这个样子。
【00439079要实现】
跳到0043910F.0043910F的地方被花指令挡住了,因此在00439109按1.
00439079 0F84 90000000 JE 06.0043910F
观察内存空间首地址0x200000。推测可能准备填入exe IAT。
由于混淆和花指令,不少仔细分析都会作无用功,不知哪条真那条假。因此要肯定目标,定点分析。
存进IAT指令:
存进exe IAT 指令的地址:
记录下一条指令地址:0x43918C
如今,存在IAT的位置的是 申请出来的内存地址,内存的地址 –>> API的地址。
查看数据窗口,仔细一看你会发现,IAT被重定向了。
API的地址用0隔开,这明显不是IAT结构,是壳本身创建的IAT,ImportREC没法解析。
用OD脚本修复内存地址为真正API地址
用Universal Import Fixer重建IAT
接着用ImportREC重建导入表。
接下来就是跳出修复IAT的循环,找到OEP了。
多注意 比较指令 和 远跳。
找OEP的过程,感受就是在"花"海里遨游~~.....
跨区段远跳,通常是跳到OEP。
OEP:
记录OEP地址:0x409486
查看调用模块:
IAT引用,有些加密,有些未加密。
可见在壳修复IAT时,有些函数地址并无作相关加密处理,直接放回去了。
这就意味着在存进exe IAT 的循环中,多了一条分支,这像是有意扰乱分析者的脚步。
找一块地址密集的地方,在首部,下硬件断点,跟踪分析出分支位置。
此处存进exe IAT的指令地址跟上一处的不一样,地址正好能够作为分支的条件判断。
记录分支指令:
跳过call下一条指令地址: 0x439101
特征码搜索:
在壳解密TEXT段后,能够按各个版本的编译器的OEP特征码,进行逐个搜索。
如:
VC++的OEP特征码:
55 8B EC 6A FF
若是作了OEP特征偷取,能够针对某一条OEP相关指令,对内存进行暴力搜索。
壳操做:利用SEH异常链清理硬件断点,进行反调试。
不少状况下,要么就硬件断点断不下,要么就断下的位置不正确。
怀疑硬件断点被清除了。
按经验,首先推测在异常处理里进行反调试。
OD取消忽略异常。
Shift+F9 忽略异常运行,总共触发9处异常,列出首几处。
第三处和第四处断在了同一个地方,但异常处理函数不一样。
方案:经过在后方异常点 设置硬件断点,来判断前方异常点的异常处理 是否作了反调试。
逐个排查,肯定是第3个异常点,清理了硬件断点。
查看异常处理函数,能够在反调试函数前下硬件执行断点。
这里为了进行更好的分析,在此处Dump下来,采用IDA分析。
的确是对Dr一、二、三、4清理为零了,而且对Dr六、7进行了操做。
反反调试:编写OD脚本时,下硬件断点在此函数,并去掉反调试指令。
记录地址:0x43AF59,NOP掉字节0x1A。
//清除全部硬件断点
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"
OD脚本修复加密:
使用Universal Import Fixer 重定向修复IAT表:
从上面的壳代码的运行地址能够看出,壳的代码是运行在最后一个区段的,能够推断最后一个区段是壳的区段。
当Dump下来的时候,最后一个区段就没用了,因此能够重定向到此区段。
再用ODDump,ImportREC新建导入表:
分析经验:
混淆:无心义的垃圾指令,干扰分析,干扰反汇编引擎,使指令产生多种解释。
花指令:无心义的大量跳转,干扰分析。
花指令块:无心义跳转。
跳转指令被截断。
混淆让反汇编出错。
下硬件读写断点,会难肯定上一条是什么指令。
混淆使一样意思的指令被肢解成多条。
一个混淆和花指令结合的循环,就是上面的字符串处理循环。
经过STC设置进位标志 和 CMC进位标志求补 控制跳转,花指令。
我的总结:
附件:
KID