IORIOR
iorior.cjb.net
iorior@altavista.com
CrackMe Gold de CoOlViPeR
URL du crackme: http://coolviper.fr.st
outils: Softice, icedump, Ida, éditeur hexa
style: packed, anti-Softice, anti-procdump, cca, keygen "malin"
Date: 11/03/2000
CoOlViPeR nous a tellement parlé de son crackme que je me suis senti obligé de le cracker. Son aide.txt précise "Vous devez uniquement faire un keygen".
I Dump
Avec gettyp, on a:
 [C:\FICHIERS\CRAC\CRACME\CRACKMEG\CrackMe.exe] -----
    DOS executable file - 11414 bytes
 
    Portable executable (starting at 11036 for 378 bytes)
      Packer: UPX 0.81 - 0.84 [PE] (?)
      Packer: UPX 0.89.6 - 1.02 [PE]
      Calculated entrypoint: 9264 / 00002430h  (RVA: 0000A030h)
      Required CPU type: 80386
      Requires Win 95 or NT 4
      Flags:
        Relocation info stripped from file
        File is executable
        Line numbers stripped from file
        Local symbols stripped from file
        32 bit word machine
      Linker version: 5.12
      Objects (object align = 00001000h):
        Name      Virt size     RVA     Phys size  Phys Ofs
                  00007000h  00001000h  00000000h  00000400h
                  00003000h  00008000h  00002200h  00000400h
                  00001000h  0000B000h  00000600h  00002600h
 
    Found 150 bytes overlay
      Absolute position: 11264 of 11414 (= 98.7%)
      Zero padded (29 bytes)
      Overlay type: unknown (0070h)
 
- Files identified: 1 of 1 (100.00%) 
- Total time:       270.0 ms (50.0 ms/file) (220.0 ms lost)
Mais impossible d'utiliser upx pour décompresser, le PE ayant été changé. On peut faire un dump manuel.
On charge le crackme avec Symbol Loader, on descend de 6 pages dans la fenêtre du code, jusqu'à trouver un popad, sur lequel on met un bpx:

-------------------------------------------------------------------------PROT32-
0177:0040A13E  8D843048A40000      LEA       EAX,[ESI+EAX+0000A448]            ^
0177:0040A145  01F3                ADD       EBX,ESI                           ^
0177:0040A147  50                  PUSH      EAX                                
0177:0040A148  83C708              ADD       EDI,08                             
0177:0040A14B  FF9698A40000        CALL      [ESI+0000A498]                     
0177:0040A151  95                  XCHG      EAX,EBP                            
0177:0040A152  8A07                MOV       AL,[EDI]                           
0177:0040A154  47                  INC       EDI                                
0177:0040A155  08C0                OR        AL,AL                              
0177:0040A157  74DC                JZ        0040A135                           
0177:0040A159  89F9                MOV       ECX,EDI                            
0177:0040A15B  57                  PUSH      EDI                                
0177:0040A15C  48                  DEC       EAX                                
0177:0040A15D  F2AE                REPNZ SCASB                                  
0177:0040A15F  55                  PUSH      EBP                                
0177:0040A160  FF969CA40000        CALL      [ESI+0000A49C]                     
0177:0040A166  09C0                OR        EAX,EAX                            
0177:0040A168  7407                JZ        0040A171                           
0177:0040A16A  8903                MOV       [EBX],EAX                          
0177:0040A16C  83C304              ADD       EBX,04                             
0177:0040A16F  EBE1                JMP       0040A152                           
0177:0040A171  FF96A0A40000        CALL      [ESI+0000A4A0]                     
0177:0040A177  61                  POPAD                                       v
0177:0040A178  E98B77FFFF          JMP       00401908                      < > v
Invalid command                                                          Crackme

On trace ensuite jusqu'au popad suivant:

