首页
论坛
专栏
课程

Unpack SafeDisc v2.90.40 (更新代码修复)

2005-8-9 00:54 12545

Unpack SafeDisc v2.90.40 (更新代码修复)

2005-8-9 00:54
12545
Unpacking SafeDisc v2.90.40 -- 樱花大战3简体中文标准版(如果你的HP不是满的话,还是先去喝几个血瓶吧)

[工具]:ODbyDYK,ImportREC,LordPE
大家都知道SafeDisc好一个用驱动来欺负我们的OD,但是我们真的会让OD被他欺负吗?

用OD载入Sakura3.exe。

020B305E >  55              push    ebp                <-OD停在了这里
020B305F    8BEC            mov     ebp, esp
020B3061    60              pushad                <-大家看,多么友好的提示。
020B3062    BB 5E300B02     mov     ebx, offset Sakura3.<ModuleEntryPoint>
020B3067    33C9            xor     ecx, ecx
020B3069    8A0D 3D300B02   mov     cl, byte ptr ds:[20B303D]
020B306F    85C9            test    ecx, ecx

向下找POPAD。一共找到了三个大家可以看看哪个比较象。

020B30BA    85C9            test    ecx, ecx
020B30BC    74 09           je      short Sakura3.020B30C7
020B30BE    61              popad
020B30BF    5D              pop     ebp
020B30C0    B8 00000000     mov     eax, 0
020B30C5  ^ EB 97           jmp     short Sakura3.<ModuleEntryPoint>

020B30CD    FFD0            call    eax
020B30CF    61              popad
020B30D0    5D              pop     ebp
020B30D1    EB 46           jmp     short Sakura3.020B3119
020B30D3    807C24 08 00    cmp     byte ptr ss:[esp+8], 0

020B3115    61              popad
020B3116    1360 0D         adc     esp, dword ptr ds:[eax+D]
020B3119  - E9 09BF5FFE     jmp     Sakura3.006AF027
020B311E    CC              int3

然后你小按几下F8,就会发现刚才的入口点被修正成了

020B305E >- E9 C4BF5FFE     jmp     Sakura3.006AF027
020B3063    5E              pop     esi
020B3064    300B            xor     byte ptr ds:[ebx], cl
020B3066    0233            add     dh, byte ptr ds:[ebx]

然而,事实证明,真正有用的是020B3119那里的跳转。
先说一下safedisc的运做过程,先把自己需要的连接库解压到临时目录,写为*.tmp文件。然后LoadLibrary。
再跳到载入的~df394b.tmp模块进行调试器检测,加载光盘检测模块,解压缩大部分主程序,再进行光盘检测向主程序写入剩下的一些数据,返回。

下面进入正题:

对 IsDebuggerPresent 下断(软件/硬件断点都行,但是我选择硬件断点,感觉保险些。下面相同)。显得有些多此一举,用插件能避开的还搞那么麻烦,而且我也用插件避开了,但是我们需要定位后面的调试器检测。

断下后取消硬件断点返回到这里:

100099EC    8BF0            mov     esi, eax
100099EE    66:85F6         test    si, si
100099F1    74 13           je      short ~df394b.10009A06
100099F3    E8 8278FFFF     call    ~df394b.1000127A
100099F8    66:8BF0         mov     si, ax
100099FB    66:F7DE         neg     si
100099FE    1BF6            sbb     esi, esi
10009A00    46              inc     esi
10009A01    66:85F6         test    si, si
10009A04    75 13           jnz     short ~df394b.10009A19
10009A06    8B4424 08       mov     eax, dword ptr ss:[esp+8]
10009A0A    8B08            mov     ecx, dword ptr ds:[eax]
10009A0C    81E1 EA894267   and     ecx, 674289EA
10009A12    8908            mov     dword ptr ds:[eax], ecx
10009A14    66:8BC6         mov     ax, si
10009A17    5E              pop     esi
10009A18    C3              retn        <-继续返回

到这里:

