红绡枫叶 发表于 2013-3-4 15:05

Zp1.3IAT调用代码加密脱壳(献给广大菜鸟们)

【文章作者】: 红绡枫叶
【作者邮箱】: a474528738@163.com
【软件名称】: 风云电话DDOS软件
【加壳方式】: ZProtect1.3
【保护方式】: IAT调用代码加密保护
【编写语言】: Delphi v7.0
【使用工具】: DiE64,OD,PeLoader....
【操作平台】: XP SP3
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
前言:
         这款软件采用的IAT调用代码加密对刚入门的菜鸟来说,难度大了一点。因为要修复它,不会脚本或
         pacth的人来说,很难。当然,这个版本低强度的加密对高手来说完全是小菜一碟。高手就免了,菜鸟
         可以看看。如果和我同是菜鸟你有兴趣脱壳,那先不要看我的脱文,自己试着解决,挑战一下自己,提高
         自己的脱壳水平!
          我会尽量过程详细的讲解。
          注:脱这个ZP的壳的时候,我的电脑中了病毒,感染了我的很多文件,我上传的这个软件可能有问题。
            最后我声明一点,我留下邮箱是希望和对技术感兴趣的人交流,对发来的求破求脱邮件,我一概
            不予理会。欢迎大家用邮件同我交流经验技术!
          正文开始.
先DiE查到编写语言是Delphi,这样脱壳时候心中就有了底。
OD载入:
0084B000 >64:8B3D 3000000>MOV EDI,DWORD PTR FS:
0084B007    8B7F 0C         MOV EDI,DWORD PTR DS:
0084B00A    8B7F 1C         MOV EDI,DWORD PTR DS:
0084B00D    8B3F            MOV EDI,DWORD PTR DS:
0084B00F    8B7F 08         MOV EDI,DWORD PTR DS:
0084B012    E8 00000000   CALL 0084B017
0084B017    5B            POP EBX
0084B018    81EB 17104000   SUB EBX,00401017
F7单步到0084B017,用ESP定律(难道你不知道?),一路F9,会弹出注册窗口,点继续试用,再F9,到达OEP:
005F6D38    55            PUSH EBP
005F6D39    8BEC            MOV EBP,ESP
005F6D3B    83C4 C0         ADD ESP,-40
005F6D3E    53            PUSH EBX
005F6D3F    56            PUSH ESI
005F6D40    33C0            XOR EAX,EAX
005F6D42    8945 C0         MOV DWORD PTR SS:,EAX
005F6D45    8945 C4         MOV DWORD PTR SS:,EAX
005F6D48    8945 C8         MOV DWORD PTR SS:,EAX
005F6D4B    8945 E4         MOV DWORD PTR SS:,EAX
005F6D4E    8945 E0         MOV DWORD PTR SS:,EAX
005F6D51    8945 DC         MOV DWORD PTR SS:,EAX
005F6D54    8945 E8         MOV DWORD PTR SS:,EAX
005F6D57    8945 EC         MOV DWORD PTR SS:,EAX
005F6D5A    B8 80645F00   MOV EAX,005F6480
005F6D5F    E8 7407E1FF   CALL 004074D8
005F6D64    33C0            XOR EAX,EAX
005F6D66    55            PUSH EBP
005F6D67    68 B06F5F00   PUSH 005F6FB0
005F6D6C    64:FF30         PUSH DWORD PTR FS:
005F6D6F    64:8920         MOV DWORD PTR FS:,ESP
005F6D72    8D55 EC         LEA EDX,DWORD PTR SS:
005F6D75    B8 F8206000   MOV EAX,006020F8
005F6D7A    E8 0D78F9FF   CALL 0058E58C
005F6D7F    8B55 EC         MOV EDX,DWORD PTR SS:
看到OEP处的代码没有,的确是Delphi语言的(不要说你一点都不熟悉Delphi语言程序入口),Zp壳不会对OEP
进行处理,它的重点是IAT,我们有必要查一查(如果你对IAT也不知道,那你先补习补习基础再来吧)。
我们进入它的第一个CALL   005F6D5F    E8 7407E1FF   CALL 004074D8 看看:
004074D8    53            PUSH EBX
004074D9    8BD8            MOV EBX,EAX
004074DB    33C0            XOR EAX,EAX
004074DD    A3 A4805F00   MOV DWORD PTR DS:,EAX
004074E2    6A 00         PUSH 0
004074E4    E8 2BFFFFFF   CALL 00407414《——————再进入
004074E9    A3 68F65F00   MOV DWORD PTR DS:,EAX
004074EE    A1 68F65F00   MOV EAX,DWORD PTR DS:
004074F3    A3 B0805F00   MOV DWORD PTR DS:,EAX

