实践ASProtect 2.1x SKE脱壳(街头篮球客户端)

纯粹的照猫画虎,高手就不用浪费时间看了。

感谢loveboom的教程《ASPROTECT 2.x 脱壳系列》!
感谢mirrormask的《学习ASProtect 2.1x SKE 脱壳》一文!
感谢shoooo的指教!

工具:OllyICE,Lord-PE,ImportREC.

声明:这个脱文几乎就是loveboom的《ASPROTECT 2.x 脱壳系列之一》的翻版。

好,现在切入正题,我尽可能说的详细一些。有些地方,我还是一知半解,所以可能解释有误,还望高手斧正。


首先,因为街头篮球使用的HackShield系统。HackSield系统的反调试功能很强。
所以,如果让其加载了Hackshield的系统,那么客户端主程序FreeStyle.exe在OD下就跑不起来了.
我没有能力去搞掉hackShield系统,所以我把HackShield的目录改名,让其无法加载HackShield.
然后,可以用OD加载Freestyle.exe,忽略所有异常。看看能不能跑起来。
我这里能够跑起来,运行后加载HackShield的时候,程序会告知无法加载,等待你点一下确定,然后就退出了。

最后提醒一点:如果加载了HackShield用OD调试,好像会引起死机.


不过,这时候程序已经完全从壳里面解了出来.所以脱壳的目的是可以达到的.

用OD加载Freestyle.exe.
会停在这里:
///////////////////////////////////////////////////////////////////////
00401000 >/$  68 01F06E00   push    006EF001
00401005  |.  E8 01000000   call    0040100B
0040100A  \.  C3            retn
0040100B   $  C3            retn
0040100C      E4            db      E4
0040100D      24            db      24                               ;  CHAR '$'
0040100E      2A            db      2A                               ;  CHAR '*'
...后面全是乱七八糟的数据,不用管.
/////////////////////////////////////////////////////////////////////////////////

!!!:记住隐藏OD.(用HideOD插件)

脱壳的第一步,就是找到OEP.
帮助找到OEP的方法很多,比如ESP定律,2次内存映射断点等等.
这里可以使用这个方法.
先忽略除非法访问内存异常外的所有异常.然后按F9(运行程序).应该会有异常出现按shift+F9忽略.注意记住你忽略了多少次异常后程序开始运行.(可以设置忽略所有异常,清空LOG,然后然程序跑,跑起来后,看LOG数一数异常纪录的个数就能知道有几次异常)(我这是22次,如果没数错~)

然后重新加载.忽略除非法访问内存异常外的所有异常,最后一次异常发生时,给代码段下断点(方法:ALT+M,然后找到freestyle的代码段,选中后按一下F2),然后shift+F9忽略异常.

这时就停在了OEP了:
///////////////////////////////////////////////////////////////////////////

00626777   .  55            push    ebp                              ;  FreeStyl.0046637E
00626778   .  8BEC          mov     ebp, esp
0062677A   .  6A FF         push    -1
0062677C   .  68 18B16500   push    0065B118
00626781   .  68 B0B46200   push    0062B4B0                         ;  SE 处理程序安装
00626786   .  64:A1 0000000>mov     eax, fs:[0]
0062678C   .  50            push    eax
0062678D   .  64:8925 00000>mov     fs:[0], esp
00626794   .  83EC 58       sub     esp, 58
00626797   .  53            push    ebx
00626798   .  56            push    esi
00626799   .  57            push    edi
0062679A   .  8965 E8       mov     [ebp-18], esp
0062679D   .  FF15 B0206500 call    [6520B0]                         ;  kernel32.GetVersion

////////////////////////////////////////////////////////////////////////////

记下OEP备以后用:这里是00626777.

好了OEP就找到了.

然后就是IAT了.

看到上面的call [6520B0] ;kernel32.GetVersion那么就去去006520B0,向上看找找以一大堆00结尾在哪里,在向下看同样找找零结尾在哪里.发现IAT从00652000开始到0065247C结束,而且没有加密.
判断加密的方法,我是去看代码段最后面的一些整齐排列jmp [xxxxxxx]看看有没有被一定数量的相同call xxxxxxxx(xxxxxxxx一般是同一个数)隔开.如果没有,8成是没加密.因为call xxxxxxx就是壳的解密函数.