1000457A    83C4 04         add     esp, 4
1000457D    66:85C0         test    ax, ax
10004580    0F85 02010000   jnz     ~df394b.10004688
10004586    F6C3 04         test    bl, 4
10004589    76 12           jbe     short ~df394b.1000459D
1000458B    56              push    esi
1000458C    E8 3F530000     call    ~df394b.100098D0
10004591    83C4 04         add     esp, 4
10004594    66:85C0         test    ax, ax
10004597    0F85 EB000000   jnz     ~df394b.10004688
1000459D    F6C3 08         test    bl, 8
100045A0    76 12           jbe     short ~df394b.100045B4
100045A2    56              push    esi
100045A3    E8 58520000     call    ~df394b.10009800
100045A8    83C4 04         add     esp, 4
100045AB    66:85C0         test    ax, ax
100045AE    0F85 D4000000   jnz     ~df394b.10004688
100045B4    F7C3 00080000   test    ebx, 800
100045BA    76 12           jbe     short ~df394b.100045CE
100045BC    56              push    esi
100045BD    E8 5E510000     call    ~df394b.10009720
100045C2    83C4 04         add     esp, 4
100045C5    66:85C0         test    ax, ax
100045C8    0F85 BA000000   jnz     ~df394b.10004688        <-我们需要避开的是这个,不要让他跳转就行了。
100045CE    F7C3 00100000   test    ebx, 1000
100045D4    76 12           jbe     short ~df394b.100045E8
100045D6    56              push    esi
100045D7    E8 84500000     call    ~df394b.10009660
100045DC    83C4 04         add     esp, 4
100045DF    66:85C0         test    ax, ax
100045E2    0F85 A0000000   jnz     ~df394b.10004688
100045E8    F7C3 00200000   test    ebx, 2000
100045EE    76 12           jbe     short ~df394b.10004602
100045F0    56              push    esi
100045F1    E8 BA4F0000     call    ~df394b.100095B0
100045F6    83C4 04         add     esp, 4
100045F9    66:85C0         test    ax, ax
100045FC    0F85 86000000   jnz     ~df394b.10004688
10004602    F6C3 01         test    bl, 1
10004605    76 0E           jbe     short ~df394b.10004615
10004607    56              push    esi
10004608    E8 834E0000     call    ~df394b.10009490
1000460D    83C4 04         add     esp, 4
10004610    66:85C0         test    ax, ax
10004613    75 73           jnz     short ~df394b.10004688
10004615    F6C3 02         test    bl, 2
10004618    76 0E           jbe     short ~df394b.10004628
1000461A    56              push    esi
1000461B    E8 504D0000     call    ~df394b.10009370
10004620    83C4 04         add     esp, 4
10004623    66:85C0         test    ax, ax
10004626    75 60           jnz     short ~df394b.10004688
10004628    F6C3 10         test    bl, 10
1000462B    76 0E           jbe     short ~df394b.1000463B
1000462D    56              push    esi
1000462E    E8 DD4C0000     call    ~df394b.10009310
10004633    83C4 04         add     esp, 4
10004636    66:85C0         test    ax, ax
10004639    75 4D           jnz     short ~df394b.10004688
1000463B    F6C3 20         test    bl, 20
1000463E    76 0E           jbe     short ~df394b.1000464E
10004640    56              push    esi
10004641    E8 1A4C0000     call    ~df394b.10009260
10004646    83C4 04         add     esp, 4
10004649    66:85C0         test    ax, ax
1000464C    75 3A           jnz     short ~df394b.10004688
1000464E    F6C3 40         test    bl, 40
10004651    76 0E           jbe     short ~df394b.10004661
10004653    56              push    esi
10004654    E8 D74A0000     call    ~df394b.10009130
10004659    83C4 04         add     esp, 4
1000465C    66:85C0         test    ax, ax
1000465F    75 27           jnz     short ~df394b.10004688
10004661    F7C3 80000000   test    ebx, 80
10004667    76 0E           jbe     short ~df394b.10004677
10004669    56              push    esi
1000466A    E8 B1490000     call    ~df394b.10009020
1000466F    83C4 04         add     esp, 4
10004672    66:85C0         test    ax, ax
10004675    75 11           jnz     short ~df394b.10004688
10004677    F7C3 00400000   test    ebx, 4000
1000467D    76 09           jbe     short ~df394b.10004688
1000467F    56              push    esi
10004680    E8 CB480000     call    ~df394b.10008F50
10004685    83C4 04         add     esp, 4
10004688    5E              pop     esi
10004689    5B              pop     ebx
1000468A    C3              retn

注意:由于我的OD是修改版,所以只需要改一个跳转。你自己调试时,务必不能让其中任何一个jnz跳下去。改的时候,只能修改标志位Z=1。因为后面这个库还有模块完整性的检查。

然后,我们走啊走,走到这里:

1000357D    FF75 F8         push    dword ptr ss:[ebp-8]                           ; ~df394b.10000000
10003580    E8 20750100     call    ~df394b.1001AAA5     <-进入这个call
10003585    8B43 14         mov     eax, dword ptr ds:[ebx+14]
10003588    59              pop     ecx

1001AAA5                      55                push ebp
1001AAA6                      8BEC              mov ebp,esp
1001AAA8                      81EC 10020000     sub esp,210
1001AAAE                      833D 3C220610 00  cmp dword ptr ds:[1006223C],0 <-我们修改这里,把1006223c处的内存清0。
1001AAB5                      53                push ebx
1001AAB6                      0F84 EF000000     je ~df394b.1001ABAB

走啊走,继续一路返回就可以到入口点了:

006AF027    55              push    ebp
006AF028    8BEC            mov     ebp, esp
006AF02A    6A FF           push    -1
006AF02C    68 607DF101     push    Sakura3.01F17D60
006AF031    68 780A6B00     push    Sakura3.006B0A78
006AF036    64:A1 00000000  mov     eax, dword ptr fs:[0]
006AF03C    50              push    eax
006AF03D    64:8925 0000000>mov     dword ptr fs:[0], esp
006AF044    83EC 58         sub     esp, 58
006AF047    53              push    ebx
006AF048    56              push    esi
006AF049    57              push    edi
006AF04A    8965 E8         mov     dword ptr ss:[ebp-18], esp
006AF04D    FF15 6081EC01   call    dword ptr ds:[1EC8160]
006AF053    33D2            xor     edx, edx
006AF055    8AD4            mov     dl, ah
006AF057    8915 04BD0A02   mov     dword ptr ds:[20ABD04], edx
006AF05D    8BC8            mov     ecx, eax
006AF05F    81E1 FF000000   and     ecx, 0FF
006AF065    890D 00BD0A02   mov     dword ptr ds:[20ABD00], ecx
006AF06B    C1E1 08         shl     ecx, 8
006AF06E    03CA            add     ecx, edx
006AF070    890D FCBC0A02   mov     dword ptr ds:[20ABCFC], ecx
006AF076    C1E8 10         shr     eax, 10
006AF079    A3 F8BC0A02     mov     dword ptr ds:[20ABCF8], eax
006AF07E    6A 01           push    1
006AF080    E8 A47BD5FF     call    Sakura3.00406C29

小结:现在我们第一次的路程结束了。我们得到了什么?
我们得到了避开调试器检测的方法和调用驱动的过程以及入口点的位置,但是我们却没有得到dump文件和完美的IAT。

继续。
我们现在需要正确代码段。因为如果你细心的看下代码的话,你会发现一些这种代码。
00688CF2                      85C0              test eax,eax
00688CF4                      CC                int3 <-正常的程序会有这种东西吗?
00688CF5                      CC                int3
00688CF6                      8B4424 10         mov eax,dword ptr ss:[esp+10]
00688CFA                      8B4D 04           mov ecx,dword ptr ss:[ebp+4]
00688CFD                      3BC1              cmp eax,ecx
00688CFF                    ^ 0F8C D4FEFFFF     jl sakuara3.00688BD9

