Manual Unpacking d'Asprotect 1.0+
by LuTiN NoIR
Published by Tsehp, Aug 2000.



 
 
I_Introduction

Christal m'a demandé de refaire ma copie sur le dump de pleditor qui n'était, il est vrai, pas très expliqué. Mais cette fois il m'a demandé si je pouvais le faire sur un autre programme, histoire de vérifier si elle marche toujours. Donc cette essai visera à expliquer comment obtenir un dump fonctionnel d'un programme protégé avec asprotect 1.0 (ou plus). En fait il y a plusieurs versions d'asprotect et les deux progs présentés ici n'utilisent pas la même version (enfin c'est quasiment la même). Je vais en profiter pour parler un peu plus d'asprotect lui-même. TeeJi m'ayant proposé son aide il vous expliquera une partie du fonctionnement d'asprotect (voir son essai). Enfin trois méthodes de dump seront présentés ici: tout d'abord celle que j'ai utilisé sur pleditor mais revu et corrigé et celle mise au point sur commview par Tsehp . Une autre méthode (enfin deux pour être exact) expliquera un moyen de reconstruire une table d'import.
En fin de ce tutoriel je vous indiquerait des tuts à lire qui pourrait vous aider à mieux comprendre (certain sur aspr et d'autre sur cdilla et d'autres sur le format pe).
 
 
II_Tools

Softice 4.01
Icedump 6.01
Procdump 1.6.2 (ou Procinfos)
Ida 4.04 (pas nécessaire)
Winhex 9.4 (ou autre)
Pe-rebuilder (ou un autre rebuilder)
 
 
III_1ère méthode: pleditor

Dans le dossier sur Aspack/Asprotect j'avais proposé une méthode pour obtenir un dump fonctionnel de PerL Editor 3.0 build 15.06.2000. J'avais dit que cette méthode ne marchait pas mais en fait si. Je vais la refaire ici mais d'une autre facon. De plus je vais essayer le l'expliqué plus clairement.

Asprotect qu'est-ce que c'est? et bien c'est une protection. Elle permet de mettre sur son programme des limitations (temps, utilisation ...), de mettre des anti-debuggers, de mettre du code polymorphe ou overlaping du code,de multi compressé/cryptés le prog et d'empêcher le dump du programme. Il y a également d'autres fonctions mais elles ne nous préoccupe pas ici (on peut notamment cryptés certaine partie du prog qui se décrytpe avec une clef).
Comment peut-on s'en sortir? et bien c'est plus ou moins simple. Une fois que l'on sait faire ca devient simple :).
Bon tout d'abord qu'est ce qui empêche le dump du programme? et bien en fait asprotect ne recré pas une table d'import et une iat (import address table) correct lors de la décompression en mémoire du programme (une partie de ce tut est consacré à ceci).
 

1) Récolte d'informations et dump.

Bon tout d'abord on va regarder les sections de pleditor. Ceci v nous permettre de savoir où asprotect devrait normallement mettre la table d'import du programme. Donc on prend Procdump et on va dans Pe-Editor et sections et on a ceci :

Name: CODE      VS: 000B3000  VA: 00001000  RS: 00042800  RA: 00000400  C: C0000040
Name: DATA      VS: 00002000  VA: 000B4000  RS: 00000C00  RA: 00042C00  C: C0000040
Name: BSS       VS: 00002000  VA: 000B6000  RS: 00000000  RA: 00043800  C: C0000040
Name: .idata    VS: 00003000  VA: 000B8000  RS: 00000200  RA: 00043800  C: C0000040
Name: .tls      VS: 00001000  VA: 000BB000  RS: 00000000  RA: 00043A00  C: C0000040
Name: .rdata    VS: 00001000  VA: 000BC000  RS: 00000200  RA: 00043A00  C: C0000040
Name: .reloc    VS: 0000D000  VA: 000BD000  RS: 00000000  RA: 00043C00  C: C0000040
Name: .rsrc     VS: 00036000  VA: 000CA000  RS: 0000A200  RA: 00043C00  C: C0000040
Name: .data     VS: 00015000  VA: 00100000  RS: 00014800  RA: 0004DE00  C: C0000040
Name: .data     VS: 00001000  VA: 00115000  RS: 00000000  RA: 00062600  C: C0000040

On trouve une section .idata et c'est ici que doit se trouvé une table d'import (pour les exe avec sections .idata). Donc l'import address table correspond au virtual offset de la section .idata (b80000). Donc on sait qu'il va mettre sa table d'import en 4b8000 (virtual address + image base). Il faudra donc mettre un point d'arrêt quand il écrira dans cette partie : bpm 4b8000 w .

Maintenant que l'on sait où asprotect va mettre la table d'import on peut commencer à tracer le programme. Le point d'entrée du programme est en 500001, c'est la que se trouve la première partie d'asprotect (et oui il y a une multi-compression). Mais cette version 1.0 d'asprotect permet de décompressé ces parties en mémoires à des addresses différentes. Il va donc falloir enlever cela (thx sword). Pour ce faire on pose un bpx gettickcount et on lance le programme. Softice apparait et on appuie sur F12 pour revenir dans le code du prog, on doit normallement arriver là :

015F:00500223  C3                  RET
015F:00500224  25FFFF0100          AND       EAX,0001FFFF      <-- on arrive là
015F:00500229  EB04                JMP       0050022F
015F:0050022B  E8EB04E9EB          CALL      EC39071B
015F:00500230  FB                  STI
015F:00500231  E950EB04E8          JMP       E854ED86
015F:00500236  EB04                JMP       0050023C
015F:00500238  E9EBFBE9E8          JMP       E939FE28
015F:0050023D  0300                ADD       EAX,[EAX]
015F:0050023F  0000                ADD       [EAX],AL

Donc pour ce débarraser du changement d'adresse il faut mettre eax à 0 (ou autre chose mais tjs pareil), ensuite on trouve la fin de la première zone en 500c28 :

015F:00500C17  E8EB04E9EB          CALL      EC391107
015F:00500C1C  FB                  STI
015F:00500C1D  E95BEB04E8          JMP       E854F77D
015F:00500C22  EB04                JMP       00500C28
015F:00500C24  E9EBFBE9C3          JMP       C43A0814
015F:00500C28  C3                  RET                       <-- fin de la 1ère zone
015F:00500C29  B0DD                MOV       AL,DD
015F:00500C2B  54                  PUSH      ESP
015F:00500C2C  004765              ADD       [EDI+65],AL
015F:00500C2F  7454                JZ        00500C85

Et là il passe à la deuxième zone qu'il a décompressé en mémoire. On arrive là :

015F:0056407C  90                  NOP
015F:0056407D  60                  PUSHAD                       <-- on arrive là
015F:0056407E  E844060000          CALL      005646C7
015F:00564083  EB44                JMP       005640C9
015F:00564085  0000                ADD       [EAX],AL
015F:00564087  0000                ADD       [EAX],AL
015F:00564089  0000                ADD       [EAX],AL
015F:0056408B  0000                ADD       [EAX],AL
015F:0056408D  87DB                XCHG      EBX,EBX
015F:0056408F  90                  NOP
 

Puis il faut tracer jusqu'à la fin de cette deuxième zone. Pour y arriver plus rapidement on peut poser un bpm eip+5bb x . On arrive ici:

015F:00564632  0385A0304400        ADD       EAX,[EBP+004430A0]
015F:00564638  5B                  POP       EBX                     <-- on tombe là
015F:00564639  0BDB                OR        EBX,EBX
015F:0056463B  8985D92E4400        MOV       [EBP+00442ED9],EAX
015F:00564641  61                  POPAD
015F:00564642  7508                JNZ       0056464C
015F:00564644  B801000000          MOV       EAX,00000001
015F:00564649  C20C00              RET       000C
015F:0056464C  68B8665500          PUSH      005566B8
015F:00564651  C3                  RET                                                           <-- fin 2ème zone

Donc en 564651 il va vers la troisième zone mémoire. On y va nous aussi :

015F:005566B5  8D4000              LEA       EAX,[EAX+00]
015F:005566B8  55                  PUSH      EBP               <-- on est là
015F:005566B9  8BEC                MOV       EBP,ESP
015F:005566BB  83C4F4              ADD       ESP,-0C
015F:005566BE  E86DFBFEFF          CALL      00546230
015F:005566C3  0F858F09FFFF        JNZ       00547058
015F:005566C9  E8460EFFFF          CALL      00547514
015F:005566CE  E84537FFFF          CALL      00549E18
015F:005566D3  E81C55FFFF          CALL      0054BBF4
015F:005566D8  E8A3AAFFFF          CALL      00551180
015F:005566D8  E8A3AAFFFF          CALL      00551180
015F:005566DD  E87609FFFF          CALL      00547058         <-- on rentre dans ce call
015F:005566E2  8BE5                MOV       ESP,EBP
015F:005566E4  5D                  POP       EBP
015F:005566E5  C20C00              RET       000C
015F:005566E8  0000                ADD       [EAX],AL
015F:005566EA  0000                ADD       [EAX],AL
015F:005566EC  0000                ADD       [EAX],AL
015F:005566EE  0000                ADD       [EAX],AL
015F:005566F0  0000                ADD       [EAX],AL

Donc voici le début de la troisième zone mémoire d'asprotect, il faut toujours rentrer dans le dernier call pour s'occuper de l'anti debugger. Une fois que l'on est rentré dans ce call on rentre dans le 2ème que l'on rencontre et on trace pour arriver là :

015F:00555674  8B1574C75500        MOV       EDX,[0055C774]
015F:0055567A  8B45F8              MOV       EAX,[EBP-08]
015F:0055567D  E832E6FFFF          CALL      00553CB4
015F:00555682  8A15DCB65500        MOV       DL,[0055B6DC]
015F:00555688  8B45F8              MOV       EAX,[EBP-08]
015F:0055568B  E890E6FFFF          CALL      00553D20                 <-- call anti-debugger
015F:00555690  8945F4              MOV       [EBP-0C],EAX
015F:00555693  837DF400            CMP       DWORD PTR [EBP-0C],00
015F:00555697  7428                JZ        005556C1
015F:00555699  8B45F4              MOV       EAX,[EBP-0C]

 Le call en 55568b est l'anti-debugger ensuite il met eax dans ebp-0c et regarde si c'est 0. Donc je remplace le call par mov eax, 0 (on peut simplement mettre 0 dans eax à la sortie du call). Ensuite on appuie sur F5 et softice devrait réapparaitre. En effet j'ai dit au tout début de mettre un bpm 4b8000 w pour savoir quand il écrira dans la zone de l'import table. On doit arriver ici :

015F:00545709  782A                JS        00545735
015F:0054570B  F3A5                REPZ MOVSD                <-- on arrive là
015F:0054570D  89C1                MOV       ECX,EAX
015F:0054570F  83E103              AND       ECX,03
015F:00545712  F3A4                REPZ MOVSB
015F:00545714  5F                  POP       EDI
015F:00545715  5E                  POP       ESI
015F:00545716  C3                  RET
015F:00545717  8D740EFC            LEA       ESI,[ECX+ESI-04]
015F:0054571B  8D7C0FFC            LEA       EDI,[ECX+EDI-04]

Donc il copie ce qu'il y a en esi vers edi. Or edi == 4b8004 et esi == C72824. Ici il copie vers la zone où devrait être la table d'import des 00. Mais comment ce fait-il qu'il utilise une zone en c70000. On va regarder avec softice ce qu'il y a :

0167:00C72500 97 1F FB 4D B4 B2 65 77-1B 59 3D 6C ED E4 00 D0  ...M..ew.Y=l....
0167:00C72510 88 0B 00 01 69 6D 6D 33-32 2E 64 6C 6C 00 01 18  ....imm32.dll...
0167:00C72520 8C 90 8F 6D 2A 4B F0 E9-95 CE F8 38 EC 02 E5 C9  ...m*K.....8....
0167:00C72530 CB 82 44 A9 C1 4D E5 EA-01 17 8C 90 8F 6D 2A 4B  ..D..M.......m*K

Bizare on trouve des références à des dlls. Il faut garder cela en tête. On peut enlever le point d'arrêt en écriture car il va encore y écrire par la suite mais dans cette partie nous n'iront pas plus loin. Donc on continue de tracer (f10) pour arriver au moment ou asprotect passe la main au prog décompressé en mémoire. On arrive normalement là :