>
-------------------------------------------------------------------------PROT32-
0177:0040191E  8A06                MOV       AL,[ESI]                          ^
0177:00401920  8A19                MOV       BL,[ECX]                          ^
0177:00401922  32D8                XOR       BL,AL                              
0177:00401924  881E                MOV       [ESI],BL                           
0177:00401926  3BF7                CMP       ESI,EDI                            
0177:00401928  740D                JZ        00401937                           
0177:0040192A  46                  INC       ESI                                
0177:0040192B  41                  INC       ECX                                
0177:0040192C  80FF09              CMP       BH,09                              
0177:0040192F  7504                JNZ       00401935                           
0177:00401931  B700                MOV       BH,00                              
0177:00401933  8BCA                MOV       ECX,EDX                            
0177:00401935  EBE5                JMP       0040191C                           
0177:00401937  61                  POPAD                                        
0177:00401938  6800104000          PUSH      00401000                           
0177:0040193D  C3                  RET                                          
0177:0040193E  50                  PUSH      EAX                                
0177:0040193F  83F821              CMP       EAX,21                             
0177:00401942  74FA                JZ        0040193E                           
0177:00401944  58                  POP       EAX                                
0177:00401945  EBF6                JMP       0040193D                           
0177:00401947  0000                ADD       [EAX],AL                           
0177:00401949  0000                ADD       [EAX],AL                          v
0177:0040194B  0000                ADD       [EAX],AL                      < > v
Ici on peut dumper: /dump 400000 c000 c:\a.exe
on retient l'entry point: 00401000

Si on lance le dump, une fenêtre dos s'ouvre. Si on essaie de le regarder avec PE editor de Procdump, celui ci plante. Qu'à cela ne tienne! Regardons cela avec un éditeur hexa.

L'adresse du début du PE-Header se situe toujours en 0x3C, donc ici le PE Header est sensé commencer en 0x00002B1C, adresse à laquelle il n'y a rien (dans le dump). Pas besoin de chercher bien loin, le bon PE Header se situe en 0x000000C0. En 0x3C, on change donc le dword 1C2B0000 en C0000000.
Changeons maintenant l'entry point: en 0xE8 (C0+28), on met 00100000 à la place de 30A00000
Il faut maintenant changer la taille des sections.
La première (section .code sans doute) ne débute apparemment pas en 0x400 mais en 0x1000, sa taille est de 0x7000. La deuxième section débute en 0x8000 et sa taille est de 0x3000. On change aussi la dernière section, toujours en alignant la raw offset sur les voffsets, elle débute en 0xB000 et sa taille est de 0x1000
ça y est! on a un dump fonctionnel! Mais on n'a toujours pas vu à quoi ressemblait la fenêtre de ce crackme à cause de l'anti-Softice...


II L'anti-Softice
J'avoue que je n'ai pas tout étudié à fond.
On a une message box "Numega Softice detected" même quand on utilise frogsice, et même quand on utilise TRW!
il appelle un exception par une division par 0 en 0040116A
Là encore icedump se révèle être un outil précieux. Il existe une excellente commande /protect :
        -----------------
        /PROTECT [ON|OFF]
        -----------------

   control access to critical system resources such as the GDT and the System
   VM's IDT and LDT which are normally left accessible under win9x to normal
   (ring-3) apps. when on, winice will be brought up at any read/write attempt
   to the GDT and the System VM's IDT, or a write attempt to the System VM's
   LDT, or whenever a win32 thread attempts to change its own CPL to ring-0
   via context manipulation (typically by putting a DPL=0 code selector into
   its own CS register). when invoked without parameters it will print out the
   current status (on/off).
