Protection
   ASPack 2.001  

Ready Made Protection

  Outils
   SoftIce    
  Cible
   ASPack2.001  

By Christal

Comment réaliser un Dump exécutable d'ASPack 2.001

Avant Propos

Toujours à la recherche d'informations sur la ready made rencontrée pour de nombreux programmes ces derniers temps (et dont l'une des sections s'appelle souvent .aspr), je suis allé faire un petit tour sur le site d'ASPack. Par " réflexe " j'en ai downloadé la dernière version de ce crypteur, la 2.001, et j'ai commencé à regarder comment cette protection était foutue :

Dans le menu Help, j'ai trouvé ceci :

How can I protect my application against professional hackers? Do you plan add some protection's options like encryption, anti-debugger tricks, and so on?
Yes, I do. I finish writing a beta version of ASProtect (a full protector with encryption) for shareware authors, with powerful run-time encryption, anti-debugging, powerful serial number's generation, trial features support and so on. More details are available on request.

ASProtect et .aspr sont trop proche pour ne pas y voir une relation certaine. Pour en avoir la confirmation, j'ai commencé à jouer avec le crypteur :


De ASPack 2.001 à ASProtect : les similitudes

Les sections :

ASPack 2.001
.rsrc  00017000     0004D000    00005C00    0001D800    C0000040
.ass   00013000     00064000    00012600    00023400    C0000040
.rsrc  00001000     00077000    00000000    00035A00    C0000040

d'une Ready Made à l'autre on retrouve le doublon .rsrc

Les Entry point :

ASProtect
:0043F001  60                  PUSHAD                > Entry Point
:0043F002  E801000000          CALL      0043F008
:0043F007  90                  NOP
:0043F008  5D                  POP       EBP
:0043F009  81EDE3E54400        SUB       EBP,0044E5E3

ASPack 2.001
:00464001  60                  PUSHAD
:00464002  E801000000          CALL    00464008
:00464007  90                  NOP
:00464008  5D                  POP     EBP
:00464009  81ED17FE4400        SUB     EBP,0044FE17

Routine de Détection :
Pour ASPack, seul des modifications au niveau du PE Header (attributs des sections par exemple) sont détectées. Dans ASProtect la détection de SOFTICE (un MeltIce classique) est rajoutée, mais dans les deux cas le traitement de la détection est faite dans ce call :

ASProtect :
:006CFFF0  55                  PUSH      EBP       > à remplacer par un C3
:006CFFF1  8BEC                MOV       EBP,ESP
:006CFFF3  83C4F8              ADD       ESP,-08
:006CFFF6  8955F8              MOV       [EBP-08],EDX

ASPack :
:00C109A0  55                  PUSH    EBP         > mettre un ret
:00C109A1  8BEC                MOV     EBP,ESP
:00C109A3  83C4F8              ADD     ESP,-08
:00C109A6  8955F8              MOV     [EBP-08],EDX

Vous admettrez que la similitude est troublante !
Il en sera de même pour l'ensemble des deux protections.
Et dire qu'Alexey Solodovnik va vendre ces deux produits en prétendant qu'ils sont différents...

Cette routine est appelée par un call que vous trouverez ci dessous :

ASPack
:00C1107A  8B45E8              MOV     EAX,[EBP-18]
:00C1107D  E81623FFFF          CALL    00C03398
:00C11082  8B5303              MOV     EDX,[EBX+03]
:00C11085  E816F9FFFF          CALL    00C109A0        > ici
:00C1108A  8B45F8              MOV     EAX,[EBP-08]
:00C1108D  E89218FFFF          CALL    00C02924

Dans les deux versions, la table d'import, comme la démontré SV, est écrabouillée pour empécher un dump fonctionnel.

Après la modification de la routine Modifications_Détectées, en posant un bpx GetProcAddress, vous aurez un break:

KERNEL32!GetProcAddress
:BFF76DA8  57                  PUSH    EDI
:BFF76DA9  6A22                PUSH    22
:BFF76DAB  2BD2                SUB     EDX,EDX
:BFF76DAD  68671DFABF          PUSH    BFFA1D67
:BFF76DB2  64FF32              PUSH    DWORD PTR FS:[EDX]
:BFF76DB5  648922              MOV     FS:[EDX],ESP
:BFF76DB8  8B7C2418            MOV     EDI,[ESP+18] > d edi
:BFF76DBC  81FF00000100        CMP     EDI,00010000
:BFF76DC2  7207                JB      BFF76DCB
:BFF76DC4  2BC0                SUB     EAX,EAX
:BFF76DC6  8D48FF              LEA     ECX,[EAX-01]
:BFF76DC9  F2AE                REPNZ SCASB
:BFF76DCB  648F02              POP     DWORD PTR FS:[EDX]
:BFF76DCE  83C408              ADD     ESP,08
:BFF76DD1  5F                  POP     EDI
:BFF76DD2  E974950000          JMP     BFF8034B

Un d edi va vous donner les Datas suivants :

:004456AC 44 65 6C 65 74 65 43 72-69 74 69 63 61 6C 53 65  DeleteCriticalSe
:004456BC 63 74 69 6F 6E 00 00 00-4C 65 61 76 65 43 72 69  ction...LeaveCri
:004456CC 74 69 63 61 6C 53 65 63-74 69 6F 6E 00 00 00 00  ticalSection....
:004456DC 45 6E 74 65 72 43 72 69-74 69 63 61 6C 53 65 63  EnterCriticalSec
:004456EC 74 69 6F 6E 00 00 00 00-49 6E 69 74 69 61 6C 69  tion....Initiali
:004456FC 7A 65 43 72 69 74 69 63-61 6C 53 65 63 74 69 6F  zeCriticalSectio
:0044570C 6E 00 00 00 56 69 72 74-75 61 6C 46 72 65 65 00  n...VirtualFree.
:0044571C 00 00 56 69 72 74 75 61-6C 41 6C 6C 6F 63 00 00  ..VirtualAlloc..

Ce qui ressemblerait fort à une table d'import...
A la sortie de cette API (F12), et en traçant un peu vous arriverez aux adresses chargées de la destruction de la table d'import :

ASPack :
:00C10D60  03056466C100        ADD     EAX,[00C16664]
:00C10D66  8908                MOV     [EAX],ECX       
:00C10D68  8B45D8              MOV     EAX,[EBP-28]
:00C10D6B  8B55E8              MOV     EDX,[EBP-18]
:00C10D6E  8910                MOV     [EAX],EDX     > à noper
:00C10D70  EB08                JMP     00C10D7A
:00C10D72  8B45D8              MOV     EAX,[EBP-28]
:00C10D75  8B55F4              MOV     EDX,[EBP-0C]
:00C10D78  8910                MOV     [EAX],EDX     > à noper
:00C10D7A  83C604              ADD     ESI,04
:00C10D7D  8345D804            ADD     DWORD PTR [EBP-28],04
:00C10D81  8B45DC              MOV     EAX,[EBP-24]

ASProtect :
:00C8F4A4 03052434C900         ADD     EAX,[00C93424] 
:00C8F4AA 8908                 MOV     [EAX],ECX 
:00C8F4AC 8B45D8               MOV     EAX,[EBP-28] 
:00C8F4AF 8B55E8               MOV     EDX,[EBP-18] 
:00C8F4B2 8910                 MOV     [EAX],EDX <--------- a noper 
:00C8F4B4 EB08                 JMP     00C8F4BE 
:00C8F4B6 8B45D8               MOV     EAX,[EBP-28] 
:00C8F4B9 8B55F4               MOV     EDX,[EBP-0C] 
:00C8F4BC 8910                 MOV     [EAX],EDX <--------- a noper 
:00C8F4BE 83C604               ADD     ESI,04 
:00C8F4C1 8345D804             ADD     DWORD PTR [EBP-28],04 


En nopant les deux MOV [EAX],EDX, vous éviterez la dégradation de l'Import Table. Il ne restera plus qu'à trouver l'adresse où la protection passe le relais au programme d'origine :

