Hello,

    Aujourd'hui, nous nous attaquons à un programme qui à déjà été analysé par le Group de Travail : ZipStudio.

    La nouvelle version semble poser, même avec l'ancien cours, de sérieux problèmes à beaucoups de Newbies jusqu'à vois des " ZipStudio Incrackable ? " sur le forum. Je signale que je ne réexpliquerai pas tous ce qui a été dis dans le premier essai à son propos.

    I. zstudio.dll

    Pourquoi (re)parle-on nous de cette DLL ? Simplement parcequ'une détection de Debugger se fait dans le procédure DLLmain ( DLLEntryPoint ). Comment savons-nous cela... entre autre en utilisant FrogSice dont voici le Log :

; Chargement
; ---------------------------------------------------------------------------------
** SoftICE detection **  code 07, at  FCB2:1004FCB2     Interrupt:68h
** SoftICE detection **  code 07, at  FCB2:004CFCB2     Interrupt:68h
** SoftICE detection **  code 01, at  0177:00000177     Interrupt:03h
** SoftICE detection **  code 0B, at    cs:004CF94C     Attempting to load: SICE
** SoftICE detection **  code 0B, at    cs:004CF988     Attempting to load: NTICE
** SoftICE detection **  code 07, at  FCB2:004BFCB2     Interrupt:68h
** SoftICE detection **  code 01, at  0177:00000177     Interrupt:03h
** SoftICE detection **  code 0B, at    cs:004BE8BC     Attempting to load: SICE
** SoftICE detection **  code 0B, at    cs:004BE8F8     Attempting to load: NTICE
** SoftICE detection **  code 0B, at    cs:00490660     Attempting to load: SICE
** SoftICE detection **  code 0B, at    cs:0049069C     Attempting to load: NTICE

; En affichant la Fenetre principale
; ---------------------------------------------------------------------------------
** SoftICE detection **  code 07, at  FCB2:004BFCB2     Interrupt:68h
** SoftICE detection **  code 01, at  0177:00000177     Interrupt:03h

; En fermant cette dernière
; ---------------------------------------------------------------------------------
** SoftICE detection **  code 07, at  FCB2:004CFCB2     Interrupt:68h
** SoftICE detection **  code 01, at  0177:00000177     Interrupt:03h

On voit directement que le premier anti-sice se fait dans une DLL ( CS = 1004FCB2 ) et que c'est une INT 68.

Pour la neutraliser, il suffit de mettre un CC a l'EP de la DLL, ensuite tracer dans son code avec F10. Il y a un des call qui qui le programme :

//******************** Program Entry Point ********
:1003E000 CC                      int 03                  ;Pour forcer le BP. Ne pas oublier de remplacer par 83h
:1003E001 3DE8110410              cmp eax, 100411E8
:1003E006 007408A1                add byte ptr [eax+ecx-5F], dh
:1003E00A E8110410FF              call 0F13E420
:1003E00F E0C3                    loopnz 1003DFD4
:1003E011 55                      push ebp
:1003E012 8BEC                    mov ebp, esp
:1003E014 83EC14                  sub esp, 00000014
:1003E017 53                      push ebx
:1003E018 56                      push esi
:1003E019 57                      push edi
:1003E01A E8CF010000              call 1003E1EE
:1003E01F A16C120410              mov eax, dword ptr [1004126C]
:1003E024 2B0568120410            sub eax, dword ptr [10041268]
:1003E02A 8945F4                  mov dword ptr [ebp-0C], eax
:1003E02D 8B0DA0160410            mov ecx, dword ptr [100416A0]
:1003E033 030DAC160410            add ecx, dword ptr [100416AC]
:1003E039 894DF8                  mov dword ptr [ebp-08], ecx
:1003E03C 8B156C120410            mov edx, dword ptr [1004126C]
:1003E042 3B55F8                  cmp edx, dword ptr [ebp-08]
:1003E045 7520                    jne 1003E067
:1003E047 A178110410              mov eax, dword ptr [10041178]
:1003E04C 2B0580110410            sub eax, dword ptr [10041180]
:1003E052 50                      push eax
:1003E053 8B0D7C110410            mov ecx, dword ptr [1004117C]
:1003E059 51                      push ecx
:1003E05A E8A5010000              call 1003E204
:1003E05F 50                      push eax
:1003E060 E815050000              call 1003E57A
:1003E065 EB28                    jmp 1003E08F

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1003E045(C)
|
:1003E067 8B1578110410            mov edx, dword ptr [10041178]
:1003E06D 2B1580110410            sub edx, dword ptr [10041180]
:1003E073 52                      push edx
:1003E074 A180110410              mov eax, dword ptr [10041180]
:1003E079 50                      push eax
:1003E07A E885010000              call 1003E204
:1003E07F 50                      push eax
:1003E080 E8F5040000              call 1003E57A
:1003E085 6898160410              push 10041698
:1003E08A E8F3020000              call 1003E382

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1003E065(U)
|
:1003E08F E87F010000              call 1003E213
:1003E094 E8????????              call 10040176
:1003E099 E8E5010000              call 1003E283