On tapes donc /protect on et on lance le crackme.
On break en 004017DB
EAX=00000000   EBX=00403384   ECX=0063F9EC   EDX=BFF76855   ESI=8164A25C        
EDI=800BC000   EBP=0063F968   ESP=0063F948   EIP=004017DB   o d I s Z a P c     
CS=0177   DS=017F   SS=017F   ES=017F   FS=3467   GS=0000   DS:800BC00E=1E      
--------------------------------------------------------------------------PROT32-
0177:004017DB  8A470E              MOV       AL,[EDI+0E]                       ^
0177:004017DE  EB03                JMP       004017E3                          ^
0177:004017E0  CD20                INT       20 VXDCall EBC0,0AC7               
0177:004017E6  028BEC7466EB        ADD       CL,[EBX+EB6674EC]                  
0177:004017EC  0150BF              ADD       [EAX-41],EDX                       
0177:004017EF  A818                TEST      AL,18                              
0177:004017F1  40                  INC       EAX                                
0177:004017F2  00EB                ADD       BL,CH                              
0177:004017F4  04EB                ADD       AL,EB                              
0177:004017F6  CD20                INT       20 VXDJmp 027F,0BEB                
0177:004017FC  EB02                JMP       00401800                           
0177:004017FE  8BEC                MOV       EBP,ESP                            
0177:00401800  8B3F                MOV       EDI,[EDI]                          
0177:00401802  EB02                JMP       00401806                           
0177:00401804  8BEC                MOV       EBP,ESP                            
0177:00401806  8B07                MOV       EAX,[EDI]                          
0177:00401808  EB03                JMP       0040180D                           
0177:0040180A  E9214725FF          JMP       FF655F30                           
0177:0040180F  0000                ADD       [EAX],AL                           
0177:00401811  00EB                ADD       BL,CH                              
0177:00401813  03CD                ADD       ECX,EBP                            
0177:00401815  20C7                AND       BH,AL                              
0177:00401817  3DCC000000          CMP       EAX,000000CC                      v
0177:0040181C  EB03                JMP       00401821                      < > v
------------------------------------DUMPC23!+07DB-------------------------------
WINICE: Load32  Obj=0004 Add=017F:70C11000 Len=00003000 Mod=SHLWAPI             
WINICE: Load32  Obj=0001 Add=0177:BFE91000 Len=00067000 Mod=COMCTL32            
WINICE: Load32  Obj=0002 Add=017F:BFEF8000 Len=00001000 Mod=COMCTL32            
WINICE: Load32  Obj=0003 Add=017F:BFEF9000 Len=0001F000 Mod=COMCTL32            
WINICE: Load32  Obj=0004 Add=017F:BFF18000 Len=00004000 Mod=COMCTL32            
WINICE: Load32  Obj=0001 Add=0177:7FE11000 Len=0001C600 Mod=COMDLG32            
WINICE: Load32  Obj=0002 Add=017F:7FE2E000 Len=00001000 Mod=COMDLG32            
WINICE: Load32  Obj=0003 Add=017F:7FE31000 Len=0000A000 Mod=COMDLG32            
WINICE: Load32  Obj=0004 Add=017F:7FE3B000 Len=00002000 Mod=COMDLG32            
:/protect on                                                                    
WINICE: Load32  Obj=0001 Add=0177:00401000 Len=00007000 Mod=DUMPC23             
WINICE: Load32  Obj=0002 Add=017F:00408000 Len=00003000 Mod=DUMPC23             
WINICE: Load32  Obj=0003 Add=017F:0040B000 Len=00001000 Mod=DUMPC23             
WINICE: Load32  Obj=0001 Add=0177:BFF21000 Len=0001E000 Mod=GDI32               
WINICE: Load32  Obj=0002 Add=017F:BFF3F000 Len=00002000 Mod=GDI32               
WINICE: Load32  Obj=0003 Add=017F:BFF41000 Len=00001000 Mod=GDI32               
WINICE: Load32  Obj=0004 Add=017F:BFF42000 Len=00001000 Mod=GDI32               
WINICE: Load32  Obj=0005 Add=017F:BFF43000 Len=00001000 Mod=GDI32               
WINICE: Load32  Obj=0006 Add=017F:BFF44000 Len=00002000 Mod=GDI32               
WINICE: Load32  Obj=0001 Add=0177:BFE81000 Len=0000B000 Mod=ADVAPI32            
WINICE: Load32  Obj=0002 Add=017F:BFE8C000 Len=00001000 Mod=ADVAPI32            
WINICE: Load32  Obj=0003 Add=017F:BFE8D000 Len=00001000 Mod=ADVAPI32            
WINICE: Load32  Obj=0004 Add=017F:BFE8E000 Len=00001000 Mod=ADVAPI32            
WINICE: Load32  Obj=0005 Add=017F:BFE8F000 Len=00001000 Mod=ADVAPI32            
WINICE: Load32  Obj=0001 Add=0177:BFF51000 Len=0000C000 Mod=USER32              
WINICE: Load32  Obj=0002 Add=017F:BFF5D000 Len=00001000 Mod=USER32              
WINICE: Load32  Obj=0003 Add=017F:BFF5E000 Len=00001000 Mod=USER32              
WINICE: Load32  Obj=0004 Add=017F:BFF5F000 Len=00001000 Mod=USER32              
WINICE: Load32  Obj=0005 Add=017F:BFF60000 Len=00001000 Mod=USER32              
Break due to Access Attempt to IDT                                              
                                                                                
