By:来自轻院的狼【+Immlep+】
Site:http://ptteam.com
Blog:http://immlep.blogone.net


US_unpackMe_5是Unpacking Saga(简称 US)出的来验证成员的五个 UnpackMe中的一个,之前发过一篇unpackme_5的,今天趁着五一放假,整理了前面两个(unpackMe_1和unpackMe_2),这里讨论的是US_unpackMe_1,用acprotect加壳的,跟踪上没有什么难度,不过acp对delphi程序的stolenbyte偷了一些,今天我们要讨论的主要是把这里字节还原回去,然后基本上就脱壳成功了,至于脱壳后跨平台方面的问题可以参考fly兄以前的脱文,我这里就偷懒一下:


1.躲过acp的anti:
载入壳,在kernel32.Process32Next下硬件断点
断下后放回,会见到类似的这断代码:
00474FA6  ^\EB 90           JMP SHORT unpackme.00474F38

01023F38    0BC0            OR EAX,EAX
01023F3A    74 7F           JE SHORT NOTEPAD1.01023FBB     ; 看是不是取完了所有的进程!让它跳的(改标志位)就可以去掉这段反跟踪了,按F9就可以让od飞起来了

2.如何恢复stolenbyte:
其实很多壳的stolenbyte是偷得很bt的,但有些就偷的就像鸡肋(pespin就是一个例子),不管怎么样,最重要的是要有耐心,不过acp的stolenbyte也偷得不是很好,缺乏多态和变形,充其量也只不过是在代码之间加了很多得花指令,算算也和pespin差不多,呵呵:
被偷的代码在壳中的基本没被加密过,像这样:
stolenbyte_part_1
junk_code(很多)
stolenbyte_part_2
junk_code(很多)
stolenbyte_part_3
junk_code(很多)
stolenbyte_part_4
.....


stolenbyte都被包含在类似这样的一段代码中:
----------
  XCHG EDXEBP
  DEC EDX
  POPAD
  POP DWORD PTR [464BFD]
  MOV DWORD PTR [ESI], ECX
  POP DWORD PTR [464CBD]
  PUSH DWORD PTR [464CBD]
  POP ESI
  PUSH DWORD PTR [464C9D]
  PUSH EDX
  POP DWORD PTR [464CB5]
  PUSH DWORD PTR [464CB5]
  MOV DWORD PTR [464E6D], unpackme.00464D45
  PUSH DWORD PTR [464E6D]
  POP EDX
  MOV DWORD PTR [EDX], EAX
  POP DWORD PTR [464D61]
  MOV EDXDWORD PTR [464D61]
  PUSH DWORD PTR [464D45]
  NOP
  NOP
  PUSHAD
----------

junk_code是由一段段垃圾指令组成,每一段垃圾指令由一个;
0047CD88  ^\0F85 86FFFFFF         JNZ unpackme.0047CD14
构成循环,所以在跟踪垃圾指令时可以向下翻找:
JNZ XXXXXX   (六个字节的jnz指令)
也可以查找:
FFFFFF??850F
然后F4到JNZ XXXXXX的下一条指令
不过我们其实根本不用去跟踪花指令,用esp定律,呵呵,你可看到把stolenbyte夹在中间的
POPAD
PUSHAD
3.DELPHI程序中被偷的代码:
其实我对delphi并不是很熟悉,只不过脱些被偷字节的delphi时,一边参考一下没有加过壳的delphi程序,所以基本上就
知道了delphi入口一些代码的规律了,delphi入口代码一般有5个CALL(6个的也见过,7个过的也见过,恢复时最好跟进壳里去看看就可以看出点眉目来了)
第一个CALL跟进,在这里会调用函数kernel32.GetModuleHandleA,所以你有时大可以在GetModuleHandleA下断,断下后返回再返回,就基本可以确定第一个CALL的位置了,在恢复这些代码前找了几个delphi样本看了一下,delphi程序基本是这样的(这里是六个CALL的):
  PUSH EBP 
  MOV EBPESP
  ADD ESP, -xx
  MOV EAX, XXXXXX_1
  CALL XXXXXX_ADDR_1
  MOV EAXDWORD PTR [XXXXXX_3]
  MOV EAXDWORD PTR [EAX]
  CALL XXXXXX_ADDR_2
  MOV EAXDWORD PTR [XXXXXX_3]
  MOV EAXDWORD PTR [EAX]
  MOV EDX,XXXXXX_2
  CALL XXXXXX_ADDR_3
  MOV ECXDWORD PTR [54FF4C]
  MOV EAXDWORD PTR [XXXXXX_3]
  MOV EAXDWORD PTR [EAX]
  MOV EDXDWORD PTR [54E154]
  CALL XXXXXX_ADDR_4
  MOV EAXDWORD PTR [XXXXXX_3]
  MOV EAXDWORD PTR [EAX]
  CALL XXXXXX_ADDR_5
  CALL XXXXXX_ADDR_6

我们可以很明显的看到每个CALL指令的中间到带有:
  MOV EAXDWORD PTR [XXXXXX_3]
  MOV EAXDWORD PTR [EAX]
