【脱文作者】 weiyi75[Dfcg]
【作者邮箱】 weiyi75@sohu.com
【作者主页】 Dfcg官方大本营
【使用工具】 Ollydbg1.10b,ImportREC1.6F,LoadPe
【破解平台】 Win2000/XP
【软件名称】 PE文件分析器
【下载地址】 原程序
http://bbs2.pediy.com/download.php?id=1514
【下载地址】 加密程序
http://bbs2.pediy.com/download.php?id=1513
【软件简介】 ASProtect 1.23 RC4 Registered版本加密的一个PE文件分析器。
【软件大小】 453K
【加壳方式】 ASProtect 1.23 RC4 - 1.3.08.24 -> Alexey Solodovnikov
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享。
【破解目的】 模拟跟踪寻找Stolen Code具体内容或Oep入口。
前言,这个软件是我用ASProtect 1.23 RC4 Registered版本加密的,使用了所有反跟踪选项。
先OD载入原程序看看
004B7220 > $ 55 PUSH EBP //典型Dephi语言入口点
004B7221 . 8BEC MOV EBP,ESP
004B7223 . 83C4 F0 ADD ESP,-10
004B7226 . B8 A86F4B00 MOV EAX,Pe.004B6FA8
004B722B . E8 6CF4F4FF CALL Pe.0040669C
004B7230 . A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B7235 . 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B7237 . E8 C48CFCFF CALL Pe.0047FF00
004B723C . A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B7241 . 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B7243 . BA 80724B00 MOV EDX,Pe.004B7280
004B7248 . E8 AB88FCFF CALL Pe.0047FAF8
004B724D . 8B0D F4A14B00 MOV ECX,DWORD PTR DS:[4BA1F4] ; Pe.004BBCAC
004B7253 . A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B7258 . 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B725A . 8B15 48E44A00 MOV EDX,DWORD PTR DS:[4AE448] ; Pe.004AE494
004B7260 . E8 B38CFCFF CALL Pe.0047FF18
..........................................................................................
寄存器EBP=0012FFF0 //这是程序停在入口点EBP的值,其它Dephi语言或编程语言这里的EBP值全部相同,这又说明什么,当Asprotect运行到这里或Stolen Code时EBP的值就为EBP=0012FFF0,我们来具体试试。
OD异常设置不忽略内存异常,其余全部忽略,载入程序,用插件隐藏OD。
00401000 > 68 01F04E00 PUSH Pej.004EF001 //加壳程序入口点,F9运行
00401005 E8 01000000 CALL Pej.0040100B
0040100A C3 RETN
0040100B C3 RETN
0040100C 9A 7FCE25CC 76C>CALL FAR CE76:CC25CE7F ; 远距呼叫
00401013 FA CLI
00401014 0C 55 OR AL,55
00401016 6C INS BYTE PTR ES:[EDI],DX ; I/O 命令
00401017 D0DC RCR AH,1
00401019 25 4B551335 AND EAX,3513554B
0040101E 45 INC EBP
0040101F BC B431C8D3 MOV ESP,D3C831B4
00401024 73 66 JNB SHORT Pej.0040108C
00401026 5C POP ESP
00401027 21E2 AND EDX,ESP
00401029 04 04 ADD AL,4
0040102B 7C 0C JL SHORT Pej.00401039
0040102D - 75 AB JNZ SHORT Pej.00400FDA
0040102F 2B4415 15 SUB EAX,DWORD PTR SS:[EBP+EDX+15]
00401033 826D 84 F0 SUB BYTE PTR SS:[EBP-7C],-10
00401037 CA 5FD0 RETF 0D05F ; 远距返回
........................................................................
内存异常
00DB41A4 3100 XOR DWORD PTR DS:[EAX],EAX
00DB41A6 EB 01 JMP SHORT 00DB41A9
00DB41A8 68 648F0500 PUSH 58F64
00DB41AD 0000 ADD BYTE PTR DS:[EAX],AL
00DB41AF 00EB ADD BL,CH
00DB41B1 02E8 ADD CH,AL
00DB41B3 0158 68 ADD DWORD PTR DS:[EAX+68],EBX
00DB41B6 6C INS BYTE PTR ES:[EDI],DX ; I/O 命令
00DB41B7 AF SCAS DWORD PTR ES:[EDI]
00DB41B8 DA00 FIADD DWORD PTR DS:[EAX]
00DB41BA 68 1442DB00 PUSH 0DB4214
00DB41BF 68 8836DB00 PUSH 0DB3688
00DB41C4 68 5033DB00 PUSH 0DB3350
00DB41C9 68 002DDB00 PUSH 0DB2D00
00DB41CE 68 BC26DB00 PUSH 0DB26BC
00DB41D3 68 4C3ADB00 PUSH 0DB3A4C
00DB41D8 C3 RETN
........................................................................
继续Shift+F9 25次来到Asprotect典型的最后一次异常。
00DB39EC 3100 XOR DWORD PTR DS:[EAX],EAX //特征码
00DB39EE 64:8F05 0000000>POP DWORD PTR FS:[0]
00DB39F5 58 POP EAX
00DB39F6 833D B07EDB00 0>CMP DWORD PTR DS:[DB7EB0],0
00DB39FD 74 14 JE SHORT 00DB3A13
00DB39FF 6A 0C PUSH 0C
00DB3A01 B9 B07EDB00 MOV ECX,0DB7EB0
00DB3A06 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
00DB3A09 BA 04000000 MOV EDX,4
00DB3A0E E8 2DD1FFFF CALL 00DB0B40
00DB3A13 FF75 FC PUSH DWORD PTR SS:[EBP-4]
00DB3A16 FF75 F8 PUSH DWORD PTR SS:[EBP-8]
00DB3A19 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
00DB3A1C 8338 00 CMP DWORD PTR DS:[EAX],0
00DB3A1F 74 02 JE SHORT 00DB3A23
00DB3A21 FF30 PUSH DWORD PTR DS:[EAX]
00DB3A23 FF75 F0 PUSH DWORD PTR SS:[EBP-10]
00DB3A26 FF75 EC PUSH DWORD PTR SS:[EBP-14]
00DB3A29 C3 RETN //这里下断点,Shift+F9中断后取消断点。
........................................................................
我这次没有用内存镜像断点到OEP,下面的这个方法可以发现Stolen Code(如果有)+Oep二合一。
仍然是命令行断点
tc ebp==12fff0 //当前EBP内容为12fff0就被中断,略微看看就可以找到Stolen Code(如果有)或Oep
00DC6348 /EB 02 JMP SHORT 00DC634C //一会就来到这里,呵呵,C++语言就开始有Stolen Code,而且略有变形,往下全部用F7步过,转标签1
00DC634A |CD 20 INT 20
00DC634C F2: PREFIX REPNE: //这样的语句其实是一些变形Jmp ; 多余的前缀
00DC634D EB 01 JMP SHORT 00DC6350
00DC634F - E9 65EB01E9 JMP E9DE4EB9
00DC6354 68 91AA7FAE PUSH AE7FAA91
00DC6359 6A 2A PUSH 2A
00DC635B 897C24 04 MOV DWORD PTR SS:[ESP+4],EDI
00DC635F F2: PREFIX REPNE: ; 多余的前缀
00DC6360 EB 01 JMP SHORT 00DC6363
00DC6362 9A 8D642404 F3E>CALL FAR EBF3:0424648D ; 远距呼叫
00DC6369 02CD ADD CL,CH
00DC636B 20F2 AND DL,DH
00DC636D EB 01 JMP SHORT 00DC6370
00DC636F C7 ??? ; 未知命令
00DC6370 0FCF BSWAP EDI
00DC6372 EB 02 JMP SHORT 00DC6376
........................................................................
标签1
00DC634C F2: PREFIX REPNE: ; 多余的前缀
00DC6350 /65:EB 01 JMP SHORT 00DC6354 ; 多余的前缀
00DC6354 68 91AA7FAE PUSH AE7FAA91
00DC6359 6A 2A PUSH 2A
00DC635B 897C24 04 MOV DWORD PTR SS:[ESP+4],EDI
00DC635F F2: PREFIX REPNE: ; 多余的前缀
00DC6363 8D6424 04 LEA ESP,DWORD PTR SS:[ESP+4]
00DC6367 F3: PREFIX REP: ; 多余的前缀
00DC6368 EB 02 JMP SHORT 00DC636C
00DC636C F2: PREFIX REPNE: ; 多余的前缀
00DC6370 0FCF BSWAP EDI
00DC6372 EB 02 JMP SHORT 00DC6376
00DC6376 F2: PREFIX REPNE: ; 多余的前缀
00DC637A FF7424 07 PUSH DWORD PTR SS:[ESP+7]
00DC637E 36:EB 01 JMP SHORT 00DC6382 ; 多余的前缀
00DC6382 68 6C63DC00 PUSH 0DC636C
00DC6387 F2: PREFIX REPNE: ; 多余的前缀
00DC638B 8F4424 00 POP DWORD PTR SS:[ESP] ; 00DC636C
00DC638F 5F POP EDI
00DC6390 FF57 28 CALL DWORD PTR DS:[EDI+28]
00DC639D 5F POP EDI ; 00DC6393
00DC639E 26:EB 01 JMP SHORT 00DC63A2 ; 多余的前缀
00DC63A2 81E7 E50A9E59 AND EDI,599E0AE5
00DC63A8 F2: PREFIX REPNE: ; 多余的前缀
00DC63AC C1E7 E1 SHL EDI,0E1 ; 移动常数超出 1..31 的范围
00DC63AF EB 01 JMP SHORT 00DC63B2
00DC63B2 C1EF D6 SHR EDI,0D6 ; 移动常数超出 1..31 的范围
00DC63B5 5F POP EDI
00DC63B6 F2: PREFIX REPNE: ; 多余的前缀
00DC63BA 8D6424 F7 LEA ESP,DWORD PTR SS:[ESP-9]
00DC63BE 66:8135 C763DC0>XOR WORD PTR DS:[DC63C7],0AA91
00DC63C7 7A AB JPE SHORT 00DC6374
00DC63C7 /EB 01 JMP SHORT 00DC63CA
00DC63CA 8D6424 42 LEA ESP,DWORD PTR SS:[ESP+42]
00DC63CE 8D6424 C3 LEA ESP,DWORD PTR SS:[ESP-3D]
00DC63D2 66:8135 DB63DC0>XOR WORD PTR DS:[DC63DB],0D71A
00DC63DB F3: PREFIX REP: ; 多余的前缀
00DC63E0 55 PUSH EBP //Stolen Code第一句。
00DC63E1 66:8135 EB63DC0>XOR WORD PTR DS:[DC63EB],80A3
00DC63EA F2: PREFIX REPNE: ; 多余的前缀
00DC63EE 8F4424 00 POP DWORD PTR SS:[ESP] ; 0012FFF0
00DC63F2 8BEC MOV EBP,ESP 执行完它后,EBP=ESP=12FFC0,打破了从跟踪到这里EBP的值一直为12fff0的情况,同时也让我们也可以知道入口代码就在附近。Stolen Code第二句。
00DC63F4 81EC 10000000 SUB ESP,10 Stolen Code第三句,这句要改为ADD ESP,10 标准化。
00DC63FA F2: PREFIX REPNE: ; 多余的前缀
00DC63FE /65:EB 01 JMP SHORT 00DC6402 ; 多余的前缀
00DC6402 51 PUSH ECX
00DC6403 /EB 04 JMP SHORT 00DC6409
................................................................
后面有无数条小跳转,全部都是垃圾,我跟踪了40分钟,还没走完,已经吐血了。
所以Dephi程序最好先确定Stolen Code数目。
004B7220 > $ 55 PUSH EBP
004B7221 . 8BEC MOV EBP,ESP
004B7223 . 83C4 F0 ADD ESP,-10
004B7226 . B8 A86F4B00 MOV EAX,Pe.004B6FA8
这个程序一共抽掉11字节。
前面三句我们已经得到,现在的问题是MOV EAX,xxxxxxxx
EAX的值是多少?
ALT+M 打开内存镜像。
内存镜像, 项目 12
地址=00401000 //对401000 Code段下内存断点。
大小=000B7000 (749568.)
Owner=Pej 00400000
区段=
Contains=code
类型=Imag 01001002
访问=R
初始访问=RWE
004065D8 - FF25 58C24B00 JMP DWORD PTR DS:[4BC258] //中断在这里,清除内存断点。
004065DE 8BC0 MOV EAX,EAX
004065E0 - FF25 54C24B00 JMP DWORD PTR DS:[4BC254]
004065E6 8BC0 MOV EAX,EAX
004065E8 - FF25 50C24B00 JMP DWORD PTR DS:[4BC250]
004065EE 8BC0 MOV EAX,EAX
004065F0 - FF25 4CC24B00 JMP DWORD PTR DS:[4BC24C]
004065F6 8BC0 MOV EAX,EAX
004065F8 50 PUSH EAX
004065F9 6A 40 PUSH 40
004065FB E8 E0FFFFFF CALL Pej.004065E0
00406600 C3 RETN
....................................................
00DB1C64 55 PUSH EBP //F8返回壳中。
00DB1C65 8BEC MOV EBP,ESP
00DB1C67 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00DB1C6A 85C0 TEST EAX,EAX
00DB1C6C 75 13 JNZ SHORT 00DB1C81
00DB1C6E 813D A47ADB00 0>CMP DWORD PTR DS:[DB7AA4],400000 ; ASCII "MZP"
00DB1C78 75 07 JNZ SHORT 00DB1C81
00DB1C7A A1 A47ADB00 MOV EAX,DWORD PTR DS:[DB7AA4]
00DB1C7F EB 06 JMP SHORT 00DB1C87
00DB1C81 50 PUSH EAX
00DB1C82 E8 3135FFFF CALL 00DA51B8 ; JMP to kernel32.GetModuleHandleA
00DB1C87 5D POP EBP
00DB1C88 C2 0400 RETN 4 //Ctrl+F9返回。
......................................................
004066AD A3 68B64B00 MOV DWORD PTR DS:[4BB668],EAX ; Pej.00400000
004066B2 A1 68B64B00 MOV EAX,DWORD PTR DS:[4BB668]
004066B7 A3 AC804B00 MOV DWORD PTR DS:[4B80AC],EAX
004066BC 33C0 XOR EAX,EAX
004066BE A3 B0804B00 MOV DWORD PTR DS:[4B80B0],EAX
004066C3 33C0 XOR EAX,EAX
004066C5 A3 B4804B00 MOV DWORD PTR DS:[4B80B4],EAX
004066CA E8 C1FFFFFF CALL Pej.00406690
004066CF BA A8804B00 MOV EDX,Pej.004B80A8
004066D4 8BC3 MOV EAX,EBX //这里EBX就是我们要的EAX的数值。004B6FA8 记下来。
004066D6 E8 D9DBFFFF CALL Pej.004042B4
004066DB 5B POP EBX
004066DC C3 RETN
......................................................
004B721B 0080 6F4B0000 ADD BYTE PTR DS:[EAX+4B6F],AL //向上数11个00,确定真Oep为004B7220,补上我们记录的Stolen Code吧。
004B7221 0000 ADD BYTE PTR DS:[EAX],AL
004B7223 0000 ADD BYTE PTR DS:[EAX],AL
004B7225 0000 ADD BYTE PTR DS:[EAX],AL
004B7227 0000 ADD BYTE PTR DS:[EAX],AL
004B7229 0000 ADD BYTE PTR DS:[EAX],AL
004B722B E8 6CF4F4FF CALL Pej.0040669C
004B7230 A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4] //临时Oep
004B7235 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B7237 E8 C48CFCFF CALL Pej.0047FF00
004B723C A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B7241 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B7243 BA 80724B00 MOV EDX,Pej.004B7280
004B7248 E8 AB88FCFF CALL Pej.0047FAF8
004B724D 8B0D F4A14B00 MOV ECX,DWORD PTR DS:[4BA1F4] ; Pej.004BBCAC
004B7253 A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B7258 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B725A 8B15 48E44A00 MOV EDX,DWORD PTR DS:[4AE448] ; Pej.004AE494
004B7260 E8 B38CFCFF CALL Pej.0047FF18
004B7265 A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B726A 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B726C E8 278DFCFF CALL Pej.0047FF98
004B7271 E8 06D2F4FF CALL Pej.0040447C
......................................................
Ctrl+G 004B7220
004B7220 55 PUSH EBP //现在可以用插件修正入口为B7220,重建输入表选方式2脱壳。
004B7221 8BEC MOV EBP,ESP
004B7223 83C4 10 ADD ESP,10
004B7226 B8 A86F4B00 MOV EAX,Pej.004B6FA8
004B722B E8 6CF4F4FF CALL Pej.0040669C
004B7230 A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B7235 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B7237 E8 C48CFCFF CALL Pej.0047FF00
004B723C A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B7241 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B7243 BA 80724B00 MOV EDX,Pej.004B7280
004B7248 E8 AB88FCFF CALL Pej.0047FAF8
004B724D 8B0D F4A14B00 MOV ECX,DWORD PTR DS:[4BA1F4] ; Pej.004BBCAC
004B7253 A1 C4A04B00 MOV EAX,DWORD PTR DS:[4BA0C4]
004B7258 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B725A 8B15 48E44A00 MOV EDX,DWORD PTR DS:[4AE448] ; Pej.004AE494
004B7260 E8 B38CFCFF CALL Pej.0047FF18
......................................................
IAT修复,关闭OD,打开加壳程序,呵呵OEP填1000,ImportREC把Size认为000000A8太小了,改为1000,点获得输入表。显示无效,先用等级1方式跟踪,然后用Asprtect1.22插件再减轻一下压力。还剩591个指针没修复。
现在的问题是,这591个指针是有用的吗?ImpRec 1.6会告诉你
点击show invalid并右键单击选择其中的一个,让我们来修复它
00BC214<- 右键单击选择DeasmHexView查看:
ImpRec 1.6提示你,read error!好,够了,只要有这个提示的一律可以安全的Cut。
如果这个指针有效,里面会显示汇编指令。
找了一会,发现00BC370处的指针是唯一一个没识别的指针。
右键单击选择DeasmHexView查看,究竟它是Kernel32.dll中的哪个函数呢,按Page Down两次,看到
00DB1D2E call 00DA5158 // = kernel32.dll/00B3/FindResourceA
第一个看到的Api函数就是要修复的指针。
呵呵,修复它吧,双击00BC370这行,填入Api函数FindResourceA。
拿起剪刀,将剩下590个垃圾指针全部Cut,IAT全部修复,爽啊。修正Oep 为 B7220 最后修复文件,无法运行!
经过调试N个Dephi文件,发现Asprotect1.23rc4的Dephi程序,入口处脱壳有反脱壳代码,只能在最后一次异常处脱壳,不然即使修复IAT和补上代码也不能运行。
于是在最后一次异常处用LoadPe脱壳,IAT修复和Stolen Code过程同上面,最后正常运行。
【破解总结】发现Dephi语言的Asprotect1.23Rc4的壳开始用Stolen Code,并且有变形指令,反脱壳代码,最麻烦,tc ebp==12fff0还不错吧,好累啊,全文完。
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!