但是怎么得到呢?不能通过调试器,OD不能进驱动,SI被防得又太严。
其实非常的简单,我们只需要运行游戏,在进入游戏后按下windows徽标键强行弹出,再用LordPE把他的代码段dump下来就行了。因为这样做,我们没有对他作过任何手脚,所以它就会安心的写下所有的代码。上面的两个CC也会被一个短距跳转所取代。但后我们只要在OD到达入口点前一点的位置把他作为备份载入即可。

下面是IAT了。在现在的入口点我们可以看到部分Call []后面并没有写出是什么函数。入口点之后第一个这种调用应该是GetVision。那么我们进入看看:
02F43CE4                      68 A310EABF       push BFEA10A3
02F43CE9                      9C                pushfd
02F43CEA                      60                pushad
02F43CEB                      54                push esp
02F43CEC                      68 243DF402       push 2F43D24
02F43CF1                      E8 9F06110D       call ~df394b.10054395 <-进入
02F43CF6                      83C4 08           add esp,8
02F43CF9                      6A 00             push 0
02F43CFB                      58                pop eax
02F43CFC                      61                popad
02F43CFD                      9D                popfd
02F43CFE                      C3                retn

10054744                      FF15 50700510     call near dword ptr ds:[<&KERNEL32.SetEvent>>; kernel32.SetEvent
1005474A                      8B65 0C           mov esp,dword ptr ss:[ebp+C]
1005474D                      61                popad
1005474E                      9D                popfd
1005474F                      C3                retn

我们在第二个SetEcent后的retn处下断,运行。停下后看看堆栈:
0012FF44   77E5D142  kernel32.GetVersion <-果然
0012FF48   006AF053  返回到 sakuara3.006AF053 来自 02F43CE4
0012FF4C   77F517E6  返回到 ntdll.77F517E6 来自 ntdll.77F78C4E
0012FF50   77F51778  返回到 ntdll.77F51778 来自 ntdll.77F517B5

这就是SafeDisc对IAT加密形式中一种。尽管这种方法很难手工修复,但是我们发现还是有些IAT是没有被加密的。所以我们就要从这里下手。
重新开始。我们先对其中一个没加密的IAT的位置下硬件断点(软件断点不能下在内存单元上,内存断点会被它在修改内存属性的时候废掉)。运行,避开检测,得到了地址。然后再重来跟踪这个地址,最后我们得到了这些代码。
(这串代码并不好找,这里给大家一个带有人品问题的找法。用你的停在上面提到的要修改的避开调试器检测的跳转的地址+4FAC0,然后g 这个地址之后,在上下的代码段中找一找,一般就能找到了。用NFSU2试了下,还是比较接近的。)
10054088                      8B45 F4           mov eax,dword ptr ss:[ebp-C]
1005408B                      40                inc eax
1005408C                      8945 F4           mov dword ptr ss:[ebp-C],eax
1005408F                      8B45 F4           mov eax,dword ptr ss:[ebp-C]
10054092                      3B45 14           cmp eax,dword ptr ss:[ebp+14]
10054095                      73 55             jnb short ~df394b.100540EC
10054097                      8B45 F4           mov eax,dword ptr ss:[ebp-C]
1005409A                      C1E8 03           shr eax,3
1005409D                      8B4D F8           mov ecx,dword ptr ss:[ebp-8]
100540A0                      8B15 6C490810     mov edx,dword ptr ds:[1008496C]
100540A6                      8B0C8A            mov ecx,dword ptr ds:[edx+ecx*4]
100540A9                      0FB60401          movzx eax,byte ptr ds:[ecx+eax]
100540AD                      8B4D F4           mov ecx,dword ptr ss:[ebp-C]
100540B0                      83E1 07           and ecx,7
100540B3                      6A 01             push 1
100540B5                      5A                pop edx
100540B6                      D3E2              shl edx,cl
100540B8                      23C2              and eax,edx
100540BA                      85C0              test eax,eax <-关键,下面不跳的话就会完美很多。。。
100540BC                      75 2C             jnz short ~df394b.100540EA
100540BE                      8B45 F8           mov eax,dword ptr ss:[ebp-8]
100540C1                      69C0 8D000000     imul eax,eax,8D
100540C7                      8B0D 70490810     mov ecx,dword ptr ds:[10084970]
100540CD                      8B4401 4C         mov eax,dword ptr ds:[ecx+eax+4C]
100540D1                      8B4D F4           mov ecx,dword ptr ss:[ebp-C]
100540D4                      FF3488            push dword ptr ds:[eax+ecx*4]
100540D7                      FF75 F8           push dword ptr ss:[ebp-8]
100540DA                      E8 DB000000       call ~df394b.100541BA
100540DF                      59                pop ecx
100540E0                      59                pop ecx
100540E1                      8B4D F4           mov ecx,dword ptr ss:[ebp-C]
100540E4                      8B55 18           mov edx,dword ptr ss:[ebp+18]
100540E7                      89048A            mov dword ptr ds:[edx+ecx*4],eax
100540EA                    ^ EB 9C             jmp short ~df394b.10054088

于是我们修改100540B8修改为Xor eax,eax,然后运行到入口点,我们发现了几乎完美的IAT。。。
打开ImortREC取得IAT,发现还有1个无效的指针:[1ec8064]=02f310e7。
我们查找命令Call [1ec8064]。找到006ac1c7。新建EIP跟的这个是GetTickCount。
现在IAT修复了。似乎所有的任务都完成了。但是现实却不是这样,SafeDisc还用jmp [eax],jmp ********加密了一些函数和过程的调用。

小结:到这里第二步也完成了,我们得到了几乎完美的文件。
下面就剩文件的修复了,继续。

今天下午,我着手开始修复代码,一开始我以为要修复的代码不会很多,所以就手工一个个的修复。

我们打开两个OD,一个直接走到入口点(一下简称B),另一个修复IAT后再走到入口点(一下简称A)。

然后我们进入B的入口点之后的第一个调用,就是前面提到的GetVision的调用,到达这里

1005472F                       E8 AA14FDFF       call ~df394b.10025BDE
10054734                       59                pop ecx
10054735                       F0:FF0D 646C0610  lock dec dword ptr ds:[10066C64]
1005473C                       78 0C             js short ~df394b.1005474A <-我们在这里Patch
1005473E                       FF35 D8490810     push dword ptr ds:[100849D8]
10054744                       FF15 50700510     call near dword ptr ds:[<&KERNEL32.SetE>; kernel32.SetEvent
1005474A                       8B65 0C           mov esp,dword ptr ss:[ebp+C]
1005474D                       61                popad
1005474E                       9D                popfd
1005474F                       C3                retn
10054750                       F0:FF0D 646C0610  lock dec dword ptr ds:[10066C64]
10054757                       78 0C             js short ~df394b.10054765
10054759                       FF35 D8490810     push dword ptr ds:[100849D8]
1005475F                       FF15 50700510     call near dword ptr ds:[<&KERNEL32.SetE>; kernel32.SetEvent
10054765                       5F                pop edi

Patch之后
1005473C                       8B65 0C           mov esp,dword ptr ss:[ebp+C]
1005473F                       61                popad
10054740                       9D                popfd
10054741                       83C4 04           add esp,4<-在这里下断点(软件断点就够了)
10054744                       C3                retn
10054745                       90                nop
10054746                       90                nop
10054747                       90                nop
10054748                       90                nop
10054749                       90                nop

然后运行,暂停时堆栈的第一行就是IAT的名称和地址。
我们在进入A,比较一下这两个IAT是不是一样,不一样就在IAT表中找一个和他一样的,再把这个调用的内存地址修改成我们需要的。为什么要这样呢?因为SafeDisc加密的部分IAT调用不具有唯一性。就是说在不同的地方调用同一个内存地址,所获得的IAT并不一定是一样的。
我们就从00401000的地方开始。查找二进制字符FF15,然后开他调用的内存地址,如果是01EC8XXX那就是我们要的。在B中的那里新建EIP,然后运行,断下时和A中显示的IAT作一下比较,不同的就在A的IAT表中找一个和B中是计算出来的IAT一样的内存地址改写到A中的调用里去。然后循环处理整个代码段知道找不到为止。然后还有E9????01(要是跨段跳的那种),和一个Call的重定向。

不过做了几个之后,我发现自己错了,结果我一下午的时间就这样报销了。不过大家可以看看修复过的地方吧,应该会有某种比较深刻的印象的。。。

Call加密系列
006AF080        call sakuara3.006B0CE0
可能还有,但是我没心情看代码了,下一次测试一下就知道了。

Call []加密系列
0057830A        call near dword ptr ds:[1EC8054]        ; GDI32.CreateDIBSection
005804CA        call near dword ptr ds:[1EC8258]        ; ole32.CoCreateInstance
00583BCA        call near dword ptr ds:[1EC8054]        ; GDI32.CreateDIBSection
0058808A        call near dword ptr ds:[1EC8150]        ; ntdll.RtlUnwind
0058C9CA        call near dword ptr ds:[1EC8038]        ; GDI32.GetObjectA
0058EF3A        call near dword ptr ds:[1EC81CC]        ; USER32.GetDC
005A91CA        call near dword ptr ds:[1EC81EC]        ; USER32.ShowWindow
005ABE4A        call near dword ptr ds:[1EC8260]        ; ole32.CoTaskMemAlloc
005C7D3A        call near dword ptr ds:[1EC8258]        ; ole32.CoCreateInstance
005D99AA        call near dword ptr ds:[1EC8048]        ; GDI32.SelectObject
0061566A        call near dword ptr ds:[1EC8170]        ; kernel32.TlsAlloc
006156AA        call near dword ptr ds:[1EC8260]        ; ole32.CoTaskMemAlloc
00615BCA        call near dword ptr ds:[1EC81CC]        ; USER32.GetDC
0061B61A        call near dword ptr ds:[1EC803C]        ; GDI32.DeleteObject
0063D47A        call near dword ptr ds:[1EC820C]        ; USER32.GetQueueStatus
0063FCEA        call near dword ptr ds:[1EC802C]        ; GDI32.GetDeviceCaps
00641A2A        call near dword ptr ds:[1EC80B0]        ; kernel32.WaitForMultipleObjects
00642E8A        call near dword ptr ds:[1EC8268]        ; ole32.CoInitialize
00648E5A        call near dword ptr ds:[1EC8048]        ; GDI32.SelectObject
0064B96A        call near dword ptr ds:[1EC80D0]        ; kernel32.LCMapStringA
0064C72A        call near dword ptr ds:[1EC8268]        ; ole32.CoInitialize
0064E77A        call near dword ptr ds:[1EC80D0]        ; kernel32.LCMapStringA
0064EE0A        call near dword ptr ds:[1EC8258]        ; ole32.CoCreateInstance
00659AEA        call near dword ptr ds:[1EC8090]        ; kernel32.DeleteFileA
00666E3A        call near dword ptr ds:[1EC80B0]        ; kernel32.WaitForMultipleObjects
0066703A        call near dword ptr ds:[1EC8258]        ; ole32.CoCreateInstance
0066899A        call near dword ptr ds:[1EC80B0]        ; kernel32.WaitForMultipleObjects
00668CBA        call near dword ptr ds:[1EC8268]        ; ole32.CoInitialize
00668DDA        call near dword ptr ds:[1EC8204]        ; USER32.DrawTextW
0066948A        call near dword ptr ds:[1EC8044]        ; GDI32.CreateCompatibleDC
0066AFB0        call near dword ptr ds:[1EC8128]        ; kernel32.ReadFile
0066B0A0        call near dword ptr ds:[1EC80B4]        ; kernel32.SetFilePointer
0066DD4A        call near dword ptr ds:[1EC8024]        ; GDI32.SetBkColor
00671078        call near dword ptr ds:[1EC81F4]        ; USER32.SetCursorPos
00671418        call near dword ptr ds:[1EC80AC]        ; kernel32.MultiByteToWideChar
006717CA        call near dword ptr ds:[1EC81E4]        ; USER32.SetFocus
0068167A        call near dword ptr ds:[1EC80B0]        ; kernel32.WaitForMultipleObjects
00682FAA        call near dword ptr ds:[1EC81CC]        ; USER32.GetDC
006880C4        call near dword ptr ds:[1EC8128]        ; kernel32.ReadFile
00688142        call near dword ptr ds:[1EC8098]        ; kernel32.CreateFileA
0068817E        call near dword ptr ds:[1EC80A4]        ; kernel32.CloseHandle
00688265        call near dword ptr ds:[1EC8098]        ; kernel32.CreateFileA
006882AA        call near dword ptr ds:[1EC80B8]        ; kernel32.GetFileTime
006882BA        call near dword ptr ds:[1EC80BC]        ; kernel32.FileTimeToSystemTime
006882F4        call near dword ptr ds:[1EC80A4]        ; kernel32.CloseHandle
00688362        call near dword ptr ds:[1EC8098]        ; kernel32.CreateFileA
0068837F        call near dword ptr ds:[1EC8094]        ; kernel32.GetFileSize
00688395        call near dword ptr ds:[1EC80A4]        ; kernel32.CloseHandle
006884A6        call near dword ptr ds:[1EC8078]        ; kernel32.FindClose
006884C1        call near dword ptr ds:[1EC8074]        ; kernel32.FindFirstFileA
0068859F        call near dword ptr ds:[1EC8078]        ; kernel32.FindClose
00688951        call near dword ptr ds:[1EC8128]        ; kernel32.ReadFile
006889A8        call near dword ptr ds:[1EC809C]        ; kernel32.WriteFile
00688CEC        call near dword ptr ds:[1EC808C]        ; kernel32.FindNextFileA
00688EA1        call near dword ptr ds:[1EC8098]        ; kernel32.CreateFileA
00688F4A        call near dword ptr ds:[1EC8260]        ; ole32.CoTaskMemAlloc
006894C4        call near dword ptr ds:[1EC8080]        ; kernel32.WaitForSingleObject
0068A230        call near dword ptr ds:[1EC8064]        ; kernel32.GetTickCount
0068A2A0        call near dword ptr ds:[1EC8064]        ; kernel32.GetTickCount
0068A3C0        call near dword ptr ds:[1EC8064]        ; kernel32.GetTickCount
0068A430        call near dword ptr ds:[1EC8064]        ; kernel32.GetTickCount
0068A490        call near dword ptr ds:[1EC822C]        ; USER32.DestroyWindow
0068A508        call near dword ptr ds:[1EC806C]        ; ntdll.RtlGetLastWin32Error
0068A5AD        call near dword ptr ds:[1EC8268]        ; ole32.CoInitialize
0068A5B4        call near dword ptr ds:[1EC81CC]        ; USER32.GetDC
0068A5ED        call near dword ptr ds:[1EC821C]        ; USER32.ReleaseDC
0068A65B        call near dword ptr ds:[1EC8220]        ; USER32.AdjustWindowRect
0068A6C1        call near dword ptr ds:[1EC8228]        ; USER32.UpdateWindow
0068A8B6        call near dword ptr ds:[1EC81C8]        ; USER32.PostQuitMessage
0068A95F        call near dword ptr ds:[1EC81E8]        ; USER32.DefWindowProcA
0068A992        call near dword ptr ds:[1EC81E8]        ; USER32.DefWindowProcA
0068E3D9        call near dword ptr ds:[1EC803C]        ; GDI32.DeleteObject
0068F50F        call near dword ptr ds:[1EC800C]        ; ADVAPI32.RegOpenKeyA
0068F78C        call near dword ptr ds:[1EC8100]        ; kernel32.IsProcessorFeaturePresent
0068FBE8        call near dword ptr ds:[1EC8048]        ; GDI32.SelectObject
0068FD10        call near dword ptr ds:[1EC8024]        ; GDI32.SetBkColor
0068FD2D        call near dword ptr ds:[1EC8048]        ; GDI32.SelectObject
0068FE34        call near dword ptr ds:[1EC8204]        ; USER32.DrawTextW
0068FE3C        call near dword ptr ds:[1EC8200]        ; USER32.DrawTextA
0068FF73        call near dword ptr ds:[1EC8048]        ; GDI32.SelectObject
0069000B        call near dword ptr ds:[1EC8200]        ; USER32.DrawTextA
006A6F2B        call near dword ptr ds:[1EC8104]        ; kernel32.SetEvent
006A71EB        call near dword ptr ds:[1EC8118]        ; kernel32.ResetEvent
006A71FA        call near dword ptr ds:[1EC8104]        ; kernel32.SetEvent
006A72BF        call near dword ptr ds:[1EC820C]        ; USER32.GetQueueStatus
006A72DA        call near dword ptr ds:[1EC8208]        ; USER32.PostThreadMessageA
006A739E        call near dword ptr ds:[1EC8104]        ; kernel32.SetEvent
006A73AE        call near dword ptr ds:[1EC8118]        ; kernel32.ResetEvent
006A7491        call near dword ptr ds:[1EC810C]        ; ntdll.RtlDeleteCriticalSection
006A785C        call near dword ptr ds:[1EC8104]        ; kernel32.SetEvent
006A7A60        call near dword ptr ds:[1EC8118]        ; kernel32.ResetEvent
006A7E35        call near dword ptr ds:[1EC8104]        ; kernel32.SetEvent
006A92DA        call near dword ptr ds:[1EC8124]        ; kernel32.MulDiv
006A9663        call near dword ptr ds:[1EC8258]        ; ole32.CoCreateInstance
006A9E38        call near dword ptr ds:[1EC8258]        ; ole32.CoCreateInstance
006A9E5F        call near dword ptr ds:[1EC8254]        ; ole32.CoUninitialize
006A9EA9        call near dword ptr ds:[1EC8258]        ; ole32.CoCreateInstance
006A9ED4        call near dword ptr ds:[1EC8254]        ; ole32.CoUninitialize
006AA0A8        call near dword ptr ds:[1EC80C0]        ; kernel32.InterlockedIncrement
006AA47A        call near dword ptr ds:[1EC812C]        ; kernel32.InterlockedDecrement
006AA612        call near dword ptr ds:[1EC8260]        ; ole32.CoTaskMemAlloc
006ABA68        call near dword ptr ds:[1EC80C0]        ; kernel32.InterlockedIncrement
006ABA85        call near dword ptr ds:[1EC812C]        ; kernel32.InterlockedDecrement
006ABA99        call near dword ptr ds:[1EC80CC]        ; kernel32.FreeLibrary
006ABB69        call near dword ptr ds:[1EC80C0]        ; kernel32.InterlockedIncrement
006AC0E1        call near dword ptr ds:[1EC8064]        ; kernel32.GetTickCount
006AC101        call near dword ptr ds:[1EC80B0]        ; kernel32.WaitForMultipleObjects
006AC22E        call near dword ptr ds:[1EC80B0]        ; kernel32.WaitForMultipleObjects
006AC250        call near dword ptr ds:[1EC8148]        ; kernel32.GetThreadPriority
006AC2C0        call near dword ptr ds:[1EC811C]        ; kernel32.GetCurrentThreadId
006AC37B        call near dword ptr ds:[1EC806C]        ; ntdll.RtlGetLastWin32Error
006AC3D6        call near dword ptr ds:[1EC806C]        ;  ntdll.RtlGetLastWin32Error
006ACFD2        call near dword ptr ds:[1EC8108]        ; kernel32.InitializeCriticalSection
006AD73F        call near dword ptr ds:[1EC8260]        ; ole32.CoTaskMemAlloc
006AF0FB        call near dword ptr ds:[1EC80FC]        ; kernel32.GetModuleHandleA
006AF3EA        call near dword ptr ds:[1EC8168]        ; kernel32.TerminateProcess
006B04D2        call near dword ptr ds:[1EC8170]        ; kernel32.TlsAlloc
006B050B        call near dword ptr ds:[1EC811C]        ; kernel32.GetCurrentThreadId
006B0578        call near dword ptr ds:[1EC811C]        ; kernel32.GetCurrentThreadId
006B058F        call near dword ptr ds:[1EC8178]        ; ntdll.RtlSetLastWin32Error
006B0749        call near dword ptr ds:[1EC8154]        ; ntdll.RtlAllocateHeap
006B07A0        call near dword ptr ds:[1EC8180]        ; ntdll.RtlReAllocateHeap
006B08B1        call near dword ptr ds:[1EC8154]        ; ntdll.RtlAllocateHeap
006B0A49        call near dword ptr ds:[1EC8184]        ; ntdll.RtlSizeHeap
006B0B75        call near dword ptr ds:[1EC80FC]        ; kernel32.GetModuleHandleA
006B0C4C        call near dword ptr ds:[1EC8188]        ; kernel32.GetModuleFileNameA
006B0CF1        call near dword ptr ds:[1EC8194]        ; kernel32.HeapCreate
006B1458        call near dword ptr ds:[1EC8134]        ; kernel32.VirtualAlloc
006B14E4        call near dword ptr ds:[1EC8134]        ; kernel32.VirtualAlloc
006B18A5        call near dword ptr ds:[1EC8154]        ; ntdll.RtlAllocateHeap
006B19A4        call near dword ptr ds:[1EC80C4]        ; kernel32.VirtualFree
006B19D7        call near dword ptr ds:[1EC80C4]        ; kernel32.VirtualFree
006B5800        call near dword ptr ds:[1EC81A0]        ; kernel32.UnhandledExceptionFilter
006B5C70        call near dword ptr ds:[1EC81A8]        ; kernel32.FreeEnvironmentStringsW
006B5DDD        call near dword ptr ds:[1EC81BC]        ; kernel32.GetFileType
006B5E4E        call near dword ptr ds:[1EC81BC]        ; kernel32.GetFileType
006B5E85        call near dword ptr ds:[1EC81B4]        ; kernel32.SetHandleCount
006B5F36        call near dword ptr ds:[1EC8188]        ; kernel32.GetModuleFileNameA
006B600C        call near dword ptr ds:[1EC81B8]        ; kernel32.GetStdHandle
006B67A9        call near dword ptr ds:[1EC80C0]        ; kernel32.InterlockedIncrement
006B6E98        call near dword ptr ds:[1EC8174]        ; kernel32.SetUnhandledExceptionFilter
006B724C        call near dword ptr ds:[1EC806C]        ; ntdll.RtlGetLastWin32Error
006B73B4        call near dword ptr ds:[1EC809C]        ; kernel32.WriteFile
006B742E        call near dword ptr ds:[1EC806C]        ; ntdll.RtlGetLastWin32Error
006B7651        call near dword ptr ds:[1EC80C0]        ; kernel32.InterlockedIncrement
006B76E7        call near dword ptr ds:[1EC80E8]        ; kernel32.WideCharToMultiByte
006B7760        call near dword ptr ds:[1EC80DC]        ; kernel32.GetStringTypeA
006B7794        call near dword ptr ds:[1EC80DC]        ; kernel32.GetStringTypeA
006B77CC        call near dword ptr ds:[1EC80AC]        ; kernel32.MultiByteToWideChar
006B7834        call near dword ptr ds:[1EC80D8]        ; kernel32.GetStringTypeW
006B7DFD        call near dword ptr ds:[1EC80C0]        ; kernel32.InterlockedIncrement
006B7F07        call near dword ptr ds:[1EC80AC]        ; kernel32.MultiByteToWideChar
006B84AC        call near dword ptr ds:[1EC80F8]        ; kernel32.LoadLibraryA
006B891E        call near dword ptr ds:[1EC80D0]        ; kernel32.LCMapStringA
006B8967        call near dword ptr ds:[1EC80D0]        ; kernel32.LCMapStringA
006B899F        call near dword ptr ds:[1EC80AC]        ; kernel32.MultiByteToWideChar
006B89F7        call near dword ptr ds:[1EC80AC]        ; kernel32.MultiByteToWideChar
006B8F69        call near dword ptr ds:[1EC80C0]        ; kernel32.InterlockedIncrement
006B917C        call near dword ptr ds:[1EC8108]        ; kernel32.InitializeCriticalSection
006B920D        call near dword ptr ds:[1EC810C]        ; ntdll.RtlDeleteCriticalSection
006B96F3        call near dword ptr ds:[1EC8128]        ; kernel32.ReadFile
006B97CD        call near dword ptr ds:[1EC806C]        ; ntdll.RtlGetLastWin32Error
006B9920        call near dword ptr ds:[1EC806C]        ; ntdll.RtlGetLastWin32Error

JMP加密系列
0066B050        call near dword ptr ds:[1EC8128]        ; kernel32.ReadFile
00688177        call near dword ptr ds:[1EC8128]        ; kernel32.ReadFile
00688709        call near dword ptr ds:[1EC8074]        ; kernel32.FindFirstFileA
0068A4FE        call near dword ptr ds:[1EC8068]        ; kernel32.CreateMutexA
0068A56B        call near dword ptr ds:[1EC81D4]        ; USER32.LoadCursorA
0068A6B5        call near dword ptr ds:[1EC81EC]        ; USER32.ShowWindow
0068A930        call near dword ptr ds:[1EC81E8]        ; USER32.DefWindowProcA
0068AC10        call near dword ptr ds:[1EC8038]        ; GDI32.GetObjectA
00690003        call near dword ptr ds:[1EC8204]        ; USER32.DrawTextW
006A72DA        call near dword ptr ds:[1EC8208]        ; USER32.PostThreadMessageA
006A7361        call near dword ptr ds:[1EC8104]        ; kernel32.SetEvent
006A788D        call near dword ptr ds:[1EC8118]        ; kernel32.ResetEvent
006A9E90        call near dword ptr ds:[1EC8268]        ; ole32.CoInitialize
006AA0CA        call near dword ptr ds:[1EC812C]        ; kernel32.InterlockedDecrement
006AF839        call near dword ptr ds:[1EC80F4]        ; kernel32.GetProcAddress
006B0567        call near dword ptr ds:[1EC816C]        ; kernel32.TlsSetValue
006B08F2        call near dword ptr ds:[1EC8180]        ; ntdll.RtlReAllocateHeap
006B0BEC        call near dword ptr ds:[1EC818C]        ; kernel32.GetEnvironmentVariableA
006B5978        call near dword ptr ds:[1EC8188]        ; kernel32.GetModuleFileNameA
006B7401        call near dword ptr ds:[1EC806C]        ; ntdll.RtlGetLastWin32Error
006B7419        call near dword ptr ds:[1EC809C]        ; kernel32.WriteFile

全部搞完之后,我决定,如果下次还要搞这种东西话,我一定要写Patch代码。还好樱花大战3的代码段只有2C700H。。。(如果哪位高手写出来的话,我也想要一份^_^)
现在我们要把A的00401000段和01EC8000段备份下来。不然以后要在用的话会死人的。

小结:第三部分完成了,我们把能看到的代码全部修补了,下面就等我硬盘有空间的时候把游戏装上测试了,毕竟这个游戏还是有3G那么大的。
神啊,祝福我把~~~~!!!

[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最新回复 (25)
fly 85 2005-8-9 08:55
2
0
继续
SafeDisc目前公开的教程很少
duzaizhe 2005-8-9 09:46
3
0

支持
softworm 30 2005-8-9 12:51
4
0
学习学习
无聊的菜鸟 9 2005-8-9 18:33
5
0
感谢各位关注,今天更新了代码修复。我也要继续努力,争取早日摆平它。
simonzh2000 24 2005-8-9 18:42
6
0
继续努力啊.
脱壳请教 1 2005-8-9 19:15
7
0
我们现在需要正确代码段。因为如果你细心的看下代码的话,你会发现一些这种代码。
00688CF2                      85C0              test eax,eax
00688CF4                      CC                int3 <-正常的程序会有这种东西吗?
00688CF5                      CC                int3
00688CF6                      8B4424 10         mov eax,dword ptr ss:[esp+10]
00688CFA                      8B4D 04           mov ecx,dword ptr ss:[ebp+4]
00688CFD                      3BC1              cmp eax,ecx
00688CFF                    ^ 0F8C D4FEFFFF     jl sakuara3.00688BD9

但是怎么得到呢?不能通过调试器,OD不能进驱动,SI被防得又太严。
其实非常的简单,我们只需要运行游戏,在进入游戏后按下windows徽标键强行弹出,再用LordPE把他的代码段dump下来就行了。因为这样做,我们没有对他作过任何手脚,所以它就会安心的写下所有的代码。上面的两个CC也会被一个短距跳转所取代。但后我们只要在OD到达入口点前一点的位置把他作为备份载入即可。
===========================================================
这段我感觉有问题,int 3是动态解码部分,如果同一个地址的INT 3不运行10次以上,是不会把正确的代码写回去的~
难道我的是v3.2版,v2.9就简单很多?

还有IAT问题~
得到没有问题的IAT很容易
但是v3.2版里的IAT不是固定的
比如:
401000    call [0x111111]  是call getversion
但到了另外的地址:
402000    call [0x111111]  变成了call  createfilea

这个方式的IAT乱序我还没找到很好的解决方法,唯一的方法只有更总程序内所有调用IAT的地方了
syscom 6 2005-8-9 23:20
8
0
加油,腠然大家方法,不同...可是能用就好了..cc
  我是直接? patch,重建 import tab,在 dump,fix iat,就 ok了~!!!

佩例:原? code

451320-  call [12345678] --->CreatFileA

451449-  call [12345678] --->GetVersion

重建 import and code

451320- call [5b41000] ----> CreatFileA

451449- call [5b41004] ----> GetVersion

呃?就能成功,unpack SafeDisc OK~!!!
laoqian 8 2005-8-10 10:42
9
0
不管怎么说,加精再说啊!
终于有人公开研究它了,等破全了,我要开始学脱壳,然后学脱SafeDisc――好漫长的路啊!
北斗数据 2005-8-10 12:11
10
0
支持!!!
无聊的菜鸟 9 2005-8-10 20:19
11
0
昨天测试了,没有成功。
还有好多的CC,虽然现在少了一点。
还有似乎SafeDisc还初始化了一些数据。。。
看来还要继续修复代码了。
而且即将无奈的安装SoftIce
fly 85 2005-8-10 20:27
12
0
加油,呵呵
完成后加精
syscom 6 2005-8-10 22:33
13
0
最初由 无聊的菜鸟 发布
昨天测试了,没有成功。
还有好多的CC,虽然现在少了一点。
还有似乎SafeDisc还初始化了一些数据。。。
看来还要继续修复代码了。
而且即将无奈的安装SoftIce


cc..加油,SafeDisc,每?版本,都有一?,小?化....
可是,大体上,是不?的,只要抓到,重?,就不膣解?了

我有成功,解咿 ver 3.3 ,3.3.以後的板本,就?化加大了...

我? post 上?,斤大家,?考看看,大家多多指?....
无聊的菜鸟 9 2005-8-10 23:15
14
0
谢谢syscom了。不过有哪位给以帮我解决一下iceext的问题。我不能用Iceext加载softice,无比郁闷中。用IceExt自带的启动文件,显示内存不足之类的东西。我是XpSp1。
DarkNess0ut 2005-8-11 00:04
15
0
修改成如下键值:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTice]

"KDStackSize"=dword:00008000
"KDHeapSize"=dword:00008000
脱壳请教 1 2005-8-11 00:33
16
0
最初由 syscom 发布
加油,腠然大家方法,不同...可是能用就好了..cc
我是直接? patch,重建 import tab,在 dump,fix iat,就 ok了~!!!

佩例:原? code

........


对,我就是想用这个方法,但是怎么样才能让程序运行到所有调用过API的地方呢?
syscom 6 2005-8-11 01:52
17
0
最初由 脱壳请教 发布


对,我就是想用这个方法,但是怎么样才能让程序运行到所有调用过API的地方呢?


可以用搜? call 的 op code,去找 address....
无聊的菜鸟 9 2005-8-11 10:51
18
0
发现自己对SoftIce一窍不通,这个工程不知道要到何年马月才能完成了。。。
为什么我加了IceExt,还是不能到入口点呢?
脱壳请教 1 2005-8-11 12:25
19
0
最初由 syscom 发布


可以用搜? call 的 op code,去找 address....


对,搜索是比较简单的,但是call api的里面是一个判断程序,要运行后才知道这个CALL是对应哪个API,怎么才能自动取的呢?
无聊的菜鸟 9 2005-8-11 19:52
20
0
push Patch位置
push call的位置
jmp call的内存地址
patch API运算程序的尾部
这样就可以返回你的patch位置继续XXXXX了。
脱壳请教 1 2005-8-11 23:38
21
0
最初由 无聊的菜鸟 发布
push Patch位置
push call的位置
jmp call的内存地址
patch API运算程序的尾部
这样就可以返回你的patch位置继续XXXXX了。


呵呵,问题是这样的话会在得到API地址后运行API,才能返回到PATCH的位置
无聊的菜鸟 9 2005-8-12 13:35
22
0
不是阿,SD是先算出API的地址在返回执行API,我们就是在他返回之前patch尾部,加个pop edx或是add esp,4之类的东西在返回阿。这样他就会直接返回我们的Patch代码处,不就可以在访问到API的地址和Call的位置马?
脱壳请教 1 2005-8-12 14:42
23
0
最初由 无聊的菜鸟 发布
不是阿,SD是先算出API的地址在返回执行API,我们就是在他返回之前patch尾部,加个pop edx或是add esp,4之类的东西在返回阿。这样他就会直接返回我们的Patch代码处,不就可以在访问到API的地址和Call的位置马?


现在不行了,如果你在API计算那里PACTH,程序会自动退出~
无聊的菜鸟 9 2005-8-12 14:53
24
0
....恐怖。
无聊的菜鸟 9 2005-8-13 12:25
25
0
系统出问题了,樱花3不能运行了。等待重装系统。不过就要开学了,开学后就研究不了了,工程完成器无期延长。。。
denglinyang 2006-1-5 20:08
26
0


能写成详细的教程就好了
游客
登录 | 注册 方可回帖
返回