Invalid command                                                          Dumpc23
Il n'y a plus qu'à noper à cet endroit, et c'est tout! (on peut aussi mettre xor eax, eax = Softice non présent, mais c'est inutile puisque eax est toujours égale à 0)
Il doit y avoir aussi un meltice puisqu'on trouve \\.\SICE dans les données, je ne l'ai pas localisé.
En fait les anti-Softice deviennent inutiles, certains l'ont d'ailleurs compris: Il n'y a plus d'anti softice depuis la version 1.1 d'ASProtect, par contre il y a du cca <- Notez la qualité des transitions dans ce tutorial ;o)


III Le cca (code changeant d'apparence)
Je vous conseille vivement ida plutôt que win32asm, et surtout quand il y a du cca, ida ne le craignant pas.
Généralement, quand on a du cca, ce sont toujours les mêmes octets qui reviennent. Ici, on a:
00401000                 jmp     short loc_401005
00401000 ; ---------------------------------------------------------------------------
00401002                 db 0CDh, 20h, 0C7h
ou:
0040100C                 jmp     short loc_401011
0040100C ; ---------------------------------------------------------------------------
0040100E                 db 0E9h, 21h, 47h
ou encore:
0040102A                 jmp     short loc_401030
0040102A ; ---------------------------------------------------------------------------
0040102C                 dd 0EB20CDEBh
on va enlever tout ça.
On prends notre éditeur hexa et on utilise la fonction "remplacer" pour changer EB03CD20C7 en 9090909090 partout.

On fait la même chose pour EB04EBCD20EB, et pour tous les autres octets. On a maintenant un prog propre que l'on peut keygenner.


IV La recherche d'un serial
Il y a un vieux truc connu: anti-bpx getdlgitemtexta (on regarde si le 1er byte est CC, si c le cas, il y a un bp).
Pour contourner ça, il suffit de taper dans softice: u getdlgitemtexta
puis on place un BP après l'adresse où il est placé normalement quand on fait bpx getdlgitemtexta

On désassemble le prog sans cca avec ida.
Je vous conseille de changer les noms en "nom" et "serial" pour y voir plus clair.
00401450                 push    100h
00401455                 push    offset nom
0040145A                 push    69h
0040145C                 push    ds:dword_403070
00401462                 call    j_GetDlgItemTextA
00401467                 nop
00401468                 nop
00401469                 nop
0040146A                 nop
0040146B                 nop
0040146C                 nop
0040146D                 push    100h
00401472                 push    offset serial
00401477                 push    6Ah
00401479                 push    ds:dword_403070
0040147F                 call    j_GetDlgItemTextA
Bon j'explique l'algorythme:
en ecx se trouve le nombre de caractère du nom (
push    offset nom
call    j_lstrlen
xchg    eax, ecx
) quand on arrive ici:
004014D6                 mov     esi, offset nom
004014DB 
004014DB loc_4014DB:                             ; CODE XREF: seg000:004014EA.j
004014DB                 nop
004014DC                 nop
004014DD                 nop
004014DE                 nop
004014DF                 lodsb
004014E0                 nop
004014E1                 nop
004014E2                 nop
004014E3                 nop
004014E4                 add     ebx, eax
004014E6                 nop
004014E7                 nop
004014E8                 nop
004014E9                 nop
004014EA                 loop    loc_4014DB      ; somme_nom
en ebx sort de la boucle la somme des caractères ascii du nom
ensuite
004014F1                 mov     eax, ds:serial_plus_5 ; car6789
004014F6                 nop
004014F7                 nop
004014F8                 nop
004014F9                 nop
004014FA                 nop
004014FB                 add     ebx, eax
004014FD                 nop
004014FE                 nop
004014FF                 nop
00401500                 nop
00401501                 nop
00401502                 mov     eax, ds:aa
00401507                 nop
00401508                 nop
00401509                 nop
0040150A                 nop
0040150B                 nop
0040150C                 mul     ebx
0040150E                 nop
0040150F                 nop
00401510                 nop
00401511                 nop
00401512                 nop
00401513                 mov     ds:dword_401563, eax -autopatch
A la somme des caractères du nom est ajoutée les caractères 6,7,8,9 du serial, ensuite une multiplication est effectuée avec 582105F5h. Le résultat donné est mis en 00401563 (autopatch).
Ma première idée était de foncer tête baissée et de chercher ce qu'il faut pour que le résultat soit 90909090h
La somme des caractères de iorior est de 294h
( somme du nom + car6789 ) * 582105F5h = 90909090h
( 294h + car6789 ) * 582105F5h = 90909090h
Ici on peut faire un brute force dans softice: on met ebx à 0
En 004014FD, on met inc ebx
En 0040150E, on met cmp eax, 90909090 jne 004014FD
Et on place un BP après le jne.

025f6450h * 582105F5h = 90909090h
025f6450h - 294h = 025F61BCh <- caractere 6,7,8,9 du serial pour iorior

Sauf que on a 1 test de edx après:
00401563 dword_401563    dd 909002EBh            ; DATA XREF: seg000:00401513.w
00401567 ; ---------------------------------------------------------------------------
00401567                 nop
00401568                 nop
00401569                 nop
0040156A                 nop
0040156B                 nop
0040156C                 mov     eax, ds:serial
00401571                 nop
00401572                 nop
00401573                 nop
00401574                 nop
00401575                 nop
00401576                 nop
00401577                 cmp     eax, edx
00401579                 nop
0040157A                 nop
0040157B                 nop
0040157C                 nop
0040157D                 jnz     loc_40166E
00401583                 nop
00401584                 nop
00401585                 nop
00401586                 nop
00401587                 nop
00401588                 call    near ptr dword_4016AF
0040158D                 nop
Pour éviter ça, on peut essayer de ne pas obtenir un résultat de 90909090h mais de 90902AEBh, on aura donc un saut (EB2A) qui évitera les tests.

On fait donc la même chose:
( 294 + car6789 ) * 582105F5h = 90902AEB
En brute force, on trouve 3785015Fh
3785015Fh * 582105F5h = 90902AEB
3785015Fh - 294 = 3784FECB <- caractere 6,7,8,9 du serial pour iorior
en ascii:
Ëþ„7

Remarquez qu'on aurait pu se désintéresser complètement de la suite de l'algorithme en faisant faire un saut en 00401643, on aurait pu aussi faire un saut en 00401592, pour éviter le xor edx, edx qui pose problème en 004015CD

2eme partie
Le 2eme patch est beaucoup plus simple
00401597                 mov     eax, ds:nom
0040159C                 nop
0040159D                 nop
0040159E                 nop
0040159F                 nop
004015A0                 nop
004015A1                 and     eax, 0F0F0F0Fh
004015A6                 nop
004015A7                 nop
004015A8                 nop
004015A9                 mov     ebx, dword ptr ds:byte_403081
004015AF                 nop
004015B0                 nop
004015B1                 nop
004015B2                 nop
004015B3                 sub     ebx, eax
004015B5                 nop
004015B6                 nop
004015B7                 nop
004015B8                 nop
004015B9                 nop
004015BA                 mov     ds:dword_4015C4, ebx -autopatch
En 403081, on a les caractères 10,11,12,13 du serial Pour éviter le saut en 004015D2, j'ai chercher à incrémenter edx, donc à trouver 90904290h pour le dword autopatché.
Les 4 premiers caractères de mon nom ont pour code ascii: 696F7269
696F7269h and 0F0F0F0Fh = 090F0209h
090F0209h + 90904290h = 999F4499h
Soit en ascii:
™ŸD™

3 eme partie
un dernier contrôle:
004015EC                 mov     esi, offset serial
004015F1                 nop
004015F2                 nop
004015F3                 nop
004015F4                 nop
004015F5                 nop
004015F6                 mov     ecx, edx
004015F8                 nop
004015F9                 nop
004015FA                 nop
004015FB                 nop
004015FC                 add     ecx, 5
004015FF                 nop
00401600                 nop
00401601                 nop
00401602 
00401602 loc_401602:                             ; CODE XREF: seg000:0040160F.j
00401602                 lodsb
00401603                 nop
00401604                 nop
00401605                 nop
00401606                 nop
00401607                 nop
00401608                 add     ebx, eax
0040160A                 nop
0040160B                 nop
0040160C                 nop
0040160D                 nop
0040160E                 nop
0040160F                 loop    loc_401602
00401611                 nop
00401612                 nop
00401613                 nop
00401614                 and     bx, 0F0F0h
00401619                 nop
0040161A                 nop
0040161B                 nop
0040161C                 nop
0040161D                 nop
0040161E                 nop
0040161F                 ror     bx, 2
00401623                 nop
00401624                 nop
00401625                 nop
00401626                 nop
00401627                 nop
00401628                 add     bx, 3030h
0040162D                 nop
0040162E                 nop
0040162F                 nop
00401630                 nop
00401631                 cmp     word ptr ds:byte_403081+4, bx
00401638                 nop
00401639                 nop
0040163A                 nop
0040163B                 jnz     short loc_40166E
Étant donné que l'on a incrémenté edx, ecx est égal à 6 en 004015FF.
En 403081+4, se trouvent les caractères 14 et 15, pour iorior, 3060h. Ce qui en ascii fait:
`0

voici donc un des nombreux serials possibles pour iorior:
12345Ëþ„7™ŸD™`0

On peut passer au keygen, sur les mêmes principes.


V Le keygen
Il existe beaucoup de possibilités, j'ai pris le parti d'obtenir les auto-patchs 90902AEBh et 90904290h, mais on peut en choisir d'autres...

Voici donc mes sources:
dans .data :
buffer db 100 dup (0)  
serial db 31h,32h,33h,34h,35h,8 dup (33h) ,0,0,0
key db 4 dup (0)
et donc:
pushad
    lea  EAX, buffer                          ; le nom
	push eax
    call lstrlen                              ; longueur du nom dans eax 
    cmp EAX, 4
    jng   trop_court 
      
xor ebx, ebx
mov ecx, eax		;longueur du nom dans ecx (compteur)
mov esi, offset buffer
@@1:
lodsb
add     ebx, eax		; somme des caracteres du nom
loop @@1

mov eax, 3785015fh		;à 3785015fh on soustrait la somme des caractères
sub eax, ebx

mov ecx, offset serial+5
mov [ecx], eax



mov ecx, offset buffer

mov al, [ecx] 				; routine de merde pour que
mov byte ptr [key+3], al	; les bytes soient dans le bon ordre
mov al, [ecx+1]
mov byte ptr [key+2], al
mov al, [ecx+2]
mov byte ptr [key+1], al
mov al, [ecx+3]
mov byte ptr [key], al

mov eax, dword ptr [key]
and eax, 0F0F0F0Fh

adc eax, 90904290h			; ça c'est du reverse d'algorithme! 
		; y avait un sub, je mets un adc  ;)