后面两个CALL是连着的。
呵呵,这是很好的特征
4.以上面的代码为例本,现在就来试试修复这些代码:
载入壳时,忽略所有异常,撤销所有软断点,下硬件断点:
hr 0012FFA4
bp Process32Next

用上面的方法躲过acp的anti,再第二次Process32Next断点处理后,就会频繁在第一个断点0012FFA4断下了,每次断在这样的代码出,就要注意了,被偷的字节有可能就在这里了,我们现在在GetModuleHandleA下断,看看第一个call的位置,免得做些无用功,二次断下时,发现时返回到程序里去得,跟:

0012FFAC   0047E083   RETURN to unpackme.0047E083 from unpackme.00406610

到0047E083看看:
part:
0047E05A    61                    POPAD
0047E05B    52                    PUSH EDX
0047E05C    893424                MOV DWORD PTR [ESP], ESI
0047E05F    891C24                MOV DWORD PTR [ESP], EBX                               ; unpackme.00453A4C
0047E062    8F05 4D4D4600         POP DWORD PTR [464D4D]                                 ; 7FFDF000
0047E068    8F05 6D4D4600         POP DWORD PTR [464D6D]                                 ; 7FFDF000
0047E06E    FF35 6D4D4600         PUSH DWORD PTR [464D6D]
0047E074    8B1C24                MOV EBXDWORD PTR [ESP]
0047E077    8F05 254D4600         POP DWORD PTR [464D25]                                 ; 7FFDF000
0047E07D    FF15 4D4D4600         CALL NEAR DWORD PTR [464D4D]                           ; unpackme.00406610  ;被偷得CALL都被换成这样的..
0047E083    A1 744E4500           MOV EAXDWORD PTR [454E74]        //这个是不是很熟悉咧。。
0047E088    8B00                  MOV EAXDWORD PTR [EAX]              //这个是不是很熟悉咧。。
0047E08A    53                    PUSH EBX                                               ; unpackme.00453A4C
0047E08B    891424                MOV DWORD PTR [ESP], EDX
0047E08E    893C24                MOV DWORD PTR [ESP], EDI
0047E091    C70424 44214500       MOV DWORD PTR [ESP], unpackme.00452144                 ; ASCII "S◆ME"
0047E098    8F05 814C4600         POP DWORD PTR [464C81]                                 ; 7FFDF000
0047E09E    FF15 814C4600         CALL NEAR DWORD PTR [464C81]         //被偷的CALL_2 unpackme.00452144
0047E0A4    8935 8D4C4600         MOV DWORD PTR [464C8D], ESI
0047E0AA    90                    NOP
0047E0AB    60                    PUSHAD

继续F9,hr 0012FFA4断下多处,捉有用的下来:
part:
0047F57A    61                    POPAD
0047F57B    8B3D A14D4600         MOV EDIDWORD PTR [464DA1]
0047F581    8F05 1D4C4600         POP DWORD PTR [464C1D]                                 ; 7FFDF000
0047F587    57                    PUSH EDI                                               ; unpackme.00454F4C
0047F588    BF 1D4C4600           MOV EDI, unpackme.00464C1D                             ; ASCII "e_1.exe"
0047F58D    8B1F                  MOV EBXDWORD PTR [EDI]                               ; unpackme.00455C48
0047F58F    5F                    POP EDI                                                ; 7FFDF000
0047F590    8B08                  MOV ECXDWORD PTR [EAX]                //这个有点熟悉咧 ; unpackme.00455C48   EAX=00454F4C
0047F592    8F05 854E4600         POP DWORD PTR [464E85]                                 ; 7FFDF000
0047F598    FF35 854E4600         PUSH DWORD PTR [464E85]
0047F59E    8F05 154F4600         POP DWORD PTR [464F15]                                 ; 7FFDF000
0047F5A4    8B05 154F4600         MOV EAXDWORD PTR [464F15]               
0047F5AA    A1 744E4500           MOV EAXDWORD PTR [454E74]               //这个是不是很熟悉咧。。
0047F5AF    8B00                  MOV EAXDWORD PTR [EAX]                  //这个是不是很熟悉咧。。
0047F5B1    8915 4D4E4600         MOV DWORD PTR [464E4D], EDX
0047F5B7    FF35 4D4E4600         PUSH DWORD PTR [464E4D]
0047F5BD    890C24                MOV DWORD PTR [ESP], ECX
0047F5C0    891C24                MOV DWORD PTR [ESP], EBX                               ; unpackme.00454F4C
0047F5C3    8905 E54C4600         MOV DWORD PTR [464CE5], EAX                            ; unpackme.00454F4C
0047F5C9    90                    NOP
0047F5CA    90                    NOP
0047F5CB    60                    PUSHAD