015F:00555DE9  8B4508              MOV       EAX,[EBP+08]
015F:00555DEC  8B10                MOV       EDX,[EAX]
015F:00555DEE  8B4508              MOV       EAX,[EBP+08]
015F:00555DF1  8B401C              MOV       EAX,[EAX+1C]
015F:00555DF4  E887F6FFFF          CALL      00555480             <-- on rentre là
015F:00555DF9  5F                  POP       EDI
015F:00555DFA  5E                  POP       ESI
015F:00555DFB  5B                  POP       EBX
015F:00555DFC  5D                  POP       EBP
015F:00555DFD  C20400              RET       0004

Bon on reconnait facilement ce call grace au fait qu'il récupère les registres juste après. Il faut donc y rentrer, sinon le prog se lance. Ensuite on arrive là :

015F:005554A4  B854775400          MOV       EAX,00547754
015F:005554A9  E8AE3CFFFF          CALL      0054915C
015F:005554AE  E86D0AFFFF          CALL      00545F20        <-- on évite ce call
015F:005554B3  33C0                XOR       EAX,EAX
015F:005554B5  5A                  POP       EDX
015F:005554B6  59                  POP       ECX
015F:005554B7  59                  POP       ECX
015F:005554B8  648910              MOV       FS:[EAX],EDX
015F:005554BB  EB0A                JMP       005554C7
015F:005554BD  E93208FFFF          JMP       00545CF4

Et là il faut eviter de passer ce deuxième call sinon il utilise des sehs pour lancer le prog et on s'y pert. Don soit on le nop soit on fait r eip eip+5 quand on est dessus. Ensuite on à la même chose plus loin :

015F:005554D9  B854775400          MOV       EAX,00547754
015F:005554DE  E8793CFFFF          CALL      0054915C
015F:005554E3  E8380AFFFF          CALL      00545F20         <-- on évite
015F:005554E8  33C0                XOR       EAX,EAX
015F:005554EA  5A                  POP       EDX
015F:005554EB  59                  POP       ECX
015F:005554EC  59                  POP       ECX
015F:005554ED  648910              MOV       FS:[EAX],EDX
015F:005554F0  EB0A                JMP       005554FC
015F:005554F2  E9FD07FFFF          JMP       00545CF4

On fait pareil r eip eip+5 ou on nop. Il reste encore un double call, ou on évite le deuxième :

015F:00555534  648920              MOV       FS:[EAX],ESP
015F:00555537  33C9                XOR       ECX,ECX
015F:00555539  B201                MOV       DL,01
015F:0055553B  B854775400          MOV       EAX,00547754
015F:00555540  E8173CFFFF          CALL      0054915C
015F:00555545  E8D609FFFF          CALL      00545F20             <-- on évite
015F:0055554A  33C0                XOR       EAX,EAX
015F:0055554C  5A                  POP       EDX
015F:0055554D  59                  POP       ECX
015F:0055554E  59                  POP       ECX

De même on fair r eip eip+5 quand on est sur le call. Maintenant on continue de tracer pour arriver ici :

015F:00555590  EBE8                JMP       0055557A
015F:00555592  61                  POPAD                          <-- eax a l'eip
015F:00555593  EB01                JMP       00555596
015F:00555595  E850EB02E9          CALL      E95840EA
015F:0055559A  17                  POP       SS
015F:0055559B  E802000000          CALL      005555A2
015F:005555A0  E91758803D          JMP       3DD5ADBC
015F:005555A5  88C7                MOV       BH,AL
015F:005555A7  55                  PUSH      EBP
015F:005555A8  0000                ADD       [EAX],AL

Ici on retrouve le popad qui est caractéristique d'une fin de décompression . Et en effet à ce moment eax contient l'eip du prog décompressé en mémoire et plus loin un ret nous y envoie. Mais avant de faire quelquechose regardons donc l'état de la zone en 4b8000 ou devrait être la table d'import :