:00C10EA0  E9148B1D68          JMP     68DE99B9
:00C10EA5  66C100EB            ROL     WORD PTR [EAX],EB
:00C10EA9  01EB                ADD     EBX,EBP
:00C10EAB  89041C              MOV     [EBX+ESP],EAX
:00C10EAE  EB02                JMP     00C10EB2
:00C10EB0  EB02                JMP     00C10EB4
:00C10EB2  61                  POPAD                > restauration des registres
:00C10EB3  EB01                JMP     00C10EB6     > le push eax est "caché" 
:00C10EB5  E850EB02E9          CALL    E9C3FA0A
:00C10EBA  17                  POP     SS
:00C10EBB  C3                  RET                  > et passe le relais


En remplaçant le RET par un JMP EIP, vous allez pouvoir créer votre Full DUMP (et n'oubliez pas de relever la valeur de l'OEP dans EAX !).

ATTENTION : l'import Table devant rester tel quel, il faudra sélectionner l'Option "Don't Rebuild Import" dans ProcDump.

Il ne restera qu'à modifier l'exécutable obtenu en y mettant le bon Entry Point (41C68 dans mon cas) et changer dans "Directory" l'Import Table en RVA 45000. (4456AC, valeur relevée dans EDI lors du break sur GetProAddress - l'ImageBase 400000, et en arrondissant grassement...)

Pour être un peu plus sérieux:

Il y a en fait 3 ou 4 parties différentes dans cette section d'import :
L'original thunk, le nom des dlls, le thunk et les noms des fonctions (Il se peut qu'il n'y est pas d'original thunk).
Il y a donc au début de l'import Table une partie qui fait 5 DWORDs de long pour chaque dll, et qui pointe vers les différentes autres parties. C'est le début de celle ci qu'il faut localiser !
Il y a parfois moyen d'avoir des indications dans les noms des sections :
'
.idata' est normalement une section d'import et il n'y a plus qu'à regarder le Virtual Offset ajouté à la base pour bien la repérer :

Sections lnformations :
Name         Virtual Size      Virtual Offset        Raw Size
CODE           00041000           00001000           0001B800
DATA           00002000           00042000           00000E00
BSS            00001000           00044000           00000000
.idata         00002000           00045000           00000C00
.tls           00001000           00047000           00000000
.rdata         00001000           00048000           00000200

Mais le plus facile, et le plus fiable reste encore d'utiliser l'ascenseur de la fenêtre des Datas, et aprés avoir afficher le contenu de EDI, (cette valeur correspond à la RVA de l'Import Table), vous devez voir juste au dessus de la fenêtre DATA quelque chose qui ressemble à 'ASPACK!.idata+XXXX. En revenant en arrière à + 0000, vous aurez l'adresse de début de votre Import Table.

Vous voilà avec un Dump exécutable d'ASPack 2.001. La méthode, et vous l'avez bien compris, est identique pour ASProtect, d'autant plus que la détection supplémentaire de SoftIce ne vous demandera rien de plus ...

Une dernière chose:

En testant la version décompressée, vous aurez peut être droit à des messages d'erreurs d'exécution, mais qui ne gênent pas le fonctionnement du prog (si vous lancez la version non décompressée, que vous la refermez, en relançant à nouveau la version décompressée il n'y a plus de messages d'erreur...).
J'ai vite remarqué que ce problème se produisait au moment de l'affichage (dans la fenêtre d'Aspack) du texte qui indique le nombre de jours restants (xx days). (texte affiché dans la version d'origine mais pas dans la version décompressée)
Avec Restorator 2.5 on peut voir que ce texte est en fait stocké dans des ressources et non pas dans les datas.
Il semblerait donc qu'une partie des ressources est placée dans une zone mémoire définie par le loader Aspack et donc non initialisée par la version décompressée puisqu'on by-passe le loader.
Encore plus étonnant : le fait de générer une version décompressée, donc de by-passer le loader Aspack, fait
"sauter" le contrôle d'expiration time limit. La protection est donc gérée dans le loader..
En faisant une image (avec Advanced Registry Tracer par exemple) avant expiration de la date puis après expiration, vous trouverez de suite l'entrée dans HKLM qui signale que time is expired.

Merci à SV , Metallica et el.CaRaCoL pour leur participation à la compréhension de cette protection..

Bonne Journée
Christal