Le call en 1003E094 détecte les debugger et si debugger il y a, exit le programme. Le problème, c'est qu'il saute dans du code préalablement décrypté et qu'il est donc impossible de patcher directement. Cependant, quand ce call est exécuté, l'instruction INT 68 est déjà décrypté en mémoire, on peut donc le dévier et patcher l'INT 68 en NOP NOP :

:1003E094 E8473F0000              call 10041FE0
...
* Referenced by a CALL at Address:
|:1003E094
|
:10041FE0 66C7053B0104109090      mov word ptr [1004013B], 9090  ;On patch l'instruction en NOPs
:10041FE9 E988E1FFFF              jmp 10040176                   ;Et on redonne la main

D'après FrogsIce, il n'y a qu'un seul Anti-sice dans la DLL ( vu que le suivant se fait dans le code de l'EXE ). Nous en avons donc terminé pour le problème principale de la pluspart d'entre vous.

Rem : pour trouver l'adresse de l'INT68, il suffit de tracer avec F8 dans le call en 1003E094. A un moment, vous vous retrouverai dans VMM ( dans le code de gestion des interruptions ), à ce moment, faites 2-3 F12 pour revenir dans le code zstudio.dll et vous devez aperçevoir l'instruction juste au-dessus de l'adresse de retour.

    II. Zip Studio.exe

Attaquons-nous à présent à notre petit préféré, ZipStudio. Un rapide coup d'oeil au PE Header nous apprend qu'il est compressé par UPX. ( Voir les nom des sections ). Ensuite, d'après le Log de FrogsIce, il semblerait qu'il y aie seulement un bloc important :