015F:004B8180 F4 49 C7 00 00 4A C7 00-0C 4A C7 00 18 4A C7 00  .I...J...J...J..
015F:004B8190 24 4A C7 00 30 4A C7 00-3C 4A C7 00 48 4A C7 00  $J..0J..<J..HJ..
015F:004B81A0 54 4A C7 00 60 4A C7 00-6C 4A C7 00 78 4A C7 00  TJ..`J..lJ..xJ..
015F:004B81B0 84 4A C7 00 90 4A C7 00-9C 4A C7 00 A8 4A C7 00  .J...J...J...J..

Et qu'est-ce qu'on y retrouve et bien des références vers la zone c7xxxx. Et oui il utilise le même principe (bien que différent) que cdilla. Pour appeler une api il fait call [4b8180], qui appel ce qu'il y a en c749f4 et là on a un truc du genre jmp api. En fait c'est plus complexe (voir la partie du tut qui en parle), il décrypte certaines choses pour avoir l'api. Mais cela il le fait quand le programme a besoin de cette api. Donc l'idée est de rajouter cette partie au programme donc il faut dumper ce qu'il y a en c7xxxx. Pour ce faire il faut savoir où commence cette zone et où elle se termine. On regarde sous softice et on voit (entre des zones mémoires invalides) qu'elle commence en c70000 et qu'elle se termine en c78000. Donc On peut dumper cette zone en utilisant icedump (extension pour softice) et en faisant : pagein d c70000 8000 c:\import.dat . On obtiendra ainsi un dump de cette zone dans le fichier import.dat.
Cependant il ne faut pas ce précipiter et dumper le prog ensuite directement. En effet si on analyse cela de plus près et qu'on laisse le programme ce dérouler on constate que quand il fait appel à la zone en c7xxxx il fait également appel à une autre zone. Voici un exemple :

:00C74C32  0000                ADD       [EAX],AL
:00C74C34  1E                  PUSH      DS
:00C74C35  0000                ADD       [EAX],AL
:00C74C37  006842              ADD       [EAX+42],CH
:00C74C38  68424CC700          PUSH      00C74C42
:00C74C3D  E84A048EFF          CALL      0055508C                    <-- il appel une zone mémoire en 55508c
:00C74C42  7A2C                JP        00C74C70
:00C74C44  C7009A2CC700        MOV       DWORD PTR [EAX],00C72C9A
:00C74C4A  C7002A560000        MOV       DWORD PTR [EAX],0000562A
:00C74C50  1E                  PUSH

On voit qu'il se sert d'une zone mémoire situé en 55508c. Or ceci correspond au endroit ou asprotect se décompresse. Donc pour que le programme marche la zone d'asprotect doit aussi être présente. Il faut donc la dumper aussi. Comme tout à l'heure on repère toute la zone entre des zones mémoires invalides, mais attention ici certaine partie sont encore invalide, donc il faut bien regarder. On trouve que cette zone s'étend de 520000 à 567000, il faut donc la dumper comme ceci : pagein d 520000 44000 c:\asprotect.dat . Maintenant on a la zone d'asprotect dans le fichier asprotect.dat .
On peut maintenant passer au dump du programme par lui même. Au niveau du popad on fait a eip pour modifier l'instruction et on met jmp eip pour qu'il boucle sur lui-même. Ensuite f5 pour sortir du programme et il reste a dumper le programme avec procdump en faisant un dump full sur la cible en mémoire.
 

2) Reconstruction du dump

Maintenant avec tout cela il faut reconstituer un exe valide. J'avais utilisé une première méthode très peu détaillé et assez compliqué. Un jour TeeJi m'a demandé pourquoi j'avais fait cela et pourquoi je n'avais pas utilisé les sections ? heu oui pourquoi ... heu ... il faut le temps que ca monte au cerveau ... lol :). En fait je n'y est pas pensé une seule seconde. Donc la je vais le faire ca va être nettement plus simple.

Bon tout d'abord il faut faire une petite manipulaiton. Il faut copier la section d'asprotect (celle qui est déjà dans le fichier) du prog d'origine (le protégé) et le mettre sur celle de notre dump. On fait ca car sinon la table d'import (celle utilisé par asprotect pas celle dont nous parlions) est abimé et on ne peut pas utiliser le programme dumpé. Pour savoir ou est le début de cette zone on cherche avec un héditeur hexa 90 60 E8 01 00 00 00 90  5D c'est le début de la zone d'asprotect (toujours) et on copi de la à la fin du prog, et on le remet à la place de celle du programme dumpé (on cherche la même chaine pour être au début).

Ensuite les deux autres dumps que l'on a fait il faut les rajoutés au programme. Cependant il faut qu'il soit remis dans les zones mémoires où ils se trouvaient. Pour ce faire on va utiliser procdump, puis peeditor et on ouvre notre programme dumpé. On va dans section et on fait add section. On rajoute une section avec ces caractéristiques :

Name: .aspr     VS: 00047000  VA: 00120000  RS: 00047000  RA: 00115400  C: E0000020

C'est la section pour le fichier asprotect.dat. On met une virtual adresse de 120000 (plus l'image base == 520000) pour qu'il se trouve au bon endroit en mémoire. La taille du dump était de 47000h donc on met 47000h. La RA est géré par procdump (ca de moins à faire :) ) et on peut changer les caractéristiques de la section mais ce n'est pas obligatoire.
Ensuite On rajoute la section pour import.dat :

Name: .import   VS: 00008000  VA: 00870000  RS: 00008000  RA: 0015C400  C: E0000020

Même explication que précédement. Ensuite il ne faut pas oublié de changer la taille de l'image. Je l'avoue je n'e m'en préoccupe pas car j'utilise procinfo (de TeeJi) qui le fait à ma place. Mais vous il faut le faire :) en utilisant la taille rajouté dans les sections que l'on rajoute à la taille de l'image.

Bon maintenant que ceci est fait, on prend son éditeur hexa et on ouvre le fichier asprotect.dat et on copi tout. On insère cela à la fin du dump de pleditor. On fait ensuite la même chose avec le fichier import.dat. On sauvegarde le dump et on change l'eip (celui contenu dans eax au niveau du popad), ici on fait 4b327c - 400000 (image base) = b327c. Donc le nouvel eip est b327c, on le change soit avec l'éditeur hexa soit avec pe-editor de procdump.

Maintenant on lance le dump et il se lance. CooL :). On a enfin notre dump qui est executable. Il ne nous reste plus qu'à cracker le dump ...
 
 
 
 
III_2ème méthode: Advanced mail list verify 2.0

N'ayant pas réussi à utiliser la méthode précédente sur amv, je vais vous présenter une méthode que Tsehp a utilisé sur commview. Remarquez que cette méthode ne marche pas sur pleditor (enfin Tsehp l'a changé: voir partie4). Cette méthode est notamment utilisé avec cdilla: c'est ce qu'on appel un "call fixer". Il permet de mettre les adresses des apis (enfin des fonctions) dans la table d'import (enfin ici dans l'iat). Donc en fait on aura toujours pas une iat et une table d'import correct au vrai sens du terme mais on n'aura plus besoin de dumper le chunk de l'it et la partie d'asprotect.

Regardons d'abord un peu comment de présentent les sections du programmes :

Name: .text     VS: 00028000  VA: 00001000  RS: 00012200  RA: 00001000  C: C0000040
Name: .rdata    VS: 00003000  VA: 00029000  RS: 00000C00  RA: 00013200  C: C0000040
Name: .data     VS: 0000D000  VA: 0002C000  RS: 00001400  RA: 00013E00  C: C0000040
Name: .rsrc     VS: 00029000  VA: 00039000  RS: 00019000  RA: 00015200  C: C0000040
Name: .data     VS: 00015000  VA: 00062000  RS: 00014E00  RA: 0002E200  C: C0000040
Name: .data     VS: 00001000  VA: 00077000  RS: 00000000  RA: 00043000  C: C0000040

Ici point de section .idata mais une section .rdata donc la table d'import du prog décompressé aurait du (si elle existait) se trouvé dans la section .rdata. On va donc mettre un point d'arrêt sur le début de la section (lorsqu'il va y écrire) : bpm 429000 w . Ensuite il faut tracer comme tout à l'heure (je ne réexplique pas c'est identique) jusqu'au début de la zone trois d'asprotect. là on vire de la même facon le debugger, et softice réagit de même pour le point d'arrêt en écriture sur le début de la section .rdata. On trouve cette fois ci que le chunk de "l'import table" est compris entre de0000 et de4000.
Bon on enlève notre point d'arrêt et on trace jusqu'à la fin (identique à tout à l'heure à l'exception des doubles calls qui n'y sont pas). On passe ensuite au début du programme :

015F:00421BFB  C3                  RET
015F:00421BFC  55                  PUSH      EBP                   <-- début du prog
015F:00421BFD  8BEC                MOV       EBP,ESP
015F:00421BFF  6AFF                PUSH      FF
015F:00421C01  6860944200          PUSH      00429460
015F:00421C06  68985B4200          PUSH      00425B98
015F:00421C0B  64A100000000        MOV       EAX,FS:[00000000]
015F:00421C11  50                  PUSH      EAX
015F:00421C12  64892500000000      MOV       FS:[00000000],ESP
015F:00421C19  83EC58              SUB       ESP,58

Au passage on en profite pour noté que l'eip est 421bfc. On continue de tracer pour arriver là :

015F:00421C19  83EC58              SUB       ESP,58
015F:00421C1C  53                  PUSH      EBX
015F:00421C1D  56                  PUSH      ESI
015F:00421C1E  57                  PUSH      EDI
015F:00421C1F  8965E8              MOV       [EBP-18],ESP
015F:00421C22  FF1574914200        CALL      [00429174]         <-- intérressant
015F:00421C28  33D2                XOR       EDX,EDX
015F:00421C2A  8AD4                MOV       DL,AH
015F:00421C2C  8915B86B4300        MOV       [00436BB8],EDX
015F:00421C32  8BC8                MOV       ECX,EAX

Là on retrouve ce que j'avais expliqué pour pleditor. Il appel ce qu'il y a normalement dans la table d'import (ici en 429174 au début de la section .rdata) et on trouve en 429174, de2464. Donc il va appelé ce qu'il y a en de2464 :

015F:00DE2464  E993091BBF          JMP       KERNEL32!GetVersion
015F:00DE2469  1B00                SBB       EAX,[EAX]
015F:00DE246B  000E                ADD       [ESI],CL
015F:00DE246D  0000                ADD       [EAX],AL
015F:00DE246F  00E9                ADD       CL,CH
015F:00DE2471  37                  AAA
015F:00DE2472  A11ABF1B00          MOV       EAX,[001BBF1A]

Et en de2464 c'est ce jump api. Voilà comment il retrouve ces fonctions. Mais ce n'est pas tout je vous ai dit qu'il en décrypté au runtime. On continue de tracé le programme et voici un endroit intérressant (on cherche tjs un call [429xxxx] ) :

015F:0040B8DB  51                  PUSH      ECX
015F:0040B8DC  52                  PUSH      EDX
015F:0040B8DD  FF1508904200        CALL      [00429008]                 <-- on a un call intérressant
015F:0040B8E3  85C0                TEST      EAX,EAX
015F:0040B8E5  7408                JZ        0040B8EF
015F:0040B8E7  8B44241C            MOV       EAX,[ESP+1C]
015F:0040B8EB  33F6                XOR       ESI,ESI
015F:0040B8ED  8907                MOV       [EDI],EAX

Pourquoi ce call [00429xxxx] est-il plus intérressant pour nous que d'autres? et bien voici ce qu'il fait par la suite :

015F:00DE2A14  681E2ADE00          PUSH      00DE2A1E             <-- on arrive là si on rentre dans le call
015F:00DE2A19  E816246DFF          CALL      004B4E34             <-- il appel une partie d'asprotect
015F:00DE2A1E  851F                TEST      [EDI],EBX
015F:00DE2A20  DE00                FIADD     WORD PTR [EAX]
015F:00DE2A22  AE                  SCASB
015F:00DE2A23  1F                  POP       DS
015F:00DE2A24  DE00                FIADD     WORD PTR [EAX]
015F:00DE2A26  DE00                FIADD     WORD PTR [EAX]

Et bien il va vers la même zone mémoire que tout à l'heure mais là il ne fait pas jmp api, mais call 004b4e34. C'est une partie qui est dans la zone d'asprotect. Voilà on a trouvé le call qui sert à décrypter les api. Il est très important, il faut le noter.

Bon maintenant on recommence on lance le programme, on vire le changement d'adresse, on passe les décompressions on arrive dans la troisième zone, on vire l'anti-debugger et on oubli pas de remmettre notre bpm 429000 w. Normalement softice devrait s'arrêter sur le repz mosb de tout à l'heure, là où il copiait des zéro. Mais cette fois ci on laisse ce point d'arrêt et on appuis sur f5. Là softice devrait s'arrêté ici :

015F:004B5138  87FE                XCHG      EDI,ESI
015F:004B513A  AC                  LODSB
015F:004B513B  08C0                OR        AL,AL
015F:004B513D  74E4                JZ        004B5123
015F:004B513F  4E                  DEC       ESI
015F:004B5140  56                  PUSH      ESI
015F:004B5141  53                  PUSH      EBX
015F:004B5142  80F802              CMP       AL,02
015F:004B5145  7407                JZ        004B514E
015F:004B5147  0FB64E01            MOVZX     ECX,BYTE PTR [ESI+01]
015F:004B514B  41                  INC       ECX
015F:004B514C  EB05                JMP       004B5153
015F:004B514E  B904000000          MOV       ECX,00000004
015F:004B5153  41                  INC       ECX
015F:004B5154  01CE                ADD       ESI,ECX
015F:004B5156  E8B5FDFFFF          CALL      004B4F10                <-- cherche les apis
015F:004B515B  AB                  STOSD
015F:004B515C  EBDC                JMP       004B513A                <-- retourne au début
015F:004B515E  61                  POPAD

Et là on tombe dans une boucle. Si on regarde on trouve dans edi des trucs du genre 429004. En gros cette routine sert à écrire dans la table d'import normal (en 429000) les références à la table d'import en de0000. Donc l'idée ici est qu'il n'écrive pas en 429000 des références à la zone en de0000, mais qu'il mette directement les adresses des apis qui seront utilisés. Et c'est pour cela que tout à l'heure on a cherché le call 4b4e34 qui sert à décrypter les adresses des apis.
C'est donc la qu'on va mettre le call fixer. Remarquez que si vous avez la flemme Tsehp propose de trouver le call 4b4e34 en faisant S 0 L FFFFFFFF 55 8b ec c4 f8 fe ff. Pour cette boucle on peut la trouver avec S 0 L FFFFFFFF AC 08 c0 74 E4. Mais bon il est utile de savoir d'où cela provient. Maintenant il faut avant que cette boucle ne s'éxécute écrire un call fixer. Et c'est là que l'on dit merci Tsehp :). En effet il proposait cette méthode sur le programme commview. Donc voici le principe :

015F:004B514E  B904000000          MOV       ECX,00000004
015F:004B5153  41                  INC       ECX
015F:004B5154  01CE                ADD       ESI,ECX
015F:004B5156  E8B5FDFFFF          CALL      004B4F10            <-- on dévit là
015F:004B515B  AB                  STOSD
015F:004B515C  EBDC                JMP       004B513A            <-- saut pour la boucle

Ce qu'il faut faire c'est dévié au niveau du call et chercher un espace libre en mémoire (avec des 0000) pour y dévié le call et y rajouté notre code. Je l'ai dévié en 4b6500 :

015F:004B5147  0FB64E01            MOVZX     ECX,BYTE PTR [ESI+01]
015F:004B514B  41                  INC       ECX
015F:004B514C  EB05                JMP       004B5153
015F:004B514E  B904000000          MOV       ECX,00000004
015F:004B5153  41                  INC       ECX
015F:004B5154  01CE                ADD       ESI,ECX
015F:004B5156  E9A5130000          JMP       004B6500       <-- on dévit
015F:004B515B  AB                  STOSD
015F:004B515C  EBDC                JMP       004B513A
015F:004B515E  61                  POPAD

Et en 4b6500 on met le call fixer que Tsehp nous proposait (thx man :) ). Voici ce qu'il proposait comme call fixer :

190000 call 18a2f4               ; we use the legal call
190005 cmp ecx,40000000          ; ecx contains an api address ?
19000b jle 19001c                ; if not
19000d add ecx,eax               ; if yes convert the address***case 2
19000f add ecx,5                 ; to the absolute api address for a normal import table
190012 mov dword ptr [edi],ecx   ; put it in import table, pointed by edi
190014 add edi,4                 ; updates edi to the next import
190017 jmp 18a51e                ; back to normal
19001c cmp ecx,0                 ; is it case 4 ?
19001f jz 19002e
190021 cmp eax,40000000          ; eax contains an api address ?
190026 jle 19003c                ; if not go to 19003c
190028 stosd                     ; we're in case 1, direct copy of valid api address in import table
190029 jmp 18a51e                ; back to normal
19002e push dword ptr [eax+1]    ; we're in case 3, pushes the encrypted api address
190031 call 16df80               ;IMPORTANT
you have to locate this aspack address by doing a S 0 L FFFFFFFF 55 8b ec 81 c4 f8 fe ff ff 53 56
so we found as example 16df80, you MUST modify the code at offset 16df80+95 with three nops (90), if you don't
this call will generate an error 13 in aspack (the call doesn't return properly)
this call is used to decypher the encrypted api address, normally decrypted at run time

190036 stosd                     ; the api's address is then decrypted, copy it to import table
190037 jmp 18a51e                ; back to normal, don't forget that this is the loop back jump
19003c mov eax,KERNEL32!GetProcAddress     ; use softice to have your system's getprocaddress. this is case 4
190041 stosd                               ; copy to import table
190042 jmp 18a51e                ; back to normal

Bon mais ici ce call fixer ne fonctionne pas. Il va falloir le modifer, notamment au niveau du cmp ecx, 0 qui empêche de passer par le cmp eax, 40000000. Mais avant cela il reste quelquechose qui l'empécherait de toute facon de marcher. Ne nous préoccupons pas de la table d'import pour le moment et faisons le dump du prog (comme tout à l'heure mais cette fois juste le programme). Analysons donc un peut le dump que nous avons obtenu et regardons notamment le début de la section .rdata :

00029000 DC29 DE00 F829 DE00 142A DE00 302A DE00 .)...)...*..0*..
00029010 4C2A DE00 682A DE00 842A DE00 A02A DE00 L*..h*...*...*..
00029020 BC2A DE00 0000 0000 482B DE00 542B DE00 .*......H+..T+..
00029030 602B DE00 6C2B DE00 782B DE00 842B DE00 `+..l+..x+...+..
00029040 0000 0000 4228 F2BF FE24 F2BF D824 F2BF ....B(...$...$..
00029050 3A28 F2BF 8A28 F2BF 9322 F2BF 3551 F2BF :(...(..."..5Q..
00029060 144A F2BF 7B50 F2BF 8D14 F2BF 7F26 F2BF .J..{P.......&..
00029070 0000 0000 7021 DE00 7C21 DE00 8821 DE00 ....p!..|!...!..
00029080 9421 DE00 A021 DE00 AC21 DE00 B821 DE00 .!...!...!...!..
00029090 C421 DE00 D021 DE00 DC21 DE00 E821 DE00 .!...!...!...!..
000290A0 F421 DE00 0022 DE00 0C22 DE00 1822 DE00 .!..."..."..."..
000290B0 2422 DE00 3022 DE00 3C22 DE00 4822 DE00 $"..0"..<"..H"..
000290C0 5422 DE00 6022 DE00 203D 4B00 6C22 DE00 T"..`".. =K.l"..
000290D0 7822 DE00 8422 DE00 9022 DE00 9C22 DE00 x"..."..."..."..
000290E0 A822 DE00 B422 DE00 C022 DE00 CC22 DE00 ."..."..."..."..

On retrouve bien évidemment des références à la zone dexxxx. Mais en 290c8 (4290c8 en mémoire) on trouve 4b3d20, or ceci fait partie de la section d'asprotect. Comment ce fait-il qu'il mette un lien vers cette zone ici ? Pour le savoir on va relancer le programme (on enlève le chgt d'adresse + anti-debugger) et on met un point d'arrêt sur 4b3d20: bpm 4b3d20 x . Normallement softice apparait là :

015F:004B3D1F  C3                  RET
015F:004B3D20  55                  PUSH      EBP
015F:004B3D21  8BEC                MOV       EBP,ESP
015F:004B3D23  8B550C              MOV       EDX,[EBP+0C]
015F:004B3D26  8B4508              MOV       EAX,[EBP+08]
015F:004B3D29  3B0584B64B00        CMP       EAX,[004BB684]         <-- eax == -1 ?
015F:004B3D2F  7509                JNZ       004B3D3A               <-- non on saute
015F:004B3D31  8B0495E0B64B00      MOV       EAX,[EDX*4+004BB6E0]   <-- oui on met 4b3da8 dans eax
015F:004B3D38  EB07                JMP       004B3D41               <-- et on retourne dans le prog
015F:004B3D3A  52                  PUSH      EDX
015F:004B3D3B  50                  PUSH      EAX
015F:004B3D3C  E83739FFFF          CALL      KERNEL32!GetProcAddress    <-- sinon on récupère l'adresse qu'il veut
015F:004B3D41  5D                  POP       EBP
015F:004B3D42  C20800              RET       0008                       <-- et on retourne dans le programme
015F:004B3D45  8D4000              LEA       EAX,[EAX+00]
015F:004B3D48  55                  PUSH      EBP

Intérressant non ? Donc dans notre call fixer il va falloir tenir compte du fait que eax peut être égal à 4b3d20. Le programme fait appel plusieurs fois à cette routine mais il ne met qu'une seule fois 4b3da8 dans eax. De plus En testant le programme, à aucun moment le programme n'a fait appel a ce qu'il y a en 4b3da8 (ca sert peut-être à décrypté une région du programme, mais la une clef est nécessaire, enfin je ne sait à quoi sert cette partie). Ensuite dans notre dump il faudra également remettre cette routine, et vu que le prog ne c'est pas servi de ce qu'il y avait en 4b3da8 je ne l'ai pas remis (de toutes facon ca aurait été beaucoup plus compliqué, mais je pense qu'il s'en sert pour décrypté une partie du programme si on a une clef).
Bon maintenant on peut refaire le call fixer pour qu'il tienne compte de cela :

015F:004B6500  E80BEAFFFF          CALL      004B4F10               <-- on remet le call
015F:004B6505  81F900000040        CMP       ECX,40000000           <-- ecx contient une adresse d'api
015F:004B650B  760F                JBE       004B651C               <-- non on saute
015F:004B650D  03C8                ADD       ECX,EAX                <-- oui on calcule l'adresse
015F:004B650F  83C105              ADD       ECX,05
015F:004B6512  890F                MOV       [EDI],ECX              <-- et on la met dans la table d'import
015F:004B6514  83C704              ADD       EDI,04                 <-- on augment edi pour l'import suivant
015F:004B6517  E91EECFFFF          JMP       004B513A               <-- et on boucle
015F:004B651C  3D00000040          CMP       EAX,40000000           <-- eax contient une adresse d'api
015F:004B6521  7606                JBE       004B6529               <-- non on saute
015F:004B6523  AB                  STOSD                            <-- oui on copi l'adresse dans l'import table
015F:004B6524  E911ECFFFF          JMP       004B513A               <-- et on boucle
015F:004B6529  3D203D4B00          CMP       EAX,004B3D20           <-- eax = 4b3d20
015F:004B652E  7506                JNZ       004B6536               <-- non on saute
015F:004B6530  AB                  STOSD                            <-- oui on le copi dans l'import table
015F:004B6531  E904ECFFFF          JMP       004B513A               <-- et on boucle
015F:004B6536  83F900              CMP       ECX,00                 <-- ecx = 0
015F:004B6539  750E                JNZ       004B6549               <-- non on saute
015F:004B653B  FF7001              PUSH      DWORD PTR [EAX+01]     <-- oui on met sur la pile la ref à
                                                                        l'adresse de l'api
015F:004B653E  E8F1E8FFFF          CALL      004B4E34               <-- et on appel le call de décryptage
015F:004B6543  AB                  STOSD                            <-- puis on copi eax dans la table d'import
015F:004B6544  E9F1EBFFFF          JMP       004B513A               <-- et on boucle
015F:004B6549  B8AC6DF7BF          MOV       EAX,KERNEL32!GetProcAddress        <-- sinon on met l'adresse
015F:004B654E  AB                  STOSD                            <-- de getprocaddress dans la table
                                                                        d'import
015F:004B654F  E9E6EBFFFF          JMP       004B513A               <-- et on boucle
015F:004B6554  0000                ADD       [EAX],AL
015F:004B6556  0000                ADD       [EAX],AL

Voilà le call fixer qui va mettre directement les adresses des apis dans la table d'import. Mais pour s'en servir il faut faire quelquechose sur le call 4b4e34 que l'on a trouvé précedement et qui sert à décrypter ces adresses :

004B4E34 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
004B4E34
004B4E34 ; Attributes: bp-based frame
004B4E34
004B4E34 sub_4B4E34      proc near               ; CODE XREF: .import:00DE29FDp
004B4E34                                         ; .import:00DE2A19p ...
004B4E34
004B4E34 var_108         = byte ptr -108h
004B4E34 var_8           = dword ptr -8
004B4E34 var_4           = dword ptr -4
004B4E34 arg_0           = dword ptr  8
004B4E34
004B4E34                 push    ebp
004B4E35                 mov     ebp, esp
004B4E37                add     esp, 0FFFFFEF8h
004B4E3D                 push    ebx
004B4E3E                 push    esi
004B4E3F                 mov     ebx, [ebp+arg_0]
004B4E42                 mov     eax, [ebx]
004B4E44                 mov     [ebp+var_8], eax
004B4E47                 lea     eax, [ebp+var_108]
004B4E4D                 xor     ecx, ecx
004B4E4F                 mov     edx, 100h
004B4E54                 call    sub_4A5880
004B4E59                 mov     eax, ebx
004B4E5B                 mov     edx, [eax+4]
004B4E5E                 mov     dl, [edx]
004B4E60                 cmp     dl, ds:byte_4BB74C    <-- je sais c'est mal désassemblé mais bon ...
004B4E66                 jz      short loc_4B4EB5
004B4E68                 mov     edx, [eax+4]
004B4E6B                 mov     ecx, edx
004B4E6D                 inc     ecx
004B4E6E                 mov     bl, [ecx]
004B4E70                 add     edx, 2
004B4E73                 mov     [ebp+var_4], edx
004B4E76                 mov     esi, ebx
004B4E78                 and     esi, 0FFh
004B4E7E                 mov     ecx, esi
004B4E80                 lea     eax, [ebp+var_108]
004B4E86                 mov     edx, [ebp+var_4]
004B4E89                 call    sub_4A76F0
004B4E8E                 mov     eax, [ebp+var_8]
004B4E91                 call    sub_4A817C
004B4E96                 sub     eax, 2
004B4E99                 push    eax
004B4E9A                 mov     edx, esi
004B4E9C                 lea     eax, [ebp+var_108]
004B4EA2                 mov     ecx, [ebp+var_8]
004B4EA5                 call    sub_4B3564
004B4EAA                 lea     eax, [ebp+var_108]
004B4EB0                 mov     [ebp+var_4], eax
004B4EB3                 jmp     short loc_4B4EBE
004B4EB5 ; ---------------------------------------------------------------------------
004B4EB5
004B4EB5 loc_4B4EB5:                             ; CODE XREF: sub_4B4E34+32j
004B4EB5                 mov     eax, [eax+4]
004B4EB8                 inc     eax
004B4EB9                 mov     eax, [eax]
004B4EBB                 mov     [ebp+var_4], eax
004B4EBE
004B4EBE loc_4B4EBE:                             ; CODE XREF: sub_4B4E34+7Fj
004B4EBE                 push    [ebp+var_4]
004B4EC1                 push    [ebp+var_8]
004B4EC4                 call    sub_4B4C8C
004B4EC9                 mov     [ebp+4], eax        <-- il faut nopper cette instruction
004B4ECC                 pop     esi
004B4ECD                 pop     ebx
004B4ECE                 mov     esp, ebp
004B4ED0                 pop     ebp
004B4ED1                 retn    4
004B4ED1 sub_4B4E34      endp
004B4ED1
004B4ED4

Il faut nopper l'instruction en 4b4ec9 sinon on aura droit à une erreur 13 et le prog s'arrêtera. Voilà maintenant on continu de tracer le programme (on laisse notre "call fixer" décrypté les adresses) et on va jusqu'à l'endroit où le programme passe la main à celui décompressé en mémoire. On retrouve le call suivi de la sauvegarde des registre, donc on rentre dedans. Mais ensuite on trouve presque tout de suite le popad. Là on note le nouvel eip : 421bfc, et on fait a eip et on met jmp eip. On quitte softice (f5) et on dump la cible avec procdump. Attention utilisez l'option don't rebuild import table ou use actual import, pour le dump.
Maintenant comme pour pleditor il faut changer l'eip avec le nouveau soit 21bfc (421bfc-400000). Il faut également copié la section .aspr (ici c'est l'avant dernière section la .data) de l'original sur celle du dump. Ensuite on édite avec un éditeur hexa ce qu'il y a en 4290c8. Et oui il y a la référence en 4b3d20, donc on va mettre une référence vers une zone libre du programme.

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00029090   0D 0B F8 BF 56 F6 F9 BF  15 0A F8 BF 24 2E F9 BF   ..ø¿Vöù¿..ø¿$.ù¿
000290A0   C4 64 F7 BF 93 7B F7 BF  AD 73 F7 BF 2B 0B FA BF   Äd÷¿“{÷¿­s÷¿+.ú¿
000290B0   D5 6F F7 BF B4 5C F9 BF  2C 62 F9 BF FE D5 F9 BF   Õo÷¿´\ù¿,bù¿þÕù¿
000290C0   B4 20 F8 BF EF 62 F9 BF  00 70 47 00 A0 E0 F8 BF   ´ ø¿ïbù¿..w. àø¿
000290D0   B3 CA F8 BF 85 7D F7 BF  65 43 F7 BF 3C 43 F7 BF   ³Êø¿…}÷¿eC÷¿<C÷¿
000290E0   B8 48 F7 BF DB 6D F7 BF  1F 6E F7 BF 41 6E F7 BF   ¸H÷¿Ûm÷¿.n÷¿An÷¿

J'ai trouvé de la place libre en 477000. Donc il va falloir rajouté la routine qui se trouvait normalement en 4b3d20 :

015F:00477000  55                  PUSH      EBP
015F:00477001  8BEC                MOV       EBP,ESP
015F:00477003  8B550C              MOV       EDX,[EBP+0C]
015F:00477006  8B4508              MOV       EAX,[EBP+08]
015F:00477009  3DFFFFFFFF          CMP       EAX,FFFFFFFF
015F:0047700E  90                  NOP
015F:0047700F  7509                JNZ       0047701A
015F:00477011  B8A83D4B00          MOV       EAX,004B3DA8
015F:00477016  90                  NOP
015F:00477017  90                  NOP
015F:00477018  EB07                JMP       00477021
015F:0047701A  52                  PUSH      EDX
015F:0047701B  50                  PUSH      EAX
015F:0047701C  E88BFDAFBF          CALL      KERNEL32!GetProcAddress
015F:00477021  5D                  POP       EBP
015F:00477022  C20800              RET       0008

Voilà normalement maintenant le dump est complètement fonctionnel :). Il ne reste plus qu'à le cracké...
Enfin il existe une méthode plus simple pour obtenir les addresses: vous devez d'abord dumpé le programme. Ensuite l'exe d'origine doit être lancé et vous executé le programme import_list (désolé j'ai oublié le nom de l'auteur) qui vous donnera un fichier avec les bonnes adresses, il ne reste plus qu'à faire du copier/coller (vous aurez même un txt ave les changements :) ). Enfin sur ce programme il y a toujours le problème du 4b3d20 à régler ...
 

En fait je n'est pas pris le meilleur programme pour vous montrer cette exemple. En effet si vous relancé votre machine il y a peu de chance que le dump fonctionne, pourquoi ? et bien parce que certaine librairie de windows se charge à des endroits différents en mémoires. Voici ou se trouve le problème pour ce dump :

00029000 AA19 EABF 4416 EABF 3415 EABF D114 EABF ....D...4.......
00029010 EA15 EABF 7D16 EABF 2B18 EABF 8717 EABF ....}...+.......
00029020 2A17 EABF 0000 0000 97D3 7282 FE43 7082 *.........r..Cp.
00029030 F205 7582 F4DB 7182 77D8 7182 FD4E 7282 ..u...q.w.q..Nr.
00029040 0000 0000 4228 F2BF FE24 F2BF D824 F2BF ....B(...$...$..
00029050 3A28 F2BF 8A28 F2BF 9322 F2BF 3551 F2BF :(...(..."..5Q..
00029060 144A F2BF 7B50 F2BF 8D14 F2BF 7F26 F2BF .J..{P.......&..
00029070 0000 0000 DF7A F7BF E250 F8BF A570 F7BF .....z...P...p..

Il y a 6 adresses sélectionnées et voici à quoi elle correspondent :

00DE2B48->8272D397[2]=(00001028)COMCTL32.DLL!CreateToolbarEx:0017
00DE2B54->827043FE[2]=(0000102C)COMCTL32.DLL!InitCommonControls:0011
00DE2B60->827505F2[2]=(00001030)COMCTL32.DLL!CreateStatusWindow:0015
00DE2B6C->8271DBF4[2]=(00001034)COMCTL32.DLL!ImageList_ReplaceIcon:0046
00DE2B78->8271D877[2]=(00001038)COMCTL32.DLL!ImageList_Create:002D
00DE2B84->82724EFD[2]=(0000103C)COMCTL32.DLL!PropertySheet:0056

Donc pour ces 6 adresses il va falloir faire une modification. Je vais simplement vous donner le principe car la méthode qui suit fait pareil mais en nettement mieux (enfin la méthode de Tsehp celle qui suit a changé et n'y fait pas référence). Ces 6 adresses nous savons à quelles fonctions elles correspondent, donc le principe est de modifé l'eip du prog vers un endroit où on peut mettre notre code . Là il faut avoir préalablement noté le nom de la dll et des fonctions utilisées. Encuite en utilisant GetModuleHandle puis GetProcAddress on répurère l'adresse mémoire et on va l'écrire à son emplacement dans la section .rdata. Comme cela il n'y aura plus de problème d'adresse pour ces fonctions. Je n'est volontairement pas expliqué complétement cette partie car entre temps Tsehp a mis au point une nouvelle méthode de dump ... et dans celle ci vous comprendrez de quoi je parles ...
 
 
 
IV_3ème méthode: amv vu différement

Maintenant je vais essayer de décrire une méthode qui permet d'obtenir un dump qui marche sur toutes les machines (enfin sur toutes les version de win 9x si le dump est fait sous win 9x et sous les version de NT/2000 si le dump ... enfin voilà :) ). Je vais vous présenté une  méthode qui a été mise au point par Tsehp (very good work man): vous pouver trouver son essai original sur Commview à cette adresse : http://tsehp.cjb.net  en allant dans la section news, c'est l'essai sur asprotect1.05 . Je vous la présente car le début de sa méthode (comment obtenir les noms m'a permis d'élaborer ensuite la mienne).
Je vais essayer de vous expliquer cela clairement mais ca vas être difficile, car la méthode par elle même n'est pas simple (enfin quand on sait le faire ca devient plus simple :)). Tout d'abord le principe est le suivant : au lieu de faire un dump qui a les adresses vers les fonctions utilisées déjà ecrites dans la section .rdata (dans le cas de amv sinon ca peut-être la .idata comme pleditor) il faudrait plutôt que l'on récupère le nom de cette fonction (comme CreateFileA) leur module (comme kernel32.dll) et l'endroit où elle doivent être dans la section .rdata (ou .idata). Comme cela dans le dump il suffirait de dévier le début du programme vers un bout de code qui se chargerait de récupérer l'adresse de ces fonctions et de les écrires à leurs places dans la section .rdata, comme cela le dump marcherai sur toutes les versions de win9x (ou nt/2000 si le dump est fait avec).
Où pourrait-on faire ca? Et bien au même endroit que précédement, au niveau du call fixer. Pourquoi là? et bien c'est très simple : tout d'abord on a chaque adresse vers la section .rdata où il écrit. Mais en plus pour faire ces liens il est bien obligés de connaitre de quelles fonctions il s'agit (en fait c'est plus compliqué que cela).

Bon je ne vous réexplique pas comment arrivé là, lisez la partie précédente :

015F:004B5138  87FE                XCHG      EDI,ESI
015F:004B513A  AC                  LODSB
015F:004B513B  08C0                OR        AL,AL
015F:004B513D  74E4                JZ        004B5123
015F:004B513F  4E                  DEC       ESI
015F:004B5140  56                  PUSH      ESI
015F:004B5141  53                  PUSH      EBX
015F:004B5142  80F802              CMP       AL,02
015F:004B5145  7407                JZ        004B514E
015F:004B5147  0FB64E01            MOVZX     ECX,BYTE PTR [ESI+01]
015F:004B514B  41                  INC       ECX
015F:004B514C  EB05                JMP       004B5153
015F:004B514E  B904000000          MOV       ECX,00000004
015F:004B5153  41                  INC       ECX
015F:004B5154  01CE                ADD       ESI,ECX
015F:004B5156  E8B5FDFFFF          CALL      004B4F10                <-- cherche les apis
015F:004B515B  AB                  STOSD
015F:004B515C  EBDC                JMP       004B513A                <-- retourne au début
015F:004B515E  61                  POPAD

Au niveau du call 4b4f10, on remarque que edi contient l'adresse de destination dans la section .rdata et certaine fois eax ou edx on l'adresse d'une fonction. Il serait donc intérressant de regarder un peu ce call 4b4f10. Je ne vais pas l'analyser, je vous conseil plutôt de lire l'essai de TeeJi qui a fait cela très bien. Voici qd même une petite partie :

004B4F10 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
004B4F10
004B4F10 ; Attributes: bp-based frame
004B4F10
004B4F10 sub_4B4F10      proc near               ; CODE XREF: sub_4B5094+C2p
004B4F10
004B4F10 var_11D         = byte ptr -11Dh
004B4F10 var_1D          = byte ptr -1Dh
004B4F10 var_1C          = dword ptr -1Ch
004B4F10 var_18          = byte ptr -18h
004B4F10 var_17          = dword ptr -17h
004B4F10 var_13          = byte ptr -13h
004B4F10 var_12          = dword ptr -12h
004B4F10 var_E           = dword ptr -0Eh
004B4F10 var_A           = dword ptr -0Ah
004B4F10 arg_0           = dword ptr  8
004B4F10 arg_4           = dword ptr  0Ch
004B4F10
004B4F10                 push    ebp
004B4F11                 mov     ebp, esp
004B4F13                 add     esp, 0FFFFFEE0h
004B4F19                 push    ebx
004B4F1A                 push    esi
004B4F1B                 push    edi
004B4F1C                 mov     edi, [ebp+arg_4]
004B4F1F                 mov     esi, [ebp+arg_0]
004B4F22                 mov     bl, [esi]
004B4F24                 lea     eax, [ebp+var_11D]         <-- notez l'adresse ebp-11d : pour moi 6afc6b
004B4F2A                 xor     ecx, ecx
004B4F2C                 mov     edx, 100h
004B4F31                 call    sub_4A5880
004B4F36                 sub     bl, 2
004B4F39                 jz      short loc_4B4F49
004B4F3B                 sub     bl, 2
004B4F3E                 jz      loc_4B4FE1
004B4F44                 jmp     loc_4B5035
004B4F49

.............................................................................    <-- j'ai coupé

004B508A
004B508A loc_4B508A:                             ; CODE XREF: sub_4B4F10+9Aj
004B508A                                         ; sub_4B4F10+B9j ...
004B508A                 pop     edi
004B508B                 pop     esi
004B508C                 pop     ebx
004B508D                 mov     esp, ebp
004B508F                 pop     ebp
004B5090                 retn    8
004B5090 sub_4B4F10      endp
004B5090

Bon là j'ai juste mis le début du call et la fin (il est long), mais en tracant et en ayant repéré l'adresse indiqué vous verez apparaitre le nom de la fonction (la première c'est CreateFileA). Et on resort du call (pour comprendre son utilité voir l'essai de TeeJi): là le nom de la fonction est toujours en 6afc6b. On peut repérer cette adresse à la sortit du call en faisant ebp-15dh mais ceci reste encore à vérifié. Donc obtient donc bien le nom de la fonction désirées, de plus le nom de la dll associé apparait en faisant d ebx, et dans edi on a l'adresse de destination dans la section .rdata. Donc on a tout, sauf pour les fonctions cryptées alors là comme dans la partie précédente on fait appel à la fonction de décryptage (voir la partie précédente pour savoir comment la localiser) et on obtient le nom de la fonction. Il ne reste plus qu'un cas a traité c'est le cas où les fonctions sont appelées par leurs ordinal ... et bien vous verez que contrairement à Tsehp je ne m'en préoccupe pas ... vous comprendrez pourquoi.

Bon maintenant attaquons nous à la bête :). Donc en 4b5156 on dévit le call en mettant un jmp 4b6500 (voir partie 3), où on a de la place libre. Ensuite il faut trouver un espace mémoire libre pour pouvoir aller écrire le noms des fonctions, des dlls et leur adresses dans la section .rdata. Pour ma part je rajoute le début de code suivant en 4b6500 que j'enlève après pour mettre le call fixer :

pushad                                             <-- sauve les registres
push 40                                            <-- rempli avec des 00
push 00003000                                <-- readable writable and executable
push 00008000                                <-- taille de la mémoire allouée (on prend ses précautions)
push 01000000                                <-- adresse où l'on veut allouée de la mémoire (j'ai mis 1000000 car il n'y avait rien mais ceci est aléatoire)
call KERNEL32!VirtualAlloc           <-- on alloue la mémoire
popad                                              <-- on restaure les registres

Maintenant que l'on a notre zone alloué en 1000000 et se remet au début de notre code en 4b6500 (r eip 4b6500). Maintenant là on place le call fixer qui va se charger de copier le noms des fonctions avec dlls et adresses de la section .rdata en 1000000. Voici le call fixer de Tsehp légèrement modifé :

015F:004B6500  E80BEAFFFF          CALL      004B4F10                      <-- on restaure le call
015F:004B6505  60                  PUSHAD                                  <-- on sauve les registres
015F:004B6506  833D6BFC6A0000      CMP       DWORD PTR [006AFC6B],00       <-- on regarde s'il y a un nom de fonction
015F:004B650D  7456                JZ        004B6565                      <-- si il n'y en a pas alors on va vers la
                                                                               décrytion / ordinal
015F:004B650F  6855FE6A00          PUSH      006AFE55                      <-- on met le nom de la foncttion
015F:004B6514  FF35F0644B00        PUSH      DWORD PTR [004B64F0]         <-- l'adresse ou l'on veut copier (avant
                                                                               d'éxécuter la boucle pensé à mettre
                                                                               00000001 en 4b64f0
015F:004B651A  E8DD0DACBF          CALL      KERNEL32!lstrcpy              <-- on copie
015F:004B651F  FF35F0644B00        PUSH      DWORD PTR [004B64F0]          <-- on met l'adresse ou se trouve le nom
015F:004B6525  E8830EACBF          CALL      KERNEL32!lstrlen              <-- on calcul sa longueur
015F:004B652A  40                  INC       EAX                           <-- pour rajouté un 0
015F:004B652B  43                  INC       EBX                           <-- pour être au début du nom de la dll
015F:004B652C  0105F0644B00        ADD       [004B64F0],EAX                <-- on augmente l'adresse de destination
015F:004B6532  53                  PUSH      EBX                           <-- on met le nom de la dll
015F:004B6533  FF35F0644B00        PUSH      DWORD PTR [004B64F0]          <-- l'adresse de destination
015F:004B6539  E8BE0DACBF          CALL      KERNEL32!lstrcpy              <-- on copie
015F:004B653E  FF35F0644B00        PUSH      DWORD PTR [004B64F0]          <-- on met l'adresse ou se trouve le nom
015F:004B6544  E8640EACBF          CALL      KERNEL32!lstrlen              <-- on calcul sa longueur
015F:004B6549  40                  INC       EAX                           <-- pour rajouté un 0
015F:004B654A  0105F0644B00        ADD       [004B64F0],EAX                <-- on augmente l'adresse de destination
015F:004B6550  8B0DF0644B00        MOV       ECX,[004B64F0]                <-- on met l'adresse dans ecx
015F:004B6556  8939                MOV       [ECX],EDI                     <-- et on y copie l'adresse de .rdata qui
                                                                               correspond à la fonction
015F:004B6558  8305F0644B0005      ADD       DWORD PTR [004B64F0],05       <-- on augmente l'adresse de destination
015F:004B655F  61                  POPAD                                   <-- on restaure les registres
015F:004B6560  E9D5EBFFFF          JMP       004B513A                      <-- et on retourne dans la boucle d'asprotect
                                                                               au niveau du stosd
015F:004B6565  3D00000040          CMP       EAX,40000000                  <-- eax contient l'adresse d'une api
015F:004B656A  7D14                JGE       004B6580                      <-- oui alors on va vers le traitement par
                                                                               ordinal
015F:004B656C  83F900              CMP       ECX,00                        <-- ecx == 0
015F:004B656F  750F                JNZ       004B6580                      <-- oui alors ordinal, sinon crypté
015F:004B6571  FF7001              PUSH      DWORD PTR [EAX+01]            <-- on met le paramêtre à la proc de
                                                                               décryption
015F:004B6574  E8BBE8FFFF          CALL      004B4E34                      <-- on décrypte (il faut mettre trois nop en
                                                                               4b4e34+95 pour éviter les pb
015F:004B6579  686BFC6A00          PUSH      006AFC6B                      <-- on met l'adresse du nom
015F:004B657E  EB94                JMP       004B6514                      <-- et on retourne à la copi
015F:004B6580  83EE04              SUB       ESI,04                        <-- ordinal alors on enlève 4 à esi
015F:004B6583  56                  PUSH      ESI                           <-- on le met sur la pile
015F:004B6584  EB8E                JMP       004B6514                      <-- et on retourne à la copie
015F:004B6586  0000                ADD       [EAX],AL
015F:004B6588  0000                ADD       [EAX],AL

Voilà je pense que cette fonction est assez bien détaillée. Cependant il faut mettre un bpm 4b6579 après le call de décryption pour vérifié si le nom de la proc est toujours à la même adresse. Si elle ne l'est pas et bien elle n'est pas très loin (un petit coup d'oeil sous softice) et on remplace l'adresse et après on peut boucler tranquilement. (note : un point d'arrêt après le call que l'on a dévié fait passer la boucle).
Une fois que la boucle est finie il faut copier tout ce qui est en 1000000 avec icedump, pagein d 1000000 2000 c:\noms.dat. Ensuite Tsehp propose de rajouté une section au dump et d'y mettre les noms (avec les adresses) puis d'écrire une procédure qui se chargerait de récupérer chaque nom (ou ordinal) et de récupérer l'adresse de la fonction avec getmodulehandle et getprocaddress (voir son tut), puis de mettre cette adresse en .rdata correspondand. Comme cela on aurait nous aussi reconstruit une fausse table d'import et le programme marcherait.

Mais là description de sa méthode s'arrête là. En effet j'ai changé tout ca de manière non pas à obtenir une fausse table d'import pour que le programme marche mais une vraie comme si on n'avait jamais touvhé au programme (aucun rajout de section ou de code après). Ceci est possible car pour le moment asprotect ne détruit pas encore tout ... enfin sur la version d'amv, vous verez après que la dernière version (pleditor, commview ...) est plus compliqué .... Enfin repartons du début :

015F:004B5138  87FE                XCHG      EDI,ESI
015F:004B513A  AC                  LODSB                              <-- on est là
015F:004B513B  08C0                OR        AL,AL
015F:004B513D  74E4                JZ        004B5123
015F:004B513F  4E                  DEC       ESI
015F:004B5140  56                  PUSH      ESI
015F:004B5141  53                  PUSH      EBX
015F:004B5142  80F802              CMP       AL,02
015F:004B5145  7407                JZ        004B514E
015F:004B5147  0FB64E01            MOVZX     ECX,BYTE PTR [ESI+01]
015F:004B514B  41                  INC       ECX
015F:004B514C  EB05                JMP       004B5153
015F:004B514E  B904000000          MOV       ECX,00000004
015F:004B5153  41                  INC       ECX
015F:004B5154  01CE                ADD       ESI,ECX
015F:004B5156  E8B5FDFFFF          CALL      004B4F10                <-- cherche les apis
015F:004B515B  AB                  STOSD
015F:004B515C  EBDC                JMP       004B513A                <-- retourne au début
015F:004B515E  61                  POPAD

Donc on se trouve en 4b513a et rien n'a encore été fait. Et bien regardons comment est le début de la section .rdata a ce moment là :

0030:00429000 72 B3 02 00 FC B2 02 00-0A B3 02 00 1E B3 02 00  r...............
0030:00429010 2E B3 02 00 40 B3 02 00-52 B3 02 00 62 B3 02 00  ....@...R...b...
0030:00429020 80 B3 02 00 00 00 00 00-2C B4 02 00 11 00 00 80  ........,.......
0030:00429030 06 00 00 80 3E B4 02 00-56 B4 02 00 6A B4 02 00  ....>...V...j...
0030:00429040 00 00 00 00 12 B2 02 00-44 B2 02 00 54 B2 02 00  ........D...T...
0030:00429050 38 B2 02 00 7A B2 02 00-86 B2 02 00 6A B2 02 00  8...z.......j...
0030:00429060 9E B2 02 00 AC B2 02 00-90 B2 02 00 22 B2 02 00  ............"...
0030:00429070 00 00 00 00 58 AB 02 00-66 AB 02 00 76 AB 02 00  ....X...f...v...
0030:00429080 4C AB 02 00 3E AB 02 00-88 AB 02 00 A8 AB 02 00  L...>...........
0030:00429090 B8 AB 02 00 C8 AB 02 00-DA AB 02 00 98 AB 02 00  ................
0030:004290A0 F6 AB 02 00 02 AC 02 00-EA AB 02 00 24 AC 02 00  ............$...
0030:004290B0 3E AC 02 00 4A AC 02 00-5E AC 02 00 72 AC 02 00  >...J...^...r...

Et oui on trouve des références du style 2b372, or si on ajoute l'image base on a 42b372 ... est ce que ceci ne ressemblerait pas à une import address table (lien vers les noms des fonctions en gros)? et bien oui, asprotect n'a pas détrui l'iat elle est comme neuve. Regardons un peu plus loin :

0030:00429300 E2 AF 02 00 CE AF 02 00-C2 AF 02 00 B4 AF 02 00  ................
0030:00429310 A0 AF 02 00 92 AF 02 00-84 AF 02 00 76 AF 02 00  ............v...
0030:00429320 60 AF 02 00 4A AF 02 00-36 AF 02 00 26 AF 02 00  `...J...6...&...
0030:00429330 12 AE 02 00 04 AE 02 00-8C B0 02 00 A6 B1 02 00  ................
0030:00429340 00 00 00 00 D2 B3 02 00-E4 B3 02 00 FA B3 02 00  ................
0030:00429350 00 00 00 00 14 00 00 80-03 00 00 80 13 00 00 80  ................
0030:00429360 10 00 00 80 02 00 00 80-12 00 00 80 16 00 00 80  ................
0030:00429370 06 00 00 80 74 00 00 80-73 00 00 80 33 00 00 80  ....t...s...3...
0030:00429380 0A 00 00 80 11 00 00 80-04 00 00 80 17 00 00 80  ................
0030:00429390 34 00 00 80 00 00 00 00-C6 B2 02 00 DA B2 02 00  4...............
0030:004293A0 00 00 00 00 00 00 00 00-53 6F 66 74 77 61 72 65  ........Software
0030:004293B0 5C 4D 69 63 72 6F 73 6F-66 74 5C 57 41 42 5C 44  \Microsoft\WAB\D

Pourquoi j'ai mis 14 00 00 80 en plus gros ? et bien simplement parceque là aussi c'est l'iat mais ce n'est pas un lien vers le nom de la fonction -2, c'est l'ordinal de la fonction utilisé. Bon maintenant allons voir la suite : en 429000 on a 2b372, donc normallement en 42b372 on devrait avoir l'import table (celle avec les noms et l'ordinal de chaque fonctions) :

0030:0042B2F0 00 00 00 00 00 00 00 00-00 00 00 00 5B 01 00 00  ............[...
0030:0042B300 00 00 00 00 00 00 00 00-00 00 7B 01 00 00 00 00  ..........{.....
0030:0042B310 00 00 00 00 00 00 00 00-00 00 00 00 00 00 72 01  ..............r.
0030:0042B320 00 00 00 00 00 00 00 00-00 00 00 00 00 00 86 01  ................
0030:0042B330 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0030:0042B340 5F 01 00 00 00 00 00 00-00 00 00 00 00 00 00 00  _...............
0030:0042B350 00 00 67 01 00 00 00 00-00 00 00 00 00 00 00 00  ..g.............
0030:0042B360 00 00 62 01 00 00 00 00-00 00 00 00 00 00 00 00  ..b.............
0030:0042B370 00 00 71 01 00 00 00 00-00 00 00 00 00 00 00 00  ..q.............
0030:0042B380 5E 01 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ^...............
0030:0042B390 00 00 00 00 00 00 00 00-00 00 00 00 00 00 72 00  ..............r.
0030:0042B3A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

Et là il n'y a pas de nom de fonction :(. Mais en 42b372 on a pourtant 7101 puis des 00 00. Et bien le 7101 c'est l'ordinal de la fonction et juste après on devrait avoir le nom de la fonction. Car l'it est fait comme cela : un word pour l'ordinal de la fonction et juste après le nom de la fonction. Donc en fait dans l'iat les références pointe vers le nom de la fonction-2.
C'est interressant tout cela on a l'iat correct et l'it (supposé) contient des espaces vides avec des words suposés être l'ordinal de la fonction. Il faut donc le vérifier. On va faire un premier passage dans la boucle jusqu'au call inclu. Là si on regarde en 6afc3b on a la fonction CreateFileA et en edi 429074. Donc on va voir en 429074 et on a 58 AB 02 00 , donc si on ajoute l'image base (400000 pour amv) et bien on obtient 42ab58. Allons voir en 42ab58 :

0042AB58 3400 0000 0000 0000 0000 0000 0000 1A01        4...............

Et bien en 42AB58 on a 3400 (lordinal de createfilea) et juste la place de mettre CreateFileA (avec un 0 caractère de fin) avant d'arriver sur l'ordinal suivant. Donc c'est bien cela : c'est l'it sans les noms.
Donc l'idée est de faire un call fixer qui va se charger de remettre les noms à leurs places. Et oui comme edi pointe vers ce qu'il y a en 429xxx, il suffit de récupérer ce qu'il y a et de rajouter l'image base comme cela on sera au début de l'endroit où doit être le nom de la fonction-2. Pour ce qui est du cas des fonctions appelés par ordinal il n'y a rien à faire car l'ordinal est déjà dans l'iat. Ensuite on dumpera cette partie que l'on remettre dans le dump.

Bon maintenant il faut le faire :). Donc on recommence tout et on est de nouveau au début de la boucle en 4b513a. Là on va jusqu'au call qu'on dévit de nouveau :

015F:004B5147  0FB64E01            MOVZX     ECX,BYTE PTR [ESI+01]
015F:004B514B  41                  INC       ECX
015F:004B514C  EB05                JMP       004B5153
015F:004B514E  B904000000          MOV       ECX,00000004
015F:004B5153  41                  INC       ECX
015F:004B5154  01CE                ADD       ESI,ECX
015F:004B5156  E9A5130000          JMP       004B6500       <-- on dévit
015F:004B515B  AB                  STOSD
015F:004B515C  EBDC                JMP       004B513A
015F:004B515E  61                  POPAD

Maintenant on peut mettre en 4b6500 notre fixer  :

015F:004B6500  E80BEAFFFF          CALL      004B4F10                     <-- le call que l'on a détruit
015F:004B6505  60                  PUSHAD                                 <-- on sauve les registres
015F:004B6506  833D6BFC6A0000      CMP       DWORD PTR [006AFC6B],00      <-- est que le nom est là si non on saute
015F:004B650D  741C                JZ        004B652B                     <-- et on va vers crypté/ordinal
015F:004B650F  686BFC6A00          PUSH      006AFC6B                     <-- on met le nom
015F:004B6514  8B0F                MOV       ECX,[EDI]                    <-- on met la VA pointé par edi dans .rdata
015F:004B6516  81C102004000        ADD       ECX,00400002                 <-- on rajoute l'imagebase + 2 pour passer
                                                                              l'ordinal
015F:004B651C  51                  PUSH      ECX                          <-- on met l'adresse de destination
015F:004B651D  E8DA0DACBF          CALL      KERNEL32!lstrcpy             <-- et on copie
015F:004B6522  61                  POPAD                                  <-- on restaure les registres
015F:004B6523  83C704              ADD       EDI,04                       <-- on passe au prochain traitement
015F:004B6526  E90FECFFFF          JMP       004B513A                     <-- et on boucle
015F:004B652B  3D00000040          CMP       EAX,40000000                 <-- eax contient l'adresse d'une api
015F:004B6530  7DF0                JGE       004B6522                     <-- oui alors c'est par ordinal et on
                                                                              passe au suivant car l'ordinal est déjà
                                                                              dans l'iat
015F:004B6532  83F900              CMP       ECX,00                       <-- ecx = 0 si non alors ordinal et on
015F:004B6535  75EB                JNZ       004B6522                     <-- passe au suivant
015F:004B6537  FF7001              PUSH      DWORD PTR [EAX+01]           <-- sinon c crypté et on passe le paramètre
015F:004B653A  E8F5E8FFFF          CALL      004B4E34                     <-- à la fonction de décryption
015F:004B653F  6864FC6A00          PUSH      006AFC64                     <-- on recherche l'adresse du nom que l'on
                                                                              met sur la pile
015F:004B6544  EBCE                JMP       004B6514                                       <-- et on va l'écrire dans l'it
 

Voilà cette proc est bien commentée je pense. Toutefois il faut également mettre 3 nops en 4b4e34+95 (la proc de décryption) et faire attention à l'adresse du nom en retour de cette procédure (voir partie précédente).
Avant de laisser tournée la boucle il faut mettre un bpm 4b515e x pour s'arrêter après cette boucle. Une fois qu'elle est finie il faut dumper toute la partie qui a changé : pagein d 429000 2c00 c:\import.dat .

Maintenant on prend le dump du prog (obtenu en allant à l'endroit où il passe la main à celui décompressé et en ayant mis jmp eip, puis en le dumpant avec procdump ou procinfos). Si jamais vous avez dumper le prog avec icedump pensé à le reconstruire avec perebuilder (avec l'option fix raw offset) ou alors vous mettez directement le raw offset de chaque section égal à la virtual address .
Maintenant une chose très pratique est que la virtual adress est égal au raw ofset, comme cela on se repère facilement. Il va donc faloir coller l'import que l'on a dumpé dans le dump en 29000. Une fois cela fait le dump n'est pas encore fonctionnel : en effet on a bien l'it (les noms des fonctions avec l'ordinal), l'iat (liens vers le noms des fonctions) mais il manque encore l'import descriptor qui dit quelles dlls sont utilisées.
Et bien il nous reste encore à le reconstruire.

Pour ce faire un petit coup d'oeil sur le tut de TeeJi sur comment rajouter une dll dans l'iat et on comprend tout de suite mieux de quoi ca parle :). Bon on va commencer par le début : comment se présente d'import descriptor :

IMAGE_IMPORT_DESCRIPTOR struct
      OriginalFirstThunk   dd 0  ;RVA to original unbound IAT
      TimeDateStamp        dd 0  ;not used here
      ForwarderChain       dd 0  ;not used here
      Name                 dd 0  ;RVA to DLL name sring
      FirstThunk           dd 0  ;RVA to IAT array
IMAGE_IMPORT_DESCRIPTOR ends

Donc pour une dll il y a 4 dword : le premier correspond au début de la zone de l'iat dorrespondante, le deuxième on s'en fou, le troisième ne sert pas ici donc on met FFFFFFFF, le quatrième pointe vers le nom de la dll, et le cinquième vers un tableau d'adresse (comme ici il n'y en a pas on le mettra égal à l'OriginalFirstThunk).
Bon, commencons : tout d'abord allons au début de la section .rdata en 429000 :

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00029000   72 B3 02 00 FC B2 02 00  0A B3 02 00 1E B3 02 00   r³..ü²...³...³..
00029010   2E B3 02 00 40 B3 02 00  52 B3 02 00 62 B3 02 00   .³..@³..R³..b³..
00029020   80 B3 02 00 00 00 00 00  2C B4 02 00 11 00 00 80   €³......,´.....€
00029030   06 00 00 80 3E B4 02 00  56 B4 02 00 6A B4 02 00   ...€>´..V´..j´..
00029040   00 00 00 00 12 B2 02 00  44 B2 02 00 54 B2 02 00   .....²..D²..T²..
00029050   38 B2 02 00 7A B2 02 00  86 B2 02 00 6A B2 02 00   8²..z²..†²..j²..
00029060   9E B2 02 00 AC B2 02 00  90 B2 02 00 22 B2 02 00   ž²..¬²..².."²..

Voilà comment on repaire les dlls utilisés: au début de la section en 29000 et bien on a des liens vers les noms-2. J'en ai sélectionné 17 car juste après il y a 00 00 00 00. Ceci permet de dire que le prog fait appel à 17 fonctions de cette dlls. On sait déjà que L'originalFirstThunk est 29000. Pour le nom  de la dll on pourrait le mettre n'importe où mais on peut faire mieux ici : Le premier liens est 2b372, on y va :

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

0002B350   41 00 67 01 52 65 67 45  6E 75 6D 4B 65 79 45 78   A.g.RegEnumKeyEx
0002B360   41 00 62 01 52 65 67 44  65 6C 65 74 65 4B 65 79   A.b.RegDeleteKey
0002B370   41 00 71 01 52 65 67 4F  70 65 6E 4B 65 79 41 00   A.q.RegOpenKeyA.
0002B380   5E 01 52 65 67 43 72 65  61 74 65 4B 65 79 41 00   ^.RegCreateKeyA.
0002B390   00 00 00 00 00 00 00 00  00 00 00 00 00 00 72 00   ..............r.
0002B3A0   53 68 65 6C 6C 45 78 65  63 75 74 65 41 00 00 00   ShellExecuteA...

En 2b390 on trouve plein de 00, et au dessus les noms des fonctions de la dlls, pointés par la partie de l'iat sélectionné. Or c'est fonctions font partis de la dll advapi32.dll. Donc en 2b390 on met advapi32.dll et le nom de la dll est en 2b390. Si vous ne vous y retrouvé pas au niveau des noms des dlls utilisé le prog import list il vous donnera dans l'ordre les fonctions avec leur dll associée. Maintenant on passe en 29020 et on recommence avec la dll suivante . Pour ce qui est des Ordinals il se trouve que dans ce prog c'est pour la dll wsock32.dll (vous pouvez le repérer soit avec le prog russe, soit au niveau de la boucle que l'on a fait et en mettant un point d'arrêt au niveau du traitement de l'ordinal et vous notez la/les dll(s) correspondantes). Pour écrire l'import descriptor on choisi une place libre, voici le mien reconstruit :

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

0002A800   00 90 02 00 00 00 00 00  FF FF FF FF 90 B3 02 00   .......ÿÿÿÿ³..
0002A810   00 90 02 00 28 90 02 00  00 00 00 00 FF FF FF FF   ...(......ÿÿÿÿ
0002A820   7B B4 02 00 28 90 02 00  44 90 02 00 00 00 00 00   {´..(..D......
0002A830   FF FF FF FF BC B2 02 00  44 90 02 00 74 90 02 00   ÿÿÿÿ¼²..D..t..
0002A840   00 00 00 00 FF FF FF FF  2F AD 02 00 74 90 02 00   ....ÿÿÿÿ/­..t..
0002A850   04 92 02 00 00 00 00 00  FF FF FF FF AE B3 02 00   .’......ÿÿÿÿ®³..
0002A860   04 92 02 00 0C 92 02 00  00 00 00 00 FF FF FF FF   .’...’......ÿÿÿÿ
0002A870   05 B2 02 00 0C 92 02 00  44 93 02 00 00 00 00 00   .²...’..D“......
0002A880   FF FF FF FF 14 B4 02 00  44 93 02 00 54 93 02 00   ÿÿÿÿ.´..D“..T“..
0002A890   00 00 00 00 FF FF FF FF  D0 A8 02 00 54 93 02 00   ....ÿÿÿÿШ..T“..
0002A8A0   98 93 02 00 00 00 00 00  FF FF FF FF ED B2 02 00   ˜“......ÿÿÿÿí²..
0002A8B0   98 93 02 00 00 00 00 00  00 00 00 00 00 00 00 00   ˜“..............
0002A8C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
0002A8D0   57 53 4F 43 4B 33 32 2E  44 4C 4C 00 00 00 00 00   WSOCK32.DLL.....                           .

Voilà, j'ai mis en evidente les différentes parties, ici le prog utilise 8 dlls. Maintenant pour que le dump soit opérationnel, il faut encore changé l'import adress RVA (avec peeditor) en 2a800, et également mettre l'eip original, celui trouvé au moment où le prog passe la main à celui décompressé (ici 421bfc).

Bon mais là amv ne marchera pas, pourquoi ? et bien si vous vous souvenez dans une partie précédent je vous ai dit qu'il mettait une adresse d'asprotect dans la table d'import qui servira pour une décryption si on a la clef. Et bien en fait il fait appel à GetProcAddress sauf pour un passage où il met cette valeur. Donc notre fixer a mis comme valeur pour ca une référence à GetProcAddress, et si le dump ne marche pas c'est que pour le passage pour la décryption et bien il fait appel à getprocaddress alors qu'il devrait mettre une valeur. Regardons le message d'erreur qui apparait au lancement du dump :

Crypt API not found. Please re-install

Donc on désassemble et on recherche ca et on arrive là :

00417620 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
00417620
00417620
00417620 sub_417620      proc near               ; CODE XREF: _WinMain@16+EBp
00417620                 push    4
00417622                 push    0FFFFFFFFh
00417624                 call    ds:off_4290C8
0041762A                 test    eax, eax
0041762C                 mov     ds:dword_433758, eax
00417631                 jnz     short loc_417649           <-- on force
00417633                 push    10h
00417635                 push    offset aAdvancedMailLi ; "Advanced Mail List Verify"     <-- pas bon
0041763A                 push    offset aCryptApiNotFou ; "Crypt API not found. Please re-install "...
0041763F                 push    eax
00417640                 call    ds:dword_4292E8
00417646                 xor     eax, eax
00417648                 retn
00417649 ; ---------------------------------------------------------------------------
00417649
00417649 loc_417649:                             ; CODE XREF: sub_417620+11j
00417649                 mov     eax, 1
0041764E                 retn

Pour eviter ce message d'erreur et la fin du prog il suffit de forcer le saut en 417631 et le tours est joué. Maintenant le dump est complètement fonctionnel et comme neuf :) . Biensur il y a encore une partie crypté nécessitant la clef ... mais bon on a comme obtenu un dump d'amv avec une véritable table d'import.
Bon si je vous est décrit le principe ce la méthode à Tsehp c'est parce que c'est grace à cela que j'ai pu élaborer celle là, et oui il fallait savoir où était le nom des fonctions ....
 
 
 
 
V_4ème méthode: pleditor

Ce qui serait intérressant c'est que la méthode précédente marche également sur pleditor (étant donné qu'il est protégé avec une version plus récente d'asprotect). Et bien malheuresement elle ne marche pas car l'iat et l'it n'éxiste plus, il n'y a que des 00. Cependant est il impossible pour autant d'arriver au même objectif que précédement? et bien non mais il va falloir arriver à mettre une méthode au point qui va créer une iat, une it et pourquoi pas en même temps l'import descriptor. Mais comment peut on y arriver? et bien c'est simple on ne va plus maintenant écrire un call fixer mais un import table rebuilder. Comment est-ce possible ? et bien tout simplement parce que asprotect se trahi lui même... Il est obligé de mettre c'est liens vers les fonctions (qu'il y ai du cryptage ou juste un jmp ceci n'a pas d'importance) au même endroit qu'il devait se trouvé originellement. En effet suposons qu'en 429000 on est un lien vers l'api CreateFileA, et bien le programme appelera ce qu'il y a en 429000 : call [429000] et comme ceci fait partie de l'import table, windows se chargera de remplacer ca par l'adresse de CreateFileA. Donc si Asprotect veut reconstruire une import table, même une crypté ou n'importe quoi d'autre, il est obligé que ce qui liera le prog à CreateFileA se trouve en 429000. Et bien c'est comme cela que nous pourrons arriver à reconstruire une iat, it, et l'import descriptor.
Je tiens à précisez que je n'aurais jamais pu mettre cette méthode au point si Tsehp n'avait pas expliqué comment récupérer le noms des fonctions.

Bon maintenant mettons les choses en pratique. On lance pleditor, on trace, on enlève l'anti-debug et on arrive à cette fameuse boucle (voir toutes les parties précédentes pour y arriver) :

015F:00555392  AC                  LODSB
015F:00555393  08C0                OR        AL,AL
015F:00555395  74E4                JZ        0055537B
015F:00555397  4E                  DEC       ESI
015F:00555398  56                  PUSH      ESI
015F:00555399  53                  PUSH      EBX
015F:0055539A  80F802              CMP       AL,02
015F:0055539D  7407                JZ        005553A6
015F:0055539F  0FB64E01            MOVZX     ECX,BYTE PTR [ESI+01]
015F:005553A3  41                  INC       ECX
015F:005553A4  EB05                JMP       005553AB
015F:005553A6  B904000000          MOV       ECX,00000004
015F:005553AB  41                  INC       ECX
015F:005553AC  01CE                ADD       ESI,ECX
015F:005553AE  E8B5FDFFFF          CALL      00555168             <-- on redévi le call en jmp 556700
015F:005553B3  AB                  STOSD
015F:005553B4  EBDC                JMP       00555392
015F:005553B6  61                  POPAD
015F:005553B7  837D0800            CMP       DWORD PTR [EBP+08],00
015F:005553BB  7509                JNZ       005553C6
 

Bon comme précédement on redévi le call vers un endroit libre, pour moi en 556700. Maintenant je vais essayer de vous expliquer le principe de de cette import rebuilder. Tout d'abord supposons que asprotect désire mettre son lien en 4b8000 et bien on prendra une place pour mettre notre it (les noms) en 4b8950 (par exemple) et on écrit le nom en 4b8950+2 (pour gérer l'ordinal mais qui ici n'y est pas) et on met en 4b8000 un lien vers 4b8950-image base (ici b8950 car l'image base est de 400000). Ensuite pour le cas où la fonction est appelé par ordinal on mettra directement l'ordinal en 4b8000 (enfin l'adresse à vers laquelle aspr pointe), on le met directement dans l'iat, mais pour que windows le reconnaisse il faudra ajouter 80000000 pour qu'il sache que c'est un ordinal et non l'adresse du nom de la fonction-2. Pour ce qui est de l'import descriptor on le reconstruira comme ceci ebx, contient une référence vers le nom de la dll en cours, il suffira de comparé ebx à chaque passage à ca valeur précendente pour savoir si on est toujours dans la même partie de l'import descriptor. Si non alors on reconstruit une structure comme ceci:

IMAGE_IMPORT_DESCRIPTOR struct
      OriginalFirstThunk   dd 0  ;début de la zone où l'on va écrire les noms pour cette structure
      TimeDateStamp        dd 0  ;on met 00000000
      ForwarderChain       dd 0  ;on met FFFFFFFF
      Name                 dd 0  ;on écrit le nom de la dll avec le nom des fonctions et on met un lien vers ce nom
      FirstThunk           dd 0  ;on le met égal à OriginalFirstThunk
IMAGE_IMPORT_DESCRIPTOR ends

Je sais tout ceci n'est expliqué que très grossièrement mais je ne sais pas trop comment le dire ...  Bon maintenant on peut mettre en 556700 l'import rebuilder (il n'est en rien optimisé mais il fonctionne bien :) ) :

015F:00556700  E863EAFFFF          CALL      00555168                     <-- on restaure le call
015F:00556705  60                  PUSHAD                                 <-- on sauve les registres
015F:00556706  391DFC665500        CMP       [005566FC],EBX               <-- est-on tjs dans la même structure de
                                                                              l'import descriptor
015F:0055670C  7470                JZ        0055677E                     <-- oui on passe à la suite
015F:0055670E  60                  PUSHAD                                 <-- non en en créér une nouvelle
015F:0055670F  891DFC665500        MOV       [005566FC],EBX               <-- on met ebx (pointeur vers le nom de la
                                                                              dll) dans une variable
015F:00556715  8B15F4665500        MOV       EDX,[005566F4]               <-- on met l'adresse courante de l'iad
                                                                              dans edx
015F:0055671B  893A                MOV       [EDX],EDI                    <-- et on y met le contenu de edi (c'est à
                                                                              dire le début de l'iat correspondant
015F:0055671D  812A00004000        SUB       DWORD PTR [EDX],00400000     <-- on enlève l'image base
015F:00556723  8305F466550008      ADD       DWORD PTR [005566F4],08      <-- on actualise le pointeur vers l'iad
015F:0055672A  8B15F4665500        MOV       EDX,[005566F4]               <-- et on le met dans edx
015F:00556730  C702FFFFFFFF        MOV       DWORD PTR [EDX],FFFFFFFF     <-- pour mettre ff.. dans la structure
015F:00556736  43                  INC       EBX                          <-- on fait pointer ebx sur la dll
015F:00556737  53                  PUSH      EBX                          <-- on met sur la pile
015F:00556738  FF35F8665500        PUSH      DWORD PTR [005566F8]         <-- ainsi que sa destination (adresse
                                                                              courante de l'it)
015F:0055673E  E8B90BA2BF          CALL      KERNEL32!lstrcpy             <-- et on copi
015F:00556743  FF35F8665500        PUSH      DWORD PTR [005566F8]         <-- on calcule la longueur du nom
015F:00556749  E85F0CA2BF          CALL      KERNEL32!lstrlen             <-- dela dll
015F:0055674E  40                  INC       EAX                          <-- on incrémente pour le 0 de fin
015F:0055674F  8B15F8665500        MOV       EDX,[005566F8]               <-- on met l'adresse courante de l'it (contient
                                                                              le nom de la dll)
015F:00556755  81EA00004000        SUB       EDX,00400000                 <-- on enlève l'image base
015F:0055675B  8305F466550004      ADD       DWORD PTR [005566F4],04      <-- on actualise l'iad
015F:00556762  8B0DF4665500        MOV       ECX,[005566F4]               <-- et on met son adresse dans ecx
015F:00556768  8911                MOV       [ECX],EDX                    <-- pour y mettre le pointeur vers le nom de la
                                                                              dll
015F:0055676A  8B59F4              MOV       EBX,[ECX-0C]                 <-- on récupère l'OriginalFirstThunk
015F:0055676D  895904              MOV       [ECX+04],EBX                 <-- que l'on met dans le FirstThunk
015F:00556770  8305F466550008      ADD       DWORD PTR [005566F4],08      <-- on actualise l'iad
015F:00556777  0105F8665500        ADD       [005566F8],EAX               <-- ainsi que l'it
015F:0055677D  61                  POPAD                                  <-- on a finit pour l'iad on passe à la
                                                                              suite
015F:0055677E  833D6BFC740000      CMP       DWORD PTR [0074FC6B],00      <-- on a un nom de focntion
015F:00556785  743C                JZ        005567C3                     <-- non alors on va vers crypté/ordinal
015F:00556787  8B15F8665500        MOV       EDX,[005566F8]               <-- oui on récupère l'adresse courante de
                                                                              l'it
015F:0055678D  81EA00004000        SUB       EDX,00400000                 <-- on enlève l'image base
015F:00556793  8917                MOV       [EDI],EDX                    <-- et on met un lien dans l'iat
015F:00556795  686BFC7400          PUSH      0074FC6B                     <-- on met l'adresse du nom de fonction
015F:0055679A  8B15F8665500        MOV       EDX,[005566F8]               <-- on met l'adresse courante de l'it
015F:005567A0  83C202              ADD       EDX,02                       <-- on ajoute deux pour l'ordinal
015F:005567A3  52                  PUSH      EDX                          <-- on la met sur la pile
015F:005567A4  E8530BA2BF          CALL      KERNEL32!lstrcpy             <-- et on copie la procname
015F:005567A9  52                  PUSH      EDX                          <-- on met le nom de la fonction
015F:005567AA  E8FE0BA2BF          CALL      KERNEL32!lstrlen             <-- on calcule sa taille
015F:005567AF  0503000000          ADD       EAX,00000003                 <-- on ajoute trois pour le zero de fin et
                                                                              l'ordinal
015F:005567B4  0105F8665500        ADD       [005566F8],EAX               <-- on actualise l'it
015F:005567BA  61                  POPAD                                  <-- on récupère les registres
015F:005567BB  83C704              ADD       EDI,04                       <-- on passe au suivant
015F:005567BE  E9CFEBFFFF          JMP       00555392                     <-- et on boucle
015F:005567C3  3D00000040          CMP       EAX,40000000                 <-- eax a l'adresse d'une api
015F:005567C8  7D22                JGE       005567EC                     <-- oui alors ordinal
015F:005567CA  83F900              CMP       ECX,00                       <-- ecx = 0
015F:005567CD  751D                JNZ       005567EC                     <-- oui alors ordinal
015F:005567CF  FF7001              PUSH      DWORD PTR [EAX+01]           <-- on passe le paramaètre pour la fonction
015F:005567D2  E8B5E8FFFF          CALL      0055508C                     <-- de décryption
015F:005567D7  8B15F8665500        MOV       EDX,[005566F8]               <-- on met l'adresse courante de l'it dans
                                                                              edx
015F:005567DD  81EA00004000        SUB       EDX,00400000                 <-- on enlève l'image base
015F:005567E3  8917                MOV       [EDI],EDX                    <-- et on met le lien dans l'iat
015F:005567E5  6864FC7400          PUSH      0074FC64                     <-- on met l'adresse du nom de la fonction
015F:005567EA  EBAE                JMP       0055679A                     <-- et on retourne la copié dans l'it
015F:005567EC  83EE04              SUB       ESI,04                       <-- ordinal alors on le récupère
015f:005567EF  8B16                MOV       EDX,[ESI]                    <-- dans edx
015f:005567F1  81C200000080        ADD       EDX, 80000000                <-- on prépare l'ordinal pour windows
015F:005667F7  8917                MOV       [EDI],EDX                    <-- on le met dans l'iat
015F:005667F9  61                  POPAD                                  <-- on récupère les registres
015F:005567F2  83C704              ADD       EDI,04                       <-- on passe au suivant
015F:005567F5  E998EBFFFF          JMP       00555392                     <-- on boucle
015F:005567FA  0000                ADD       [EAX],AL
015F:005567FC  0000                ADD       [EAX],AL
 

Voilà , je pense avoir commenté au maximum, mais de toute facon c'est assez dur à expliquer. Avant d'éxécuter la boucle il faudra mettre en 5566f4 le début de l'endroit où vous voulez mettre l'iad ( j'ai mis 4b8950 car quand il installe la fausse table d'import il met des liens jusque là, donc l'iat s'arrêtera là). Ensuite en 5566f8 on met l'endroit où vous voulez mettre l'it (j'ai mis 5566fc en pensant que 200h octets pour l'iad était sufisant. Il faut également mettre les trois nops dans le call de décryptages (voir avant), mais pour le repérer il faut étendre la recherche : s 0 l ffffffff 55 8b ec 81 c4 f8 fe ff ff 53 56 8b 5d 08 8b 03 89 45 f8 8d.
Maintenant on laisse tranquilement la boucle s'éxécuter et le rebuilder nous reconstruire l'import table. Donc on aura pris soin de mettre un point d'arrêt à la sortie de la boucle au niveau du popad.
Bon maintenant on dump tout ca : pagein d 4b8000 3000 c:\import.dat.  On a pris soin de faire le dump auparavant du programme et on colle notre nouvelle table d'import dans le dump (voir précédement). Attention ici je n'avais pas une VA égal au raw offset donc faites attention pour vous repérer dans le programme. Bon une fois que cela est fait il reste encore a changé l'eip (bf27c) et l'import table rva (b8950) qui correspond au début de l'import descriptor.

Maintenant on lance le programme et ..... un beau message d'erreur : Asprotect API not found! Running in unregistered mode. Hehe, le même problème que sur amv, une partie du programme est crypté par clef. Bon pour enlever cette écran un petit bpx messageboxa et on force le saut qui la précède .
Enfin voilà, maintenant il ne reste plus qu'à cracker le prog. Maintenant on a un dump avec une vrai table d'import. Bon j'avoue que cette import rebuilder n'est pas spécialement optimisé mais bon ... De plus j'ai essayé de vous en expliquez le principe mais ce n'est pas spécialement facile ...
 
 
 
 
 
VI_Conclusion

Voilà, cet essai sur le manual unpacking d'asprotect 1.0+ est fini. Je vous ai présenté différente manière d'y parvenir, mais à mon avis l'import rebuilder final est le plus intérressant car il reconstruit véritablement une table d'import.
Bon voici quelques lectures supplèmentaires si vous en avez le courage :) :

 http://assembly.citeweb.net/zip/IAT.htm              Texte très interressant sur le rajout d'une dll dans l'iat
 http://christal.citeweb.net/tutor/cdilla.htm             Etude de cdilla por mieux comprendre le call fixer
 http://tamambolo.free.fr                                      Etude de cdilla por mieux comprendre le call fixer
 http://www.66.98.132.48/tsehp_asprotect105.htm   Le texte de Tsehp sur le dump d'asprotect (dernière version)
 http://tsehp.cjb.net/                                             Pour les textes sur asprotect et cdilla
 http://assembly.citeweb.net                                 Pour les textes sur le patching d'asprotect ...

Je tenais à remercier plusieurs personnes : Christal pour m'avoir relancé dans cette protection, TeeJi pour avoir accepté d'étudier cette protection et pour les discussions dessus sur irc, et +Tsehp pour avoir pris le temps de me répondre et surtout pour avoir trouvé et mis au point (avec un très bon tut) une première méthode de dump qui m'a finalement permis d'aboutir à l'import table rebuilder.
Un special greetz à Alexey Solodovnikov qui nous prépare surement de bien belle surprise pour l'avenir ...
 

Amicalement,

LuTiN NoIR
 

(c) 2000 . LuTiN NoIR - city_of_bitch@caramail.com