这个程序没有。而且IAT地址看起来都没有问题:
//////////////////////////////////////////////////////////////////////////////
这个就是IAT:
00652000  1B C4 DC 77 83 78 DA 77 F0 6B DA 77 00 00 00 00  能w儀趙餶趙....
00652010  26 D9 18 6D 00 00 00 00 24 49 37 00 00 00 00 00  &?m....$I7.....
00652020  98 6E EF 77 8A 5A EF 77 D6 E8 EF 77 00 60 EF 77  榥飛奪飛骤飛.`飛
00652030  52 D4 EF 77 90 5B EF 77 97 5D EF 77 49 5E EF 77  R燥w怺飛梋飛I^飛
00652040  7C 8B F0 77 1D 8E F0 77 B3 BF F0 77 2D 6C EF 77  |嬸w庰w晨饂-l飛
00652050  60 B2 F1 77 B8 85 EF 77 33 8C EF 77 FB 5E EF 77  `柴w竻飛3岋w鸮飛
00652060  49 92 EF 77 00 00 00 00 B3 22 30 76 A6 3A 30 76  I掞w....?0v?0v
00652070  66 55 30 76 F3 29 30 76 82 5B 30 76 F8 6F 30 76  fU0v?0v俒0v鴒0v
00652080  8E 4D 30 76 2B 47 30 76 00 00 00 00 53 30 82 7C  嶮0v+G0v....S0倈
00652090  A9 26 82 7C FB 2C 82 7C 7C 36 81 7C 3D 04 93 7C  ?倈?倈|6亅=搢
006520A0  D4 05 93 7C 0D E0 80 7C 16 1E 80 7C A2 CA 81 7C  ?搢.鄝|€|⑹亅
006520B0  AB 14 81 7C EE 1E 80 7C 5C E8 81 7C 94 22 82 7C  ?亅?€|\鑱|?倈
006520C0  E1 EA 81 7C 40 7A 95 7C 5D 99 80 7C E0 C6 80 7C  彡亅@z晐]檧|嗥€|
006520D0  52 70 82 7C 8B C2 85 7C 84 E5 81 7C 7C 2F 81 7C  Rp倈嬄厊勫亅|/亅
006520E0  6E 9C 80 7C 3F FF 81 7C 28 9C 80 7C BD E4 81 7C  n渶|?亅(渶|戒亅
006520F0  A9 2C 81 7C 64 B6 80 7C F4 97 80 7C AC 92 80 7C  ?亅d秬|魲€|瑨€|
00652100  86 03 81 7C FD 79 93 7C 59 35 81 7C E6 2B 81 7C  ?亅齳搢Y5亅?亅
00652110  43 99 80 7C 2A E8 81 7C 0E 18 80 7C 19 90 83 7C  C檧|*鑱|€|悆|
00652120  D7 EF 80 7C EC E9 80 7C 66 EA 80 7C 4E A3 80 7C  罪€|扉€|f陘|N|
00652130  93 D2 80 7C 94 97 80 7C 42 24 80 7C 57 B3 80 7C  撘€|敆€|B$€|W硛|
00652140  C1 C9 80 7C 79 E0 81 7C 77 9B 80 7C 8D 3A 86 7C  辽€|y鄟|w泙|?唡
00652150  B7 47 86 7C 63 4C 81 7C A1 97 83 7C AD 9C 80 7C  稧唡cL亅億瓬€|
00652160  A1 9F 80 7C 8A 18 93 7C ED 10 92 7C 05 10 92 7C  €|?搢?抾抾
00652170  90 72 DD 00 C4 2F 88 7C 66 AA 80 7C 7B 97 80 7C  恟??坾f獉|{梹|
00652180  5C 9B 85 7C 8D 2C 81 7C 29 B5 80 7C 9F 0F 81 7C  \泤|?亅)祤|?亅
00652190  31 03 93 7C 8F 0C 81 7C 8D B7 80 7C 6C 94 80 7C  1搢?亅嵎€|l攢|
006521A0  24 1A 80 7C 76 09 81 7C C7 A0 80 7C 51 28 81 7C  $€|v.亅莀€|Q(亅
006521B0  FC B7 80 7C B2 AC 80 7C ED CB 81 7C 17 A4 80 7C  €|铂€|硭亅|
006521C0  DA 56 82 7C 6B 17 80 7C 72 17 81 7C 50 F8 81 7C  赩倈k€|r亅P鴣|
006521D0  C0 9F 80 7C ED 70 83 7C 7E D4 80 7C E3 12 81 7C  罒€|韕億~詟|?亅
006521E0  53 C1 81 7C AE 94 83 7C 80 A4 80 7C B9 8C 83 7C  S羴|當億€|箤億
006521F0  58 CD 80 7C CB D8 81 7C 57 BB 80 7C C4 CE 80 7C  X蛝|素亅W粈|奈€|
00652200  2B 2E 83 7C 29 9F 80 7C 81 9A 80 7C 14 9B 80 7C  +.億)焵|仛€|泙|
00652210  29 29 81 7C 10 11 81 7C 6A 48 81 7C 78 2C 81 7C  ))亅亅jH亅x,亅
00652220  23 CC 81 7C 5F 48 81 7C 19 62 82 7C B3 9E 80 7C  #虂|_H亅b倈碁€|
00652230  2F 08 81 7C 37 97 80 7C F5 9B 80 7C 50 97 80 7C  /亅7梹|鯖€|P梹|
00652240  A9 CC 80 7C 3F DC 81 7C 8A 2B 86 7C 69 10 81 7C  ┨€|?軄|?唡i亅
00652250  CF C6 80 7C A6 0D 81 7C ED 09 93 7C 49 AA 80 7C  掀€|?亅?搢I獉|
00652260  0F 2B 81 7C 40 03 93 7C 00 3C 86 7C 00 00 00 00  +亅@搢.<唡....
00652270  60 9A 00 10 30 9B 00 10 50 96 00 10 90 96 00 10  `?0?P?悥.
00652280  80 91 00 10 F0 93 00 10 C0 96 00 10 80 99 00 10  €?饟.罇.€?
00652290  20 99 00 10 A0 3A 00 10 A0 3A 00 10 A0 90 00 10   ??.?._.
006522A0  10 93 00 10 40 92 00 10 00 40 00 10 E0 38 00 10  ?@?.@.?.
006522B0  B0 94 00 10 A0 91 00 10 10 94 00 10 50 9A 00 10  皵._.?P?
006522C0  90 9A 00 10 B0 9A 00 10 D0 99 00 10 40 97 00 10  悮.皻.袡.@?
006522D0  80 95 00 10 70 96 00 10 20 97 00 10 10 9B 00 10  €?p? ??
006522E0  F0 9A 00 10 A0 40 00 10 70 3B 00 10 00 10 00 10  饸._@.p;...
006522F0  F0 10 00 10 40 10 00 10 B0 11 00 10 80 3F 00 10  ?.@.?.€?.
00652300  D0 3A 00 10 A0 39 00 10 A0 96 00 10 F0 96 00 10  ?.?._.饢.
00652310  C0 3B 00 10 A0 3E 00 10 30 3C 00 10 80 3E 00 10  ?.?.0<.€>.
00652320  40 40 00 10 40 40 00 10 40 40 00 10 60 3E 00 10  @@.@@.@@.`>.
00652330  20 38 00 10 D0 3A 00 10 D0 3A 00 10 00 3B 00 10   8.?.?..;.
00652340  90 38 00 10 10 9A 00 10 30 9A 00 10 00 00 00 00  ?.?0?....
00652350  20 49 0F 77 C2 4B 0F 77 50 48 0F 77 95 D2 11 77   Iw翶wPHw曇w
00652360  D9 66 0F 77 C0 48 0F 77 3B 4C 0F 77 A8 4C 0F 77  賔w繦w;Lw↙w
00652370  C3 CA 11 77 55 4C 0F 77 00 00 00 00 85 CB D1 77  檬wULw....吽褀
00652380  9A F3 D2 77 60 DA D1 77 33 B9 D1 77 AE B6 D1 77  汅襴`谘w3寡w褀
00652390  1B C0 D1 77 9D 8F D1 77 EA 04 D5 77 AD A8 D1 77  姥w潖褀?誻褀
006523A0  C2 D7 D1 77 DA C6 D3 77 09 B6 D1 77 1D B6 D1 77  伦褀谄觲.堆w堆w
006523B0  F6 8B D1 77 6C C9 D1 77 B8 96 D1 77 24 13 D2 77  鰦褀l裳w笘褀$襴
006523C0  3E 0B D2 77 0D D6 D1 77 F9 D7 D1 77 5D 94 D1 77  > 襴.盅w褀]斞w
006523D0  6C BF D1 77 5E 02 D2 77 A4 D8 D1 77 E6 37 D2 77  l垦w^襴へ褀?襴
006523E0  EA DA D1 77 EE D4 D1 77 41 BD D1 77 C6 B5 D1 77  贲褀钤褀A窖w频褀
006523F0  11 12 D2 77 00 00 00 00 FF 19 BD 77 50 1A BD 77  襴....絯P絯
00652400  BA 18 BD 77 00 00 00 00 5B 4E B1 76 00 00 00 00  ?絯....[N眝....
00652410  66 2B A2 71 41 3F A2 71 D4 4F A2 71 00 00 00 00  f+A?設....
00652420  80 E8 D3 6D 00 00 00 00 10 AA 11 21 70 A0 11 21  €栌m....?!p?!
00652430  20 A6 12 21 20 A2 11 21 30 A1 11 21 60 A8 11 21   ?! ?!0?!`?!
00652440  A0 A5 11 21 00 A5 11 21 90 B5 11 21 70 34 11 21  _!.?!惖!p4!
00652450  60 AC 11 21 70 AE 11 21 00 AB 11 21 A0 A4 11 21  `?!p?!.?!_!
00652460  C0 36 11 21 00 00 00 00 36 EE 9A 76 37 2A 9B 76  ?!....6顨v7*泇
00652470  C3 FA 9A 76 BA 61 A0 76 00 00 00 00 00 00 00 00  铭歷篴_v........
/////////////////////////////////////////////////////////////////////////////////

好了,知道了IAT从00652000开了,大小为:047C
纪录下来。

现在到了脱壳最困难麻烦的地方了.

大家知道vc的程序,一般OEP后面就是GetVersion后接着就是GetStartInfo.我们看看这个程序的OEP处了代码.
///////////////////////////////////////////////////////////////////////////////////////////////
00626777   .  55            push    ebp                              ;  FreeStyl.0046637E
00626778   .  8BEC          mov     ebp, esp
0062677A   .  6A FF         push    -1
0062677C   .  68 18B16500   push    0065B118
00626781   .  68 B0B46200   push    0062B4B0                         ;  SE 处理程序安装
00626786   .  64:A1 0000000>mov     eax, fs:[0]
0062678C   .  50            push    eax
0062678D   .  64:8925 00000>mov     fs:[0], esp
00626794   .  83EC 58       sub     esp, 58
00626797   .  53            push    ebx
00626798   .  56            push    esi
00626799   .  57            push    edi
0062679A   .  8965 E8       mov     [ebp-18], esp
0062679D   .  FF15 B0206500 call    [6520B0]                         ;  kernel32.GetVersion
006267A3   .  33D2          xor     edx, edx
006267A5   .  8AD4          mov     dl, ah
006267A7   .  8915 8CA86E00 mov     [6EA88C], edx
006267AD   .  8BC8          mov     ecx, eax
006267AF   .  81E1 FF000000 and     ecx, 0FF
006267B5   .  890D 88A86E00 mov     [6EA888], ecx
006267BB   .  C1E1 08       shl     ecx, 8
006267BE   .  03CA          add     ecx, edx
006267C0   .  890D 84A86E00 mov     [6EA884], ecx
006267C6   .  C1E8 10       shr     eax, 10
006267C9   .  A3 80A86E00   mov     [6EA880], eax
006267CE   .  6A 01         push    1
006267D0   .  E8 3F750000   call    0062DD14
006267D5   .  59            pop     ecx
006267D6   .  85C0          test    eax, eax
006267D8   .  75 08         jnz     short 006267E2
006267DA   .  6A 1C         push    1C
006267DC   .  E8 C3000000   call    006268A4
006267E1   .  59            pop     ecx
006267E2   >  E8 E53E0000   call    0062A6CC
006267E7   .  85C0          test    eax, eax
006267E9   .  75 08         jnz     short 006267F3
006267EB   .  6A 10         push    10
006267ED   .  E8 B2000000   call    006268A4
006267F2   .  59            pop     ecx
006267F3   >  33F6          xor     esi, esi
006267F5   .  8975 FC       mov     [ebp-4], esi
006267F8   .  E8 DE6B0000   call    0062D3DB
006267FD   .  E8 FE979B00   call    00FE0000        ;!!!!!!!!!到壳里面去了
00626802   .  91            xchg    eax, ecx
00626803   .  A3 D4CD6E00   mov     [6ECDD4], eax
00626808   .  E8 60720000   call    0062DA6D
0062680D   .  A3 70A86E00   mov     [6EA870], eax
00626812   .  E8 09700000   call    0062D820
00626817   .  E8 4B6F0000   call    0062D767
0062681C   .  E8 0E040000   call    00626C2F
00626821   .  8975 D0       mov     [ebp-30], esi
00626824   .  8D45 A4       lea     eax, [ebp-5C]
00626827   .  50            push    eax
00626828   .  E8 D3979B00   call    00FE0000       ;!!!!!!!!到壳里面去了
0062682D   .  C7 E8 DC 6E 0>ascii   "氰躰",0
00626832      00            db      00
00626833      89            db      89
00626834      45            db      45                               ;  CHAR 'E'
00626835      9C            db      9C
后面又是乱七八糟的数据,不用管

///////////////////////////////////////////////////////////////////////////////////////////////
看到了GetVersion了,但是GetStartInfo在哪呢?没有~
但是你应改发现有两个call 00FE0000.
给据loveboom的教导,知道这是壳把原来CALL API改成了CALL xxxxxxxx,这个call xxxxxxxx会到壳代码里面.
(不同机器上面好像xxxxxxxx都不一样).我这里是00FE0000.
现在就是要修复成CALL 正确的API.怎么才能得到这个正确的地址呢.当然只有跟进去看.
不过由于被改了的地方实在太多,人工修复几乎不可能.所以必须写个程序来修复.
这就是Patch.
下面大概讲一下patch的原理.后面会将详细的操作.
patch的方法很多,下面是loveboom提供的方法.
先来整理一下思路,我们要把call xxxxxxxx改称正确的call API.
就必须有一张表.里面一一对应记录着call xxxxxxxx的地址->正确的API的地址.
有了这个表,我们就可以快速的把所有call xxxxxxxx改称正确的call api了.

所以,第一次patch就是为了得到这张表.
怎么得到呢,对于ASPr壳,当进入call xxxxxxxx后,壳会把这个call xxxxxxxx改成正确的call API然后跳回原地,就地进入api.
当然这中间有复杂的算法和繁多的花指令.所以想要逆向得到这个正确的API太麻烦.可以借用壳的代码,在它解出来正确的地址的时候我们把它截取,保存下来.

patch的准备工作:
先重新载入freestyle.exe
先来到OEP,找一个call xxxxxxxx(这里是call 00FE0000)
因为aspr要把call xxxxxxxx改成正确的所以我们在上面下内存写入断点(这里是在006267FD上面下内存写入断点).

F9运行
断在了这里:
///////////////////////////////////////////////////
00DE5C9B    57              push    edi
00DE5C9C    6A 00           push    0
00DE5C9E    8D4D E0         lea     ecx, [ebp-20]
00DE5CA1    8B45 F4         mov     eax, [ebp-C]
00DE5CA4    8B40 3C         mov     eax, [eax+3C]
00DE5CA7    8B55 FC         mov     edx, [ebp-4]
00DE5CAA    E8 D1130000     call    00DE7080   ;**********
00DE5CAF    8945 FC         mov     [ebp-4], eax
00DE5CB2    8B45 E0         mov     eax, [ebp-20]
00DE5CB5    8B00            mov     eax, [eax]
00DE5CB7    E8 D0E6FFFF     call    00DE438C
00DE5CBC    8BD0            mov     edx, eax
00DE5CBE    0255 DF         add     dl, [ebp-21]
00DE5CC1    8B4D FC         mov     ecx, [ebp-4]
00DE5CC4    8B45 F4         mov     eax, [ebp-C]
00DE5CC7    E8 80040000     call    00DE614C
00DE5CCC    8945 FC         mov     [ebp-4], eax
00DE5CCF    8B45 F4         mov     eax, [ebp-C]
00DE5CD2    8B40 24         mov     eax, [eax+24]
00DE5CD5    8B55 F4         mov     edx, [ebp-C]
00DE5CD8    0382 E0000000   add     eax, [edx+E0]
00DE5CDE    0145 1C         add     [ebp+1C], eax
00DE5CE1    8B45 FC         mov     eax, [ebp-4]
00DE5CE4    2B45 1C         sub     eax, [ebp+1C]
00DE5CE7    83E8 05         sub     eax, 5
00DE5CEA    8B55 1C         mov     edx, [ebp+1C]
00DE5CED    42              inc     edx
00DE5CEE    8902            mov     [edx], eax     ;断在了这里!!!!
00DE5CF0    EB 01           jmp     short 00DE5CF3
00DE5CF2    E8 8B45F883     call    84D6A282

///////////////////////////////////////////////////
向上看,找到:
//////////////////////////////////////////////////////
00DE5C9E    8D4D E0         lea     ecx, [ebp-20]
00DE5CA1    8B45 F4         mov     eax, [ebp-C]
00DE5CA4    8B40 3C         mov     eax, [eax+3C]
00DE5CA7    8B55 FC         mov     edx, [ebp-4]
00DE5CAA    E8 D1130000     call    00DE7080
//////////////////////////////////////////////////////
跟随进入call    00DE7080
/////////////////////////////////////////////////////
00DE7080    55              push    ebp
00DE7081    8BEC            mov     ebp, esp
00DE7083    83C4 E4         add     esp, -1C
00DE7086    53              push    ebx
00DE7087    56              push    esi
00DE7088    57              push    edi
00DE7089    894D F4         mov     [ebp-C], ecx
00DE708C    8955 F8         mov     [ebp-8], edx
00DE708F    8945 FC         mov     [ebp-4], eax
00DE7092    33C0            xor     eax, eax
00DE7094    8945 F0         mov     [ebp-10], eax
00DE7097    B8 00070000     mov     eax, 700
00DE709C    E8 A3B4FDFF     call    00DC2544      ;**********
00DE70A1    8945 E4         mov     [ebp-1C], eax
//////////////////////////////////////////////////////
再跟随进入call    00DC2544
///////////////////////////////////////////////////////
00DC2544    85C0            test    eax, eax
00DC2546    74 0A           je      short 00DC2552
00DC2548    FF15 1890DE00   call    [DE9018]    ;***!!!!****
00DC254E    09C0            or      eax, eax
00DC2550    74 01           je      short 00DC2553
00DC2552    C3              retn
//////////////////////////////////////////////////////
看见 call    [DE9018]了吗?为什么要跟这么深,因为修改这里的代码不会被壳查出来.
这个地方的call    [DE9018]我们就能把它改成其他的call从而改变程序的流程.
纪录call    [DE9018]的地址,这里是:
00DC2548    FF15 1890DE00   call    [DE9018] 

这个是第一次patch的操作:
重新载入,断GetModuleHandleA(用硬件断点).当第二次断下后.清除硬件断点.F8一路返回,遇见jmp就F4到下一行代码.一会就能看见,如下的代码:
////////////////////////////////////////
00DF15C1    61              popad
00DF15C2    75 08           jnz     short 00DF15CC
00DF15C4    B8 01000000     mov     eax, 1
00DF15C9    C2 0C00         retn    0C
00DF15CC    68 DC89DE00     push    0DE89DC
00DF15D1    C3              retn
///////////////////////////////////////
retn执行以后,到了
///////////////////////////////////////////
00DE89DC    55              push    ebp                              ; 壳的OEP
00DE89DD    8BEC            mov     ebp, esp
00DE89DF    83C4 B4         add     esp, -4C
00DE89E2    B8 D487DE00     mov     eax, 0DE87D4
00DE89E7    E8 50CCFDFF     call    00DC563C
00DE89EC    E8 DBAAFDFF     call    00DC34CC
//////////////////////////////////////////
停在了壳的OEP处,搜索如下指令:
MOV [EBP],EAX
PUSH 0A
会找到一处:
00DE5F7B    8945 00         mov     [ebp], eax  ;在这里下硬件执行断点,断在这里.EIP现在指向这里
00DE5F7E    6A 0A           push    0A
00DE5F80    E8 8FCEFEFF     call    00DD2E14
00DE5F85    8BC8            mov     ecx, eax
00DE5F87    038B E4000000   add     ecx, [ebx+E4]

然后F9运行,会断在00DE5F7B mov     [ebp], eax;
(不过有时候断不下来,直接就跑飞了,下F2断点反而能断下了,不知道是什么原因,哪位牛人能解释一下.)

断下了后,就开始第一次patch了:
为了方便写程序,就近选个地方写代码,当然要先保存原来的代码,不过OD有撤销修改的功能,就不用专门保存了.
用插件申请一块内存,作为保存上面提到的那张表的空间,有这种功能的插件很多.HideOD也有.我申请到的是01020000
/////////////////////////////////////////////////
00DE5F7B    EB 43           jmp     00DE5FC0     ;   注意这里被修改指向我们自己写的代码.EIP还是指向这里
00DE5F7D    90              nop
00DE5F7E    6A 0A           push    0A
00DE5F80    E8 8FCEFEFF     call    00DD2E14
00DE5F85    8BC8            mov     ecx, eax
00DE5F87    038B E4000000   add     ecx, [ebx+E4]
00DE5F8D    8BD6            mov     edx, esi
00DE5F8F    8BC3            mov     eax, ebx
00DE5F91    E8 9EE5FFFF     call    00DE4534
00DE5F96    FF0C24          dec     dword ptr [esp]
00DE5F99    03B3 E4000000   add     esi, [ebx+E4]
00DE5F9F    833C24 00       cmp     dword ptr [esp], 0
00DE5FA3  ^ 0F87 55FEFFFF   ja      00DE5DFE
00DE5FA9    53              push    ebx      ;改完,写完代码后这里下F2断点
00DE5FAA    E8 5D000000     call    00DE600C
00DE5FAF    0183 EC000000   add     [ebx+EC], eax
00DE5FB5    B0 01           mov     al, 1
00DE5FB7    83C4 24         add     esp, 24
00DE5FBA    5D              pop     ebp
00DE5FBB    5F              pop     edi
00DE5FBC    5E              pop     esi
00DE5FBD    5B              pop     ebx
00DE5FBE    C3              retn
00DE5FBF    90              nop
00DE5FC0    53              push    ebx              ;选的这里,最近的地方. 开这开始写
00DE5FC1    51              push    ecx
00DE5FC2    B9 00415100     mov     ecx, 01020000    ;这里数字,填写你想保存这个表的地址.我申请到的地址是01020000,我就保存这
00DE5FC7    8339 00         cmp     dword ptr [ecx], 0
00DE5FCA    75 06           jnz     short 00DE5FD2
00DE5FCC    C701 10415100   mov     dword ptr [ecx], 01020010;这里填写保存地址+10h,这里就是01020000h+10h=01020010h
00DE5FD2    8B19            mov     ebx, [ecx]
00DE5FD4    4D              dec     ebp
00DE5FD5    892B            mov     [ebx], ebp
00DE5FD7    83C3 04         add     ebx, 4
00DE5FDA    8919            mov     [ecx], ebx
00DE5FDC    45              inc     ebp
00DE5FDD    59              pop     ecx
00DE5FDE    5B              pop     ebx
00DE5FDF    8945 00         mov     [ebp], eax
00DE5FE2  ^ EB 9A           jmp     short 00DE5F7E   ;这里就写完了 

///////////////////////////////////////////////////
写完代码,下好断点.F9运行.停在了
00DE5FA9    53              push    ebx  

这时把保存的数据复制一份保存备用.我从01020000复制的数据如下:
///////////////////////////////////////////////////////////////////////////////////////////////
3C 02 04 01 00 00 00 00 00 00 00 00 00 00 00 00 89 8A 48 00 D0 D1 48 00 8A D3 48 00 67 1F 49 00
06 20 49 00 20 20 49 00 39 20 49 00 75 20 49 00 E3 20 49 00 92 21 49 00 C4 24 49 00 3E EA 4B 00
59 EB 4B 00 E0 C0 4E 00 87 16 4F 00 C9 46 55 00 7A 47 55 00 88 A0 55 00 3D 16 56 00 A8 16 56 00
C7 16 56 00 E7 16 56 00 98 2A 56 00 BE C6 56 00 D2 C6 56 00 E2 C6 56 00 E2 C7 56 00 57 C8 56 00
62 C8 56 00 E0 C8 56 00 F8 C8 56 00 0B C9 56 00 B6 CA 56 00 BB DA 58 00 BB DB 58 00 07 38 59 00
73 38 59 00 9A F7 59 00 F5 F7 59 00 2D F8 59 00 9D BF 5A 00 FC C3 5A 00 42 D3 5B 00 61 D3 5B 00
30 8B 5F 00 36 8B 5F 00 3C 8B 5F 00 F2 F4 60 00 BC 06 61 00 64 0F 61 00 6B 0F 61 00 79 94 61 00
02 9A 61 00 2E 9B 61 00 88 9B 61 00 B3 9B 61 00 19 9C 61 00 44 9C 61 00 51 9C 61 00 6A 9C 61 00
95 9C 61 00 A2 9C 61 00 AF 9C 61 00 D6 9C 61 00 E4 9D 61 00 F1 9D 61 00 FE 9D 61 00 54 3D 62 00
EF 3F 62 00 2E 63 62 00 58 63 62 00 FD 67 62 00 28 68 62 00 4B 68 62 00 93 6C 62 00 9A 6C 62 00
5F 73 62 00 73 73 62 00 F6 73 62 00 1A 74 62 00 30 74 62 00 74 74 62 00 5C 79 62 00 91 79 62 00
A3 79 62 00 15 7B 62 00 26 83 62 00 BC 83 62 00 40 84 62 00 C3 8A 62 00 0B A7 62 00 78 A7 62 00
0E C6 62 00 84 C7 62 00 99 C7 62 00 24 C8 62 00 90 CD 62 00 F5 CD 62 00 39 D4 62 00 E4 D4 62 00
47 D5 62 00 55 D5 62 00 8C D5 62 00 43 D8 62 00 8C DB 62 00 A9 DB 62 00 20 DC 62 00 80 DC 62 00
17 DE 62 00 ED DE 62 00 F4 DE 62 00 15 09 63 00 5E 09 63 00 E0 13 63 00 FC 13 63 00 14 14 63 00
F5 18 63 00 74 19 63 00 A7 1A 63 00 C7 1C 63 00 1B 1E 63 00 4F 1E 63 00 3F 27 63 00 86 39 63 00
7E 3C 63 00 94 3C 63 00 D5 3D 63 00 39 40 63 00 2D 41 63 00 D3 41 63 00 7E 48 63 00 AB 4E 63 00
D9 4F 63 00 6A 55 63 00 50 58 63 00 62 8F 63 00 83 8F 63 00 93 8F 63 00 AE 8F 63 00 00 00 00 00
///////////////////////////////////////////////////////////////////////////////////////////////
然后撤销所有修改,F9继续运行.来到OEP
如果不幸跑飞,也没有关系.反正表已经拿到了.
重新加载freestyle.exe,来到OEP处,停在这里.

第二次patch准备:

要得到两行代码及其地址的信息.
第一个就是上面提到的:
00DC2548    FF15 1890DE00   call    [DE9018] 
这个地址有可能变化,但是几率不大.

第二个有点烦:
用了多态技术,一旦重新加所在地址就会变.不过还好,变化的范围不是很大.

第二个代码是:
00FF00BA    9D              popfd
00FF00BB    5C              pop     esp
00FF00BC    FF6424 FC       JMP     DWORD PTR SS:[ESP-4]
不能直接搜索,因为用了多态技术,可能搜不到.
第一次找这个指令可以这样(以后就直接到附近找,注意识别花指令):

回忆在call xxxxxxxx上,下内存写入断点那里
我们断在了(不记得了就去看看前面):
//////////////////////////////////////////////
00DE5C9B    57              push    edi
00DE5C9C    6A 00           push    0
00DE5C9E    8D4D E0         lea     ecx, [ebp-20]
00DE5CA1    8B45 F4         mov     eax, [ebp-C]
00DE5CA4    8B40 3C         mov     eax, [eax+3C]
00DE5CA7    8B55 FC         mov     edx, [ebp-4]
00DE5CAA    E8 D1130000     call    00DE7080   ;**********
00DE5CAF    8945 FC         mov     [ebp-4], eax
00DE5CB2    8B45 E0         mov     eax, [ebp-20]
00DE5CB5    8B00            mov     eax, [eax]
00DE5CB7    E8 D0E6FFFF     call    00DE438C
00DE5CBC    8BD0            mov     edx, eax
00DE5CBE    0255 DF         add     dl, [ebp-21]
00DE5CC1    8B4D FC         mov     ecx, [ebp-4]
00DE5CC4    8B45 F4         mov     eax, [ebp-C]
00DE5CC7    E8 80040000     call    00DE614C
00DE5CCC    8945 FC         mov     [ebp-4], eax
00DE5CCF    8B45 F4         mov     eax, [ebp-C]
00DE5CD2    8B40 24         mov     eax, [eax+24]
00DE5CD5    8B55 F4         mov     edx, [ebp-C]
00DE5CD8    0382 E0000000   add     eax, [edx+E0]
00DE5CDE    0145 1C         add     [ebp+1C], eax
00DE5CE1    8B45 FC         mov     eax, [ebp-4]
00DE5CE4    2B45 1C         sub     eax, [ebp+1C]
00DE5CE7    83E8 05         sub     eax, 5
00DE5CEA    8B55 1C         mov     edx, [ebp+1C]
00DE5CED    42              inc     edx
00DE5CEE    8902            mov     [edx], eax     ;断在了这里!!!!
00DE5CF0    EB 01           jmp     short 00DE5CF3
00DE5CF2    E8 8B45F883     call    84D6A282
//////////////////////////////////////////////
这个时候用条件跟踪,当遇到POPFD的时候暂停.就能跟到
////////////////////////////////////////////
00FF00BA    9D              popfd
00FF00BB    5C              pop     esp
00FF00BC    FF6424 FC       JMP     DWORD PTR SS:[ESP-4]  ;纪录这行代码
////////////////////////////////////////


下面就是第二次patch:
重新载入,来到OEP ,先确定上面提到的两行代码的信息:
直接去00DC2548发现代码没有变:
00DC2548    FF15 1890DE00   call    [DE9018] 
然后去00FF00BC,应该已经变了.
果然JMP [ESP-4]变到了00FF00AE;

信息已经足够了.
开始写代码.

找代码段后面的空白处写patch代码,现在EIP指向OEP
///////////////////////////////////////////////////////////////////////////////////////

00651100      60            pushad
00651101      B9 10000201   mov     ecx, 1020010    ;这里的数填那张表保存的地址+10h
00651106      8B19          mov     ebx, [ecx]
00651108      83FB 00       cmp     ebx, 0
0065110B      74 15         je      short 00651122
0065110D      FFE3          jmp     ebx
0065110F      8B15 08000201 mov     edx, [1020008]
00651115      66:C703 FF15  mov     word ptr [ebx], 15FF
0065111A      8953 02       mov     [ebx+2], edx
0065111D      83C1 04       add     ecx, 4
00651120    ^ EB E4         jmp     short 00651106
00651122      33C0          xor     eax, eax
00651124      B0 E8         mov     al, 0E8
00651126      BF 00104000   mov     edi, <模块入口点>
0065112B      B9 00102500   mov     ecx, 251000                ;这里填代码段的大小
00651130      F2:AE         repne   scas byte ptr es:[edi]
00651132      83F9 00       cmp     ecx, 0
00651135      74 3C         je      short 00651173
00651137      8B1F          mov     ebx, [edi]
00651139      8D5C3B 04     lea     ebx, [ebx+edi+4]
0065113D      81FB 00104000 cmp     ebx, <模块入口点>
00651143    ^ 72 EB         jb      short 00651130
00651145      81FB 02106600 cmp     ebx, 00661002    ;这里填代码段结束的地址
0065114B    ^ 77 E3         ja      short 00651130
0065114D      66:813B FF15  cmp     word ptr [ebx], 15FF
00651152    ^ 75 DC         jnz     short 00651130
00651154      817B 02 00206>cmp     dword ptr [ebx+2], 00652000  ;IAT的起始地址
0065115B    ^ 72 D3         jb      short 00651130
0065115D      817B 02 78246>cmp     dword ptr [ebx+2], 00652478  ;IAT的结束地址-4
00651164    ^ 77 CA         ja      short 00651130
00651166      66:C703 FF25  mov     word ptr [ebx], 25FF
0065116B      83C7 04       add     edi, 4
0065116E      83E9 04       sub     ecx, 4
00651171    ^ EB BD         jmp     short 00651130
00651173      61            popad
.......

00651178      dd    83116500                  ;这里的数字就是下面函数的第一句指令的地址(小头顺序)
........

00651180      90            nop
00651181      90            nop
00651182      90            nop
00651183      60            pushad
00651184      8BC2          mov     eax, edx
00651186      B9 80040000   mov     ecx, 480  ;IAT的大小+4
0065118B      BF 00206500   mov     edi, 00652000  IAT的起始地址
00651190      F2:AF         repne   scas dword ptr es:[edi]
00651192      83EF 04       sub     edi, 4
00651195      893D 08000201 mov     [1020008], edi;保存表的地址+8
0065119B      61            popad
0065119C      FF15 1890DE00 call    [DE9018]      ;刚才00DC2548    FF15 1890DE00   call    [DE9018] 中被call寻址的地址
006511A2      C3            retn
006511A3      90            nop

/////////////////////////////////////////////////////////////////////////////////////
这些patch程序都是loveboom所写,根据需要修改相应的数值,如果不清楚有些数是怎么来的,可以去看看上面.和去看看loveboom的文章.
当然,问问别人是最快的解决方式.

然后:
把上面提到的
00DC2548    FF15 1890DE00   call    [DE9018]
代码改成:
00DC2548    FF15 1890DE00   call    [651178]
就是让他进入我们的patch代码的第二个函数。



写一段ODScript:
////////////////////////////////////////////////////////////////////////
//fixed aspr 2.x
var addr


start:
  run

l1:
  cmp eip,00FF00AE ;这里的数字是上面提到的jmp [esp-4]的地址,这里是00ff00AE
  jne l2
  mov addr,esp
  sub addr,4
  mov [addr],0065110F 这个数字是上面patch2代码中jmp ebx后面那句的地址,这里是
  jmp start

l2:
  ret
/////////////////////////////////////////////////////////////////////////
保存成OD脚本.
然后把EIP从哦OEP改向我们patch代码的第一句,这里是:

00651100      60            pushad

然后要在上面提到的jmp [esp-4]的地址,这里是00ff00AE上面下硬件执行断点。
其次,在patch结束句,这里是
00651173      61            popad上面
下F2断点。

最后运行脚本。等待一段时间,脚本运行完毕后,清除掉所有的修改。

dump,修复IAT.
就大功告成了。




PS:
我从看教程到脱壳成功一共用了30小时的时间,分4天。
前几个小时,都是学习PE文件。通过这次脱壳,让我对PE文件有了比较深的认识。原来都是一知半解。
脱壳对我等菜鸟来说是个很艰苦的工程,关键要有毅力和耐心。

现在目标是绕过加载HackShield.

  • 标 题:答复
  • 作 者:shoooo
  • 时 间:2006-02-08 12:25

5f8b30
5f8b36
5f8b3c
62c784
62c799
这五个是jmp [IAT] (ff 25)

  • 标 题:答复
  • 作 者:kanxue
  • 时 间:2006-02-08 13:25

引用: 最初由 Isaiah 发布
晕,动画难做啊。怪不得脱壳动画很少。
请问各位老大,怎么判断是call [IAT] 还是jmp [IAT]啊? 


就在shoooo文章里有:

引用:
先看a情况吧,进去后一路F8

    00C5B816        0255 DF       add dl,byte ptr ss:[ebp-21]
    00C5B819        8B4D FC       mov ecx,dword ptr ss:[ebp-4]          //这个点比较好

到了这里 [ebp-4C]是我们需要的导入函数的地址,dl中的值决定了是call(ff15)还是jmp(ff25)
dl中的值不同的程序是随机,找几个call 00EA0000进去出来看一下就知道当前的程序中哪个对应ff15,哪个对应ff25了
 

引用:
再来看看b情况,进去后也是一路F8

    00C5A7E7        3A45 EF       cmp al,byte ptr ss:[ebp-11]          //al和a情况中的dl一样,决定是ff15还是ff25
    00C5A7EA        0F85 9C000000 jnz 00C5A88C

    00C5A7F0        EB 01         jmp short 00C5A7F3