part:
00480000    61                    POPAD
00480001    FF35 E54C4600         PUSH DWORD PTR [464CE5]
00480007    C70424 30364500       MOV DWORD PTR [ESP], unpackme.00453630
0048000E    8B1C24                MOV EBXDWORD PTR [ESP]
00480011    8F05 0D4D4600         POP DWORD PTR [464D0D]                                 ; 7FFDF000
00480017    8B13                  MOV EDXDWORD PTR [EBX]         //这个有点熟悉咧 ; unpackme.00455C48   EBX=00453630
00480019    8B1C24                MOV EBXDWORD PTR [ESP]
0048001C    8F05 694D4600         POP DWORD PTR [464D69]                                 ; 7FFDF000
00480022    50                    PUSH EAX
00480023    891C24                MOV DWORD PTR [ESP], EBX                               ; unpackme.00453630
00480026    8F05 014D4600         POP DWORD PTR [464D01]                                 ; 7FFDF000
0048002C    FF35 014D4600         PUSH DWORD PTR [464D01]
00480032    57                    PUSH EDI
00480033    BF 5C214500           MOV EDI, unpackme.0045215C
00480038    893D 214C4600         MOV DWORD PTR [464C21], EDI
0048003E    5F                    POP EDI                                                ; 7FFDF000
0048003F    FF35 214C4600         PUSH DWORD PTR [464C21]
00480045    8F05 D94D4600         POP DWORD PTR [464DD9]                                 ; 7FFDF000
0048004B    50                    PUSH EAX
0048004C    B8 D94D4600           MOV EAX, unpackme.00464DD9
00480051    60                    PUSHAD


part:
004809E5    61                    POPAD
004809E6    8B18                  MOV EBXDWORD PTR [EAX]                               ; unpackme.0045215C
004809E8    58                    POP EAX                                                ; 009712DC
004809E9    50                    PUSH EAX                                               ; unpackme.00464DD9
004809EA    B8 E14E4600           MOV EAX, unpackme.00464EE1
004809EF    8930                  MOV DWORD PTR [EAX], ESI
004809F1    58                    POP EAX                                                ; 009712DC
004809F2    FF35 E14E4600         PUSH DWORD PTR [464EE1]
004809F8    68 F94E4600           PUSH unpackme.00464EF9
004809FD    8F05 F94C4600         POP DWORD PTR [464CF9]                                 ; 009712DC
00480A03    52                    PUSH EDX                                               ; unpackme.0045367C
00480A04    BA F94C4600           MOV EDX, unpackme.00464CF9
00480A09    8B32                  MOV ESIDWORD PTR [EDX]                               ; unpackme.00439BD0
00480A0B    5A                    POP EDX                                                ; 009712DC
00480A0C    891E                  MOV DWORD PTR [ESI], EBX
00480A0E    8B3424                MOV ESIDWORD PTR [ESP]
00480A11    8F05 E54D4600         POP DWORD PTR [464DE5]                                 ; 009712DC
00480A17    8B1C24                MOV EBXDWORD PTR [ESP]
00480A1A    8F05 494D4600         POP DWORD PTR [464D49]                                 ; 009712DC
00480A20    FF15 F94E4600         CALL NEAR DWORD PTR [464EF9]                 //被偷的CALL_3 unpackme.0045215C
00480A26    A1 744E4500           MOV EAXDWORD PTR [454E74]                  //这个是不是很熟悉咧。
00480A2B    8B00                  MOV EAXDWORD PTR [EAX]                     //这个是不是很熟悉咧。
00480A2D    90                    NOP
00480A2E    90                    NOP
00480A2F    60                    PUSHAD

捉到这些用的之后在F9就没见什么动静了,程序运行了起来,可是我们只捉到了三个call啊,哈哈,没关系,因为acp就只偷了这些CALL,剩下的那两个最后的call是连在一起的,到我们捉到最后一片代码(00480A2F)时,手动来跟踪一下,用上面的方法步过垃圾指令:
发现:
00480E76    61                    POPAD
00480E77    EB 01                 JMP SHORT unpackme.00480E7A

00480E7A  - FF25 BC0E4800         JMP NEAR DWORD PTR [480EBC]                            ; unpackme.00453BF7

哈哈,找到了:
00453BF7    E8 E0E5FFFF           CALL unpackme.004521DC
00453BFC    E8 5705FBFF           CALL unpackme.00404158

现在来整理一下:
  PUSH EBP 
  MOV EBPESP
  ADD ESP, -10                           //跟到0047E07D:CALL 00406610时看ESP的值分析,这里要-10
  MOV EAX, 00453A4C                   //跟到0047E07D:CALL 00406610时看EAX的值00453A4C
  CALL 00406610  
  MOV EAXDWORD PTR [454E74]
  MOV EAXDWORD PTR [EAX]
  CALL 00452144
  MOV ECXDWORD PTR [00454F4C]
  MOV EAXDWORD PTR [454E74]
  MOV EAXDWORD PTR [EAX]
  MOV EDXDWORD PTR [00453630]              
  CALL 0045215C
  MOV EAXDWORD PTR [454E74]
  MOV EAXDWORD PTR [EAX]
  CALL 004521DC
  CALL 0404158


补完代码,dump,用Import RECfixdump,OK
运行。。。可以运行。。。退出--有点小错误,呵呵,自己搞定吧。。。

Special thx:
eaton,ama,catking668, www.pediy.com,www.crackslatinos.hispadominio.net,luocong's scc and you!

Ps:但要记住,虽然我没提到你,我还是记得你的,感谢着你的。。。