** SoftICE detection **  code 07, at  FCB2:004CFCB2     Interrupt:68h
** SoftICE detection **  code 01, at  0177:00000177     Interrupt:03h

 En posant 3 BreakPoints adaptés :

        BPINT 03 ( pour l'int 03 ),
        BPM Exec_Int X IF ax==68 ( pour l'int 68 )
     et BPM CreateFileA X ( pour la détection MeltICE )

 J'ai trouvé le code qui exécute les deux interruptions :

0177:004CFB07  B443                MOV       AH,43             ;L'int 68
0177:004CFB09  CD68                INT       68
0177:004CFB0B  3D86F30000          CMP       EAX,0000F386
0177:004CFB10  66FA                CLI
0177:004CFB12  FB                  STI
0177:004CFB13  A7                  CMPSD

 Après ce bloc d'instruction contenant l'Int 68, le programme installe un SEH.

 Explication : Quand une Exception survient dans un programme, normallement, vous voyez apparaître la trop bien-connue boite de dialogue affichant les registres, ect.. Mais si on veux, le programme peut gérer lui-même ses erreurs. Pour cela, il utilise le SEH. Pour installer le SEH ,il suffit d'appeler SetHunhandledExceptionFilter avec comme paramêtre l'adresse de la fonction à exécuté lors d'une Exception.

 Ci-dessous, le programme installe le SEH en 004CFB3A et créé une Exception ( avec l'int 03 ). Si le programme est debuggé, il va géré l'erreur et retourner après l'int 03 ( ExitProcess ! ). Dans le cas contraire, c'est la fonction en 004CFB3A qui sera exécutée.

0177:004CFB14  8965FC              MOV       [EBP-04],ESP
0177:004CFB17  683AFB4C00          PUSH      004CFB3A
0177:004CFB1C  E80363F3FF          CALL      KERNEL32!SetUnhandledExceptionFilter
0177:004CFB21  BD4B484342          MOV       EBP,4243484B ;BCHK
0177:004CFB26  B804000000          MOV       EAX,00000004
0177:004CFB2B  CC                  INT       3
0177:004CFB2C  E8DB68F3FF          CALL      USER32!MessageBoxA
0177:004CFB31  E8E660F3FF          CALL      KERNEL32!ExitProcess
0177:004CFB36  66FA                CLI
0177:004CFB38  FB                  STI
0177:004CFB39  A7                  CMPSD
0177:004CFB3A  8B65FC              MOV       ESP,[EBP-04]
0177:004CFB3D  6843FB4C00          PUSH      004CFB43
0177:004CFB42  C3                  RET
0177:004CFB43  C3                  RET

 Si c'est la fonction en 004CFB3A qui est exécutée, le programme ne retournera pas en 004CFB2C ( après l'INT 03 ) mais en 004CFB43. Pour neutraliser cette protection, il faudra d'abord NOPer l'INT 68 et remplacer l'INT 03 par ADD ESP,04 ; RET.

0177:004CF932  E8A562F3FF          CALL      KERNEL32!CreateFileA
0177:004CF937  83F8FF              CMP       EAX,-01
0177:004CF93A  7408                JZ        004CF944
0177:004CF93C  50                  PUSH      EAX
0177:004CF93D  E87A62F3FF          CALL      KERNEL32!CloseHandle
0177:004CF942  B301                MOV       BL,01
0177:004CF944  8BC3                MOV       EAX,EBX
0177:004CF946  5B                  POP       EBX
0177:004CF947  C3                  RET

 Ci-dessus se trouve le code de la detection MeltICE. Il suffira de patcher le MOV BL,01 en NOPs pour la neutraliser. Ce bloque d'instruction a été simplement trouvé en mettant un BPX sur CreateFileA et en reguardant la valeur de son premier paramètre en *(ESP+4).

 En continuant notre voyage dans le code, on se retrouve nez-à-nez avec une INT 03 :

:004BE938 55                      push ebp
:004BE939 8BEC                    mov ebp, esp
:004BE93B 51                      push ecx
:004BE93C 53                      push ebx
:004BE93D 56                      push esi
:004BE93E 57                      push edi
:004BE93F 33C0                    xor eax, eax
:004BE941 55                      push ebp
:004BE942 6877E94B00              push 004BE977
:004BE947 64FF30                  push dword ptr fs:[eax]
:004BE94A 648920                  mov dword ptr fs:[eax], esp
:004BE94D E8AEFFFFFF              call 004BE900
:004BE952 6A00                    push 00000000
:004BE954 6808524A00              push 004A5208
:004BE959 E8AE78F4FF              call 0040620C
:004BE95E 66B90801                mov cx, 0108
:004BE962 66BE6E00                mov si, 006E
:004BE966 AC                      lodsb
:004BE967 CC                      int 03

 Pour neutraliser cela, nous allons essayer de retrouver le code appelant. Pour cela, on met des BPX au début de la fonction en 004BE938, on relance et on reguarde en [ESP]. On voit qu'on vient d'ici :

:004BED2C 55                      push ebp
:004BED2D 8BEC                    mov ebp, esp
:004BED2F 83C4F0                  add esp, FFFFFFF0
:004BED32 53                      push ebx
:004BED33 56                      push esi
:004BED34 57                      push edi
:004BED35 33C9                    xor ecx, ecx
:004BED37 894DF0                  mov dword ptr [ebp-10], ecx
:004BED3A 8945FC                  mov dword ptr [ebp-04], eax
:004BED3D 33C0                    xor eax, eax
:004BED3F 55                      push ebp
:004BED40 6833F04B00              push 004BF033
:004BED45 64FF30                  push dword ptr fs:[eax]
:004BED48 648920                  mov dword ptr fs:[eax], esp
:004BED4B 6A00                    push 00000000
:004BED4D 68E44C4A00              push 004A4CE4
:004BED52 E8B574F4FF              call 0040620C
:004BED57 E8DCFBFFFF              call 004BE938

 Et si on remplace le PUSH EBP par un RET, l'Anti-Sice est neutralisé.

 Après cela, il y a encore 2 détections INT 68/BCHK ( exactement le même code que pour le premier cas ), 1 détection MeltICE ( Idem ) et 2 détections comme la dernière qui, chez moi ne posent étonnament pas problème.. (?), mais que vous pouvez quand même neutraliser.

 INT68 : 004CFB09, 004BCFA1, 004CE287    ; Remplacer par NOP ; NOP
 BCHK  : 004CFB2B, 004BCFC3, 004CE2A9    ; Remplacer par ADD ESP,04 ; RET

 MeltICE : 00490656, 004CF942            ; Remplacer par NOP ; NOP

 INT03 : 004BED2C, 004BD010, 004CE2F8    ; Remplacer par RET

 UPX donne la main à l'OEP ici :

:0081E492 61                      popad
:0081E493 E97C1ACBFF              jmp 004CFF14

 On va donc le dévier vers notre code et patcher en mémoire :

0081E493: E968000000                   jmp      .00081E500
...
0081E500: 66C70509FB4C009090           mov       w,[0004CFB09],09090     ;Premier bloc INT68/BCHK
0081E509: C7052BFB4C0083C404C3         mov       d,[0004CFB2B],0C304C483 ;
0081E513: 66C705A1CF4B009090           mov       w,[0004BCFA1],09090     ;Second bloc INT68/BCHK
0081E51C: C705C3CF4B0083C404C3         mov       d,[0004BCFC3],0C304C483 ;
0081E526: 66C70587E24C009090           mov       w,[0004CE287],09090     ;Dernier bloc INT68/BCHK
0081E52F: C705A9E24C0083C404C3         mov       d,[0004CE2A9],0C304C483 ;
0081E539: 66C705560649009090           mov       w,[000490656],09090     ;Les 2 MeltICE
0081E542: 66C70542F94C009090           mov       w,[0004CF942],09090     ;
0081E54B: C6052CED4B00C3               mov       b,[0004BED2C],0C3       ;Les 3 INT3
0081E552: C60510D04B00C3               mov       b,[0004BD010],0C3       ;
0081E559: C605F8E24C00C3               mov       b,[0004CE2F8],0C3       ;
0081E560: E9AF19CBFF                   jmp       0FFD67314               ;Et on saute à l'OEP

 Voilà ce qui termine les protections Anti-debug. De plus, j'ai l'impression que les INT03 sont compris dans les fonctions lié au caractère Shareware de ZipStudio car je n'ai plus de NagScreen..

 Remarquez bien que ce cours n'explique pas comment cracker ce programme.. il donne juste un aperçus des moyens que l'on peut uriliser pour passer les Anti-debug utilisés.. D'ailleurs, il n'est pas possible d'utiliser le programme dans cet état. Les 3 bloc INT03 sont en fait des fonctions importantes de ZipStudio et ne contiennent pas QUE du code Anti-debug. Il va donc falloire etudier cela de plus pret...

Amicalement,
TeeJi