mov ecx, offset serial+9

mov [ecx+3], al
ror eax,8
mov [ecx+2], al
ror eax,8
mov [ecx+1], al
ror eax,8
mov [ecx], al
ror eax,8


mov ecx, 6
mov esi, offset serial

					; ensuite c'est du rip ;)
xor ebx, ebx
xor eax, eax

@@3:
lodsb
add     ebx, eax
loop @@3

and     bx, 0F0F0h
ror     bx, 2
add     bx, 3030h

mov ecx, offset serial+13
mov [ecx], bx
popad
jmp bravo
Coolviper a dit que c'était pas ce qui était prévu (le 909020EBh), et que j'avais exploité une faille dans l'algorithme. Et bien s'il ne veut pas que j'exploite des failles, une seule solution: il n'en laisse pas. ;o)

Voilà, c'est tout.
A+

Mes remerciements vont à: (Greets to:) Amante4, Christal, +DaFixer, Demonaz, El.CaRaCoL, Eternal Bliss, Falcon, F@t@lity, +FP, H@lloWin___HiA, Iczelion, Lancelot, La main rouge (PP), Lutin Noir, Morgatte, Muad'Dib, MrPhilex, Pulsar, r!sc, St Thomas, +Spath, SyntaxError, Tamambolo, Teeji, Tornado, The Analyst, The Egoiste, +Tsehp, Volatility, et tous les autres...
iorior © 2001