来到:
00407413    90            NOP
00407414- FF25 B4326000   JMP DWORD PTR DS:<---到了这里
0040741A    8BC0            MOV EAX,EAX
0040741C- E9 AB082900   JMP 00697CCC
00407421    90            NOP
00407422    8BC0            MOV EAX,EAX
00407424- E9 8B0B2900   JMP 00697FB4
00407429    90            NOP
0040742A    8BC0            MOV EAX,EAX
0040742C- E9 23142900   JMP 00698854
00407431    90            NOP

这里就是IAT调用跳转被处理了的地方,上下翻看,可以发现有两种加密方式:
第一种:
00407424- E9 8B0B2900   JMP 00697FB4
00407429    90            NOP
是E9??????0090型加密
第二种:
00407414- FF25 B4326000   JMP DWORD PTR DS:,

其实这种只有三处,还有两处是:
004013D8- FF25 14326000   JMP DWORD PTR DS:
004079D4- FF25 EC336000   JMP DWORD PTR DS:
在00407414- FF25 B4326000   JMP DWORD PTR DS:跟随可以到达:

00E33E10    8B4424 04       MOV EAX,DWORD PTR SS:
00E33E14    E8 57050000   CALL 00E34370<------进入
00E33E19    C2 0400         RETN 4

进入后来到:
00E34370    50            PUSH EAX
00E34371    FF15 6CC8E300   CALL DWORD PTR DS:               ; kernel32.GetModuleHandleA
00E34377    C3            RETN

哈,原来是调用GetModuleHandleA。可以发现,这三个都是调用GetModuleHandleA,于是我们手工解决了它们。

对第一种,我们先要找到它解密的地方。
我们在004079DC- E9 7F0B2900   JMP 00698560新建EIP,F7单步跟踪,可来到
00E4E734    9C            PUSHFD<——————在这步之后在命令行输入 hr esp(对ESP下断点)
00E4E735    E9 F7430000   JMP 00E52B31
00E4E73A    17            POP SS
之后F9,可以来到
00DF6A8E    C3            RETN<--------停在这里
00DF6A8F    68 6AD06979   PUSH 7969D06A
00DF6A94^ E9 6795FFFF   JMP 00DF0000
00DF6A99    000F            ADD BYTE PTR DS:,CL
00DF6A9B    B6 53         MOV DH,53

此时堆栈出现
0012FFC0   7C809A2Dkernel32.LocalAlloc<---------对应的是这句
0012FFC4   7C817077返回到 kernel32.7C817077
0012FFC8   7C930228ntdll.7C930228
原来它是跳向LocalAlloc函数,那这里00DF6A8E 就是解密完成后的地方了,现在我们写脚本修复。
var fi
var tmp
var oldeip
var oldesp
mov oldeip,eip      //脚本之后要还原EIP,ESP
mov oldesp,esp
mov fi,401000
bphws 00DF6A8E,"x"   //在解密处设置硬件断点

loop:
mov esp,oldesp
find fi,#E9??????0090#      //搜索E9??????0090型加密
cmp $RESULT,0
je exit
mov fi,$RESULT
GCIfi,TYPE
CMP$RESULT,50
JNZ loop
gci fi,DESTINATION         //修改指定地址的指令在搜索到的地址处获取目标地址
mov tmp,$RESULT
mov eip,fi
esto
mov tmp,                //把解密后的函数写向tmp变量
eval "jmp {tmp}"             //计算表达式,得到“jmp XXXXXXXXX”
asm fi,$RESULT                //将结果进行汇编,修改指定地址的指令
jmp loop

exit:
mov eip,oldeip
mov esp,oldesp
bphwc
ret

跑完脚本后,我们发现我们原先找到的IAT跳转加密处变成了:
00407414- FF25 B4326000   JMP DWORD PTR DS:; kernel32.GetModuleHandleA<------这里我们已经修复了的
0040741A    8BC0            MOV EAX,EAX
0040741C- E9 0C26407C   JMP kernel32.LocalAlloc
00407421    90            NOP
00407422    8BC0            MOV EAX,EAX
00407424- E9 B723407C   JMP kernel32.TlsGetValue
00407429    90            NOP
0040742A    8BC0            MOV EAX,EAX
0040742C- E9 3428407C   JMP kernel32.TlsSetValue
00407431    90            NOP

这样的IAT跳转可不行,因为你就算脱掉了,也不能在别的人的电脑上运行。这里介绍一种工具,专门解决这类
问题的:Universal Import Fixer (UIF) v1.2 FINAL。(你没用过这款工具?啧啧...)
打开工具,输入我们OD加载的程序ID,把那几个勾都打上,点击开始,于是,我们看到:

00407414- FF25 68004E01   JMP DWORD PTR DS:               ; kernel32.GetModuleHandleA
0040741A    8BC0            MOV EAX,EAX
0040741C- FF25 A8004E01   JMP DWORD PTR DS:               ; kernel32.LocalAlloc
00407422    8BC0            MOV EAX,EAX
00407424- FF25 BC004E01   JMP DWORD PTR DS:               ; kernel32.TlsGetValue
0040742A    8BC0            MOV EAX,EAX
0040742C- FF25 C0004E01   JMP DWORD PTR DS:               ; kernel32.TlsSetValue
00407432    8BC0            MOV EAX,EAX
00407434    50            PUSH EAX
看到了没有,帮我们都修理好了,哈哈,只剩下DUMP修复了!
于是我们兴高采烈地Dump,想到我以前脱掉的ZP1.4demo的壳,都会对资源进行处理(不知道的同志到论坛搜搜啦)
于是Dump的时候去掉了“paste header from disk(从磁盘粘贴PE文件头)”前面的勾
然后修复IAT,看到UIF的日志


74680000 至:746CC000

msctfime.ime
73640000 至:7366E000

===============================================================

输入表修复完成!

已修复的模块: 风起电话DDOS软件.exe
镜像基址:   00400000

IAT RVA : 010E0000
IAT 大小: 0000080C

正常的输入表函数: 3<-------这是我们手工修复的三个GetModuleHandleA函数
直接的输入表函数: 553
全部的输入表函数: 556

在修复IAT的时候,IAT RVA要填 010E0000,也就是UIF帮我们重建的RVA地址(在上面,还没看见?...)
填好后,点Get Imports,此时就不要点自动搜索了。修复IAT,我们兴奋地打开“修复好了”的程序,
咔嚓..心凉了半截,怎么出错了?
看到出错提示:“应用程序正常初始化(0xc0000005)失败。请单击确定,终止应用程序。”
傻了眼,怎么会初始化失败呢?看到初始化几个字,你想到了什么?对,多半是PE头出了问题。
也就是说,我们Dump的时候PE头不是从磁盘粘贴的,而我们得到的是残缺的PE头!那么只要我们从磁盘
粘贴PE头就可以了吧。但是,程序资源表必然是动过手脚的,怎么办呢?哈哈,这还不简单?我们现在得到的程序虽然PE头有问题,但我们资源表是好的啊,于是记下
资源表RVA :00229000
          SIZE:0006BF58
再重新Dump,此时要勾选“从磁盘粘贴PE头”。修复IAT后,修改资源表RVA,SIZE,保存。
运行。...哈哈,成功!
试练软件:http://pan.baidu.com/share/link?shareid=403882&uk=4280448916,当然,你也可以自己到网上搜索下载
--------------------------------------------------------------------------------
【版权声明】: 本文原创于红绡枫叶, 转载请注明作者并保持文章的完整, 谢谢!
                                                       2013年03月03日 下午 09:16:25

1002217709 发表于 2013-3-4 15:08

好经验,感谢分享

蓝色街灯 发表于 2013-3-4 15:58

菜鸟表示亚历山大呀

yejiaxi82 发表于 2013-3-4 16:06

学习了……

红绡枫叶 发表于 2013-3-4 16:17

蓝色街灯 发表于 2013-3-4 15:58 static/image/common/back.gif
菜鸟表示亚历山大呀

只是看起来很复杂而已,自己动手,还是比较简单的

小雨细无声 发表于 2013-3-4 19:25

很详细,谢谢大牛提供!

蓝色街灯 发表于 2013-3-4 20:55

红绡枫叶 发表于 2013-3-4 16:17 static/image/common/back.gif
只是看起来很复杂而已,自己动手,还是比较简单的

谢谢,努力学习争取能追寻大牛的脚步:lol

cszlxl 发表于 2013-3-4 21:12

好东西,学习一下,谢谢了。

jiaxcheng 发表于 2013-3-4 22:32

只会压缩壳,学点加密壳,试试看

wanwanle 发表于 2013-3-6 10:39

原创的教程支持下啰
页: [1]
查看完整版本: Zp1.3IAT调用代码加密脱壳(献给广大菜鸟们)