TUTORIAL sur ASProtect 2.x :



Protection commerciale : ASProtect 2
Editeur : Alexey Solodovnikov (http://www.aspack.com/asprotectske.aspx )

Ce tutorial décrit le manual unpacking d'ASProtect 2 ainsi que quelques-uns de ses aspects.
Il sera illustré avec 2 cibles :
- Icon Constructor v3.52 ( http://www.iconconstructor.com )
- Flash Conv v1.3 ( http://www.flashconv.com/ )

Outils nécessaires :
OllyDbg v1.10 (Plugins nécessaires : OdbgScript, HideDebugger)
ImpRec 1.6f
LordPE
Masm v9.0
Un éditeur hexadécimal

Trial Reset
Resource Hacker
XnView

OS: Win XP
Attention : certains plugins ne fonctionnent pas bien sous Vista !


Ce tutorial est détaillé de façon suivante :

Introduction

I) Manuel unpacking sur Icon Constructor v3.52

A) Protections anti-debugging
B) Trouver l'OEP
C) Protections anti-dumping
D) Protections du shareware (en lui-même)


II) Manuel unpacking sur Flash Conv v1.3

A) Trouver l'OEP
B) Protections anti-dumping :
C) Protections du shareware (en lui-même) :

III) Perspectives et conclusion

A) Perspectives :
B) Conclusion & remerciements :


Introduction :

ASProtect est l'un des protecteurs les plus connus (avec Armadillo) et les plus employés dans la protection des sharewares.
Il a été développé par Alexey Solodovnikov.
Il existe, en français, deux tutoriaux sur ASProtect 1.2, notamment celui de elooo et Kaine.
Il en existe des plus anciens, comme ceux sur le site de christal ou ceux de +Splaj (en anglais).
Ce tutorial se donne pour objectif la compréhension d'un protecteur commercial avec une certaine méthodologie (méthodologie, qui je l'espère pourra vous aider à attaquer un autre protecteur).
Au contraire, ce tutorial n'a pas pour but de fournir "une recette de cuisine" prête à l'emploi (recette, qui sera forcémment obsolète avec le temps).
Si l'unpacking ne vous intéresse pas, vous pouvez toujours essayer Stripper ou le script de VolX. Mais, ne vous faites pas d'illusion, les solutions publiques sont tôt ou tard contrés par les protectionnistes...

Comment détecter ASProtect ?

On lance Ollydbg et à l'OEP, on retrouve la série d'instructions suivantes, caractéristique d'ASProtect :



ASProtect se caractérise également par le fait que certains noms de section voire tous, ont été effacés :



On peut aussi s'aider de détecteurs comme PEiD, Protection ID, etc...
Comme ils se basent sur des signatures, pour reconnaître le packer en question, il arrive qu'ils se trompent (par exemple, PEiD, qui détecte une version 1.x d'ASProtect, alors qu'il s'agit d'une version 2.x).
Lorsqu'un doute subsiste, il apparaît donc judicieux de vérifier avec un autre détecteur complémentaire.
C'est un peu comme avec les virus. Ce n'est pas parce qu'un antivirus détecte un fichier comme un virus potentiel, qu'il est réellement infecté (faux-positif).
L'utilisation de site tel que ( http://www.virustotal.com/fr/ ) permet déjà d'avoir une idée plus objective. Pour en avoir la certitude à 100%, vous pouvez toujours analyser le fichier en question :p.

Une dernière parenthèse sur les cracks et les antivirus : de plus en plus, les éditeurs de logiciels et d'antivirus sont de connivence et utilisent des méthodes peu loyales, en considérant systématiquement certains cracks comme des virus, alors qu'il n'en rien...
Il est à craindre que cette pratique se généralise...

http://www.trendmicro.com/vinfo/grayware/ve_graywareDetails.asp?GNAME=CRCK_ACDSEE.A
http://www.trendmicro.com/vinfo/grayware/ve_GraywareDetails.asp?GNAME=CRCK_TRAPZERO

Après, il est toujours possible qu'un intermédiaire modifie un crack. Dans ce cas, vérifiez son checksum / CRC / md5 (toute team de qualité le mentionne) ;).
Fin de la parenthèse...

Si votre base de signatures est trop ancienne, il est même possible qu'AsProtect 2 ne soit pas du tout détecté (par exemple avec PEiD) ...

On ouvre l'exécutable "Icon Constructor.exe" avec PEiD, qui nous détecte ceci :
ASProtect 2.1x SKE -> Alexey Solodovnikov.

Avec Protection ID v6.0 Beta, on obtient :
Scanning -> D:\Program Files\Icon Constructor 3\Icon Constructor.exe
File Type : Exe, Size : 618496 (097000h) Byte(s)
[!] ASProtect v2.1 SKE detected !
- Scan Took : 0.735 Seconds


I) Manuel unpacking sur Icon Constructor v3.52 :

A) Protections anti-debugging :
1) Effacement des debug resisters (drx) :

ASProtect 2 efface les Debug Registers (drx) et, par conséquent, les hardware breakpoints, que l'on pourrait poser...

Comment le détecter ? Il suffit de poser un hardware breakpoint et de monitorer le debug register en question (Click droit sur la fenêtre des registres / View debug registers), au travers des différents breaks sur les exceptions.

Il ne faut oublier de décocher les exceptions de type INT 3 :



A l'OEP du loader d'ASProtect, on met un hardware breakpoint on execution (par, exemple en 00475134) :



Il faut tracer / breaker pour qu'Ollydbg mette à jour la valeur des drx.



L'effacement des drx se faisant à l'aide de SEHs. Il suffit donc de monitorer DR0 à chaque exception, pour pouvoir retrouver à quel niveau (SEH), les debugs registers sont effacés. Lorsque l'on arrive sur cette exception, DR0 a été effacé :



Il faut donc breaker à l'exception précédente et étudier le SEH en question :



En posant un breakpoint au niveau du SE handler (cf la pile), on arrive sur la routine, chargée d'effacer les debug registers :



Ce qui concorde avec la structure du context :



Si vous voulez plus d'explications sur ce type de trick (effacement des drx via SEH), vous pouvez consulter le tutorial de BeatriX :
Comprendre tElock 0.98 et private versions

Pour les SEHs, les références sont :
Mouvements de pile et Except handler, par Christal et son Groupe de Travail
Win32 Exception handling for assembler programmers, by Jeremy Gordon

Pour éviter l'effacement des drx et pouvoir utiliser les hardware breakpoints, il existe divers plugins dont :

- PhantOm:



- Anti-Anti Hardware Breakpoint (disponible aussi )

2) Vérification du flag BeingDebug :

On lance Icon Constructor 3 sous Ollydbg et l'on obtient ce message :



On commence à mettre un bp sur l'API classique IsDebuggerPresent.
Malheureusement, on ne breake sur rien d'intéressant :(.
Pourtant, si l'on utilise le plugin Hide Debugger et si l'on coche "IsDebuggerPresent", la détection anti-debugging (anti-ollydbg) échoue...
Pour comprendre ce qu'il se passe, il suffit de regarder ce que fait l'API IsDebuggerPresent :



Elle se branche sur le PEB (récupère l'adresse linéaire de celui-ci), pour récupérer le flag BeingDebug :



http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Process/PEB.html

"01 byte, which is placed at block_base+2 is BeingDebug byte that is also used by IsDebuggerPresent API. If program is debugged, that byte is 1, if not then 0. We must set it to 0".

Maintenant, tapons fs:[18] dans la fenêtre des datas :





Mettons un hardware breakpoint on access (byte). On breake ici :



Note : les jmp eip+3 (EB01) ainsi que l'opcode intercalé en eip+2 (ici E8) ont été noppés pour une meilleure lisibilité...



appelé par le call 00B370B4 en 00B37107 et suivi d'une détection anti-SoftIce :



La détection anti-SoftIce consiste en l'utilisation d'une int 03 (avec les "magic values") :



Plus d'infos sur cette vieille détection de SoftIce, ici.

Il y a d'ailleurs en dessous de ce code, la détection anti-SoftIce, la plus connue, à savoir MeltICE :



Ce code détecte SoftIce par la présence de ses drivers...

On continue de breaker.
Et hop, une émulation de l'API IsDebuggerPresent :



Ensuite, un autre break et l'on retombe à nouveau ici :



Cette fois appelé par :



Un dernier break :



Cette fois, Alexey a poussé le vice, en utilisant la valeur du flag BeingDebug pour sauter au bon endroit...
Voilà, c'en est fini des anti-debugs ;).

Pour contrer ces anti-debugs, vous pouvez utiliser Hide Debugger / Asterix :



L'option protect against IsDebuggerPresent permet justement de mettre à 0, le flag BeingDebug :).


B) Trouver l'OEP :

Comment trouver en général l'OEP d'un programme packé ?
- tracer tout le code
- rechercher la signature du saut vers l'OEP
- se servir des APIs classiques utilisées au début des programmes unpackés
- se servir d'éléments du loader, permettant de breaker juste avant qu'il ne redonne la main au programme unpacké
- se servir de la pile pour remonter à l'OEP

1) tracer tout le code jusqu'au saut à l'OEP :

Pour des packers comme upx, aspack ou des protectors moisis (comme ACProtect, anciennement UltraProtect), c'est faisable manuellement...
Ici, c'est beaucoup trop long et fastidieux :p. Et c'est carrément inenvisageable pour les protectors plus récents et plus costauds...
On peut par contre coder un traceur, qui détectera l'OEP par un changement important de l'eip courant et / ou une signature (tel qu'un jmp eax).

2) recherche de la signature du saut vers l'OEP :

On pouvait utiliser cette méthode pour les premières versions 1.x d'ASProtect.
Lorsque le code du loader d'ASProtect était décrypté en mémoire, il suffisait de chercher la signature hexadécimale "61FFE0", correspondant aux instructions popad / jmp eax, permettant le saut vers l'OEP du programme unpacké.
cf. http://71.6.196.237/krobar/other/up107.html
Bien évidemment, Alexey a remédié à ceci...

En regardant la pile du programme en exécution, on peut retrouver facilement l'une des dernières routines du loader appelées par ASProtect (en vert, sur cette image).
Vous remarquerez que cette adresse change à chaque exécution...
Ceci permet d'éviter l'utilisation de breakpoints (hardware) d'une exécution à l'autre.
On peut contourner la difficulté en mettant un hardware breakpoint on write sur la pile en 0012FF7C. On s'arrête au dernier break avant le lancement de l'application.
On atterrit alors dans une zone mémoire allouée par ASProtect :





En traçant un peu (attention aux différentes exceptions), on arrive à ce code :



On trace à l'intérieur de ce dernier call :



Le code précédent (les adresses et les instructions ne sont jamais les mêmes d'une exécution à l'autre) permet de sauter vers une autre zone mémoire allouée par ASProtect avec le calcul de l'OEP du programme unpacké et le saut final vers celui-ci (le junk code a été éliminé) :



La boucle entourée en bleu permet le décryptage des instructions sous celle-ci et l'apparition du jmp eax :



Ainsi, l'obtention d'une signature du saut vers l'OEP n'est pas d'une grande utilité puisqu'elle apparaît au dernier moment... (autant utiliser un tracer, qui détecte le changement du registre eip vers la section .text). En plus, rien n'indique que le junk code inséré à ce niveau est le même d'une application à l'autre.

Enfin, Alexey avait déjà poussé le vice sur d'anciennes versions d'ASProtect (v 1.23) en effaçant le code d'ASProtect où se trouvent les stolen bytes, les instructions émulées (et la signature éventuelle du saut vers l'OEP), afin de ne pas pouvoir les retrouver une fois dans le code exécutable unpacké.
cf. http://www.forumcrack.com/forum/viewtopic.php?f=6&t=8669

Note : Le junk code d'ASProtect consiste principalement en l'ajout de sauts avec insertion d'opcodes, qui perturbent le désassemblage des instructions sur lesquelles on arrive par ce saut (code polymorphe). ASProtect ajoute aussi des préfixes inutiles...

3) se servir des APIs classiques utilisées au début des programmes unpackés (GetVersion, GetModuleHandle, etc...) :

Cette méthode utilisée, jadis, pour obtenir l'OEP de programmes protégés par d'anciens packers / protectors n'est plus d'actualité pour la raison suivante :
- Il y a de grandes chances que les instructions de ces APIs soient partiellement ou entièrement émulées (c'est le cas pour ASProtect 2).
De plus, la plupart des protectors (Armadillo, EXECryptor, etc...) détectent la présence de breakpoints (scan des premières instructions de l'API à la recherche de l'opcode 0CCh).

4) se servir d'éléments du loader, permettant de breaker juste avant qu'il ne redonne la main au programme (saut vers l'OEP du programme unpacké) :

- Comme pour les anciennes versions d'ASProtect, on peut se servir des exceptions successives (mises en place via des SEHs), pour avancer dans le loader d'ASProtect et breaker à l'OEP. Pour cela, on lance Ollydbg, on va dans le menu Options / Debugging options et l'on décoche la case "Memory access violation" :



Ensuite, on lance le programme dans Ollydbg, on compte le nombre de breaks obtenus (nombre d'exceptions) avant de lancer l'application. Un Alt+F9 permet de passer à l'exception suivante.
On relance le programme et lorsqu'on breake sur la dernière exception du loader :



on fait un View Memory (Alt+M) pour mettre un memory breakpoint sur la section code de l'exécutable en question (Set memory breakpoint on access) :



On arrive finalement à l'OEP de notre programme en relançant :) (N'oubliez pas de faire un Ctrl+A, si votre code n'est pas désassemblé) :



Ces différentes exceptions (via les SEHs) ont été mises en place par Alexey pour corser le tracing / le debugging sous SoftIce.
Ce dernier n'avait pas cette possibilité de breaker sur les exceptions, mises en place dans des SEHs, comme Ollydbg.
Il n'est pas dit que cette méthode marche sur toutes les versions d'ASProtect 2 (et notamment les toutes dernières) !

- On peut utiliser les accès en lecture / écriture pour avancer dans le loader...
C'est la même méthode qu'avec les SEHs mais avec des accès en lecture / écriture.
Pour des packers simples, des accès en écriture suffisent pour avancer dans le loader et breaker à l'OEP.
Ici, ce n'est pas le cas, puisqu'après l'écriture du code, divers accès en lecture se suivent et interfèrent avec un éventuel "Set break-on-access".
Exemple d'accès en lecture : vérifications d'intégrité du code unpacké :



Comment procéder ?
- mettre un Set break-on-access (Alt + M suivi d'un F2) sur la section .text
La commande Set break-on-access sur la section n'est valide que pour un seul accès en lecture contrairement à Set memory breakpoint on access.
- quitter la boucle pour ne plus breaker sur l'instruction, où se déroule l'accès en lecture.
Il suffit de surveiller les sauts conditionnels et les adresses de retour dans la pile...
- on repose un Set break-on-access
- et ansi de suite jusqu'à breaker au niveau de la section .text

On peut également se limiter aux accès en lecture (écriture) sur un endroit limité (par exemple un dword).
- on compte le nombre d'accès en lecture sur ce dword (hardware breakpoint) avant de lancer le programme
- on relance et au dernier accès en lecture, on met un Set break-on-access sur la section .text
- si d'autres accès en lecture se produisent à d'autres endroits, on procédera alors suivant la 1ère méthode

Comme vous l'aurez remarqué, cette méthode est longue, fastidieuse et inefficace...

Ici, avec cette méthode, on finit par breaker en 00401250, qui ne ressemble en rien à un OEP :



En effet, ASProtect exécute au niveau du loader les routines de vérification de l'enregistrement du programme unpacké avant de donner la main à celui-ci...

Cette méthode est complétement inefficace avec des protectors plus performants comme EXECryptor 2. Avant de redonner la main à l'OEP du programme, "des allers retours" sont effectués entre du junk code inséré dans la section .text unpackée et le loader.

- Enfin, on peut se servir d'APIs utilisées dans le loader pour avancer dans celui-ci et procéder de la même manière qu'avec les SEHs pour breaker à l'OEP (avec memory breakpoint on access sur la section .text du programme unpacké).

On peut utiliser comme APIs : MapViewOfFileEx, GetSystemTime et bien d'autres...

5) se servir de la pile pour remonter à l'OEP :

Cette fois, on lance l'exécutable et on examine la pile du programme en exécution :




On clique sur Ctrl+A pour avoir une analyse du programme unpacké.

Ensuite, on cherche dans la pile, des adresses de retour, correspondant à la 1ère section (section .text).
On accède au call en question dans la fenêtre du code, par un click droit / Follow in Disassembler (Enter) au niveau de la pile.
On remonte alors la routine dans la fenêtre du code jusqu'à son début. Deux cas se présentent :
- soit la routine en question n'est appelée par aucune routine (il suffit de regarder en bas de la fenêtre du code). C'est l'OEP.
- soit la routine en question est appelée par une autre routine (il suffit de regarder en bas de la fenêtre du code). Pour trouver l'OEP, il suffit de remonter itérativement jusqu'à une routine, qui n'est appelée par aucune autre. Cette méthode n'est peut-être pas élégante, mais est fiable.On peut éventuellement relancer plusieurs fois l'application et s'aider d'hardware breakpoints pour remonter à l'OEP.
Note : Ce n'est pas parce qu'aucune routine (appelante) n'est notifiée au bas de la fenêtre de code, que la routine en question n'est pas appelée par une autre (Par exemple, les appels du style call eax, call [eax], etc...).

Ici, c'est très facile. En effectuant un Follow in Disassembler, dans la pile (entouré en rouge), en 0012FEB8 (retour en 00475268) et en remontant la routine appelante, on trouve facilement l'OEP (00475134) :



Comme vous l'aurez constaté, il n'y a pas de Stolen Bytes sur cette version 3.52 d'Icon Constructor (il y en avait sur la 3)...

Une manière plus élégante est de s'aider des SEHs, plus précisemment des SE handlers. Dans notre exemple, un click droit / Search for / All commands / push 00489578 (SE handler entouré en bleu), nous amène directement au niveau de l'OEP...

Pour trouver génériquement l'OEP d'un programme protégé par ASProtect (sans l'option "protection sur l'OEP"), le mieux à faire est de coder un traceur, qui repérera le "jmp eax", combiné à un changement de l'eip courant (et pointant sur la section .text). La deuxième condition n'est pas suffisante à elle seule, à cause de la possibilité d'ASProtect, d'exécuter du code du programme unpacké, avant l'OEP.

Maintenant, on sait que l'OEP se trouve en 00475134, que le programme a été écrit en Microsoft Visual C++ 6.0
On peut donc passer à la suite...


C) Protections anti-dumping :
1) Advanced Import Protection v 1 :

Tout d'abord, un petit rappel pout trouver l'IAT, son début et sa fin :

L'IAT est un tableau d'adresses (variant suivant l'OS) des différentes API utilisées par le programme en question. La séparation entre les différentes librairies / dlls se fait à l'aide d'un dword nul.
L'appel à ces APIs se fait à l'aide de call dword ptr [xxxxxxxx] / jmp dword ptr [xxxxxxxx]. Pour en trouver, il suffit de faire défiler le code de la fenêtre CPU.
Pour les call [API], on peut utiliser la commande Search for -> All intermodular calls.
Une fois le call / jmp [API] repéré, on peut faire un Follow in Dump -> Memory Address pour avoir dans la fenêtre Data, l'adresse de l'API au niveau de l'IAT :



Pour une meilleure lisibilité, vous pouvez faire Click droit -> Long -> Address :



Lorsqu'un séparateur (dword nul) est suivi d'une valeur, qui n'a rien à avoir l'adresse d'une API, c'est que l'on est à la fin de l'IAT...
L'IAT du programme commence donc en 00480000 et finit en 00480688.

Pour de plus amples informations sur les imports, vous pouvez toujours consulter (en français) :
Import Function tutorial.doc / Import-Function in section RDATA.doc de El.CaRaCoL

A l'OEP, on lance ensuite ImpRec et l'on met les valeurs suivantes :



On clique sur Show Invalid :



Il y a donc dans l'IAT, une adresse (un import) détournée par ASProtect en 004800E0 (pointe en 00B37290)...
Allons voir cette routine en 00B37290 :



Hum... Difficile de ne pas s'apercevoir que c'est l'API GetProcAddress, qui est détournée...



On n'a juste à remplacer en 004800E0 (qui pointe vers 00B37290), de telle manière à ce que l'adresse de l'API GetProcAddress (ici, 7C80AC28) soit pointée (*):



Ceci doit être modifié en :



Toujours à l'OEP, on lance LordPE et l'on fait un dump full (on obtient alors dumped.exe) :



On relance ImpRec et l'on refait les mêmes choses que précédemment. Cette fois, on n'obtient plus rien, en cliquant sur Show Invalid.
On clique sur Fix Dump et l'on sélectionne le dumped.exe précédent.
On obtient un dumped_.exe, que l'on lance et bien sûr, cela ne marche pas...
Sous Ollydbg, on obtient l'erreur suivante :



En traçant un peu, on s'aperçoit que le problème est situé à l'adresse 00467DC7 :



ASProtect détourne donc les call [API] en call 00D80000 (adresse d'une zone mémoire allouée par ASProtect...), 00D80000 étant l'adresse d'une routine d'ASProtect, chargée de calculer l'adresse de l'API détournée, pour émuler ses premières instructions puis sauter sur celle-ci...
Dans le dump, la routine dans cette zone allouée par le loader d'ASProtect n'est plus présente, d'où le crash.

Il s'agit donc de cet "Advanced Import Protection".
"Advanced" me fait sourire, puisque ce type de protection était déjà instauré dans les jeux depuis au moins 1999 (dans Safedisc - SecuROM - etc...).
Alexey, ne serais-tu pas à la traîne ?

Maintenant, comment trouver cette adresse (00D80000) sans être obligé de dumper et reconstruire l'exécutable ?
Il suffit d'un click droit / Search for / All intermodal calls :



On relance donc l'exécutable protégé par ASProtect pour tracer à l'intérieur de la routine située en 00D80000...
En fait, ASProtect copie les x premières instructions d'une API en mémoire, suivi d'un saut vers l'API (ou plutôt vers sa (x+1)ième instruction). Pour un gain de temps et ne pas avoir à refaire plusieurs fois cette opération, ASProtect patche le call 00D80000 précédent en un call 00EF0004 (puis l'exécute). Ce dernier nous conduit à la zone mémoire évoquée précédemment (avec les x premières instructions copiées de l'API, suivie d'une redirection "au milieu" de celle-ci).
Ce procédé de copie des x premières instructions d'une API n'est pas non plus nouveau... Il a été utilisé par Copylok (les jeux Cossaks, Gangters 2, ONI, Sudden Strike, Tropico). Ce procédé constitue également un anti-bpx API. En effet, lorsque l'on pose un bp API, une int 03 (CC) est placée à l'adresse de la 1ère instruction de l'API. Et comme le programme protégé n'y passe pas, tous les bp API ne permettent donc pas de breaker et ne servent à rien dans le programme lui-même...



En 00EF0004, on a ceci :



Le push 0EE0000/ret (équivalent à un jump) nous envoie là :



Les 5 premières instructions de l'API en question , ont été copiées. Le push 7CAC66A0/ret nous fait sauter sur la 6ème instruction de l'API SHGetSpecialFolderPathA :



Après l'exécution de cette API, on retourne tranquillement en 00467DCD :



Maintenant, il s'agit de trouver comment récupérer l'adresse des APIs détournées.
Il suffit de tracer dans la routine en 00D80000 :



En fait, on trace les routines en Step over. Dès qu'on trace un call, qui relance le programme, c'est qu'il fallait faire du Step into :p.
En procédant deux fois de la sorte, on finit par arriver à la routine, qui détermine l'adresse de l'API en question (il faut alors surveiller le registre eax).
On trace donc jusqu'à arriver à un call ecx [le registre change d'une exécution à l'autre...] :



Ce n'est pas dur à trouver ; c'est juste à la fin de la routine.

On fait un Step into (F7) :



On trace jusqu'à arriver ici :



On fait un Step into (F7) à l'intérieur du call 00B45B38, situé en 00B45973 :



En traçant (F8) une dernière fois, on finit par tomber en 00B45C91, avec eax pointant sur l'API concernée :).
Apparemment, cette adresse est toujours du style 0xxx5C91 pour une même version d'ASProtect...



2) Vérification d'intégrité de la routine, chargée de calculer l'adresse de l'API :

J'avais fait un call-fixer en asm (j'ai pris un de mes call-fixer pour SecuROM :p et je l'ai modifié). Il recherche dans la section .text toutes les occurences de call 00D80000. S'il en trouve une, il émule son appel (en mettant la bonne valeur sur la pile) et saute vers cette routine (00D80000). ASProtect nous calcule l'adresse de l'API détournée à partir de la valeur mise dans la pile (lors du call). Arrivé en 00B45C91, on détourne pour récupérer l'adresse de l'API (contenue dans eax). On recherche dans l'IAT, l'adresse correspondante et l'on patche le call 00D80000 (soit E8xxxxxxxx) en call dword ptr [00480xxx] (soit FF15xx0x4800). On "vide" la pile et ainsi de suite...
J'avais assemblé ce call-fixer avec Masm v9, l'avais copié dans le header (Binary Paste) et détourné de l'OEP d'Icon Constructor (00475134) par un "Goto expression" et un "New origin here". J'avais détourné l'instruction en 00B45C94 par un simple jump !!!
Malheureusement, ASProtect effectue des vérifications d'intégrité sur cette routine et l'on a droit à :



Voici la routine, qui effectue cette vérification :



La valeur calculée est stockée en eax. Elle est appelée en 00B445BA :



Bien-sûr, inverser le saut par exemple en 00B445EB ne suffit pas à neutraliser la protection et fait planter le programme, puisque cette valeur est utilisée...
Sur SoftIce, une macro aurait suffit...

Note : Cette erreur 115 peut survenir également en traçant (Step over F8) justement le call, chargé de la vérification d'intégrité. En effet, le debugger modifie le code de l'instruction suivant le call, en y mettant une int 03 (opcode 0CCh) et par conséquent l'intégrité de la routine d'ASProtect.

3) Fixer les call ASProtect à l'aide d'un script sous Ollydbg :

Finalement, j'ai commencé par faire un script pour OllyScript (ASProtect 2.xx_call-fixer.txt) :

/*
Aspr 2.xx call-fixer
--------------------
*/

var Aspr
var Count
var Offset
var Stack
var TextFound
var IATStart
var IATEnd
var x

ask "Enter IAT start:"
cmp $RESULT,0
je @err1
mov IATStart,$RESULT
ask "Enter IAT end:"
cmp $RESULT,0
je @err1
mov IATEnd,$RESULT
ask "Enter address of redirected "call API":"
cmp $RESULT,0
je @err1
mov Aspr,$RESULT

mov Count,0
mov TextFound,00401000
mov Offset,eip
bphws 00B45C94, "x"
@start:
find TextFound, #E8#
cmp $RESULT,0
je @end
inc $RESULT
mov TextFound,$RESULT
mov x,[$RESULT]
add x,$RESULT
add x,04
cmp x,Aspr
jne @start
add $RESULT,04
mov Stack,esp
sub esp,04
mov [esp],$RESULT
mov eip,Aspr
run

mov $RESULT,IATStart
@Search_IAT:
cmp [$RESULT],eax
je @APIFound
add $RESULT,04
cmp $RESULT,IATEnd
ja @err2
jmp @Search_IAT

@APIFound:
inc Count
mov x,TextFound
dec x
mov [x],0015FF
add x,02
mov [x],$RESULT
mov esp,Stack
jmp @start

@err1:
msg "Error! Check these values!"
jmp @exit

@err2:
msg "API not found in IAT!"
jmp @exit

@end:
eval "Script finished! In total {Count} calls are restored!"
msg $RESULT
@exit:
bphwc 00B45C94
mov eip,Offset
ret



Il suffit de rentrer le début de l'IAT, la fin de l'IAT et l'adresse de la routine ASProtect, chargée de détourner les APIs...
Pour ce programme, on doit donc entrer 480000, 480688 et 00D80000...

J'ai fait un script pour retrouver l'adresse appelée par les call Aspr (Search_call_aspr.txt) :



Modifiez également si nécessaire : bphws 00B45C94, "x" en mettant l'adresse à détourner. (Vous aurez certainement à changer cette ligne pour un autre programme protégé par une version similaire d'ASProtect...).
Si ce sont les jmp [API], qui sont détournés, modifiez la ligne suivante de cette façon :
mov [x],0015FF -> mov [x],0025FF

Comment savoir si ce sont des call [API] ou des jmp [API] ?
- Tout d'abord, connaître le langage de programmation aide grandement :).
- Ensuite, si vous avez des call ASProtect en plein milieu d'un "tableau" de jmp [API], il n'est pas très difficile de répondre à la question :



(Exemple de Tag&Rename v3.4.6)

- Enfin, on peut avoir la réponse en étudiant le retour du call ASProtect.
Après, je ne pense pas qu'ASProtect détourne à la fois les call [API] & les jmp [API], comme le fait la protection Laserlock (en tout cas, je ne suis jamais tombé sur un cas pareil).


Note : N'utilisez pas le plugin OllyScript, mais ODbgScript !!!
Ce dernier comporte plus de commandes et est bien plus rapide dans l'exécution des scripts.

Mon script reconstruit parfaitement tous les calls (135 calls reconstruits pour Icon Constructor 3).
Pour vérifier ceci, il suffit d'un click droit / Search for / All commands / call 00D80000...

Maintenant, vous pouvez dumper et reconstruire l'exécutable (à l'aide d'ImpRec).
Important : N'oubliez pas d'effectuer l'étape (*) avant d'exécuter le script !!!
On peut ensuite lancer le programme pour détecter s'il y a eu des problèmes éventuels...

J'ai renoncé à l'utilisation de la commande findop ; pour une raison, que j'ignore, un tas de "call ASProtect" étaient "oubliés"...
Il semblerait que réduire la fenêtre d'Ollydbg pendant l'exécution d'un script, empêcherait les ralentissement par les :



De plus, rien ne vous empêche de modifier ces scripts à votre convenance ;-)

Ce script étant loin d'être optimisé, j'ai codé un call-fixer en asm...

3) Fixer les call ASProtect à l'aide d'un call-fixer en asm (Masm 9.0) :

Mon call-fixer intercepte les adresses des APIs dans le code d'aspr, de la même manière que mon précédent script, mais en modifiant le code d'aspr et en neutralisant ses vérifications d'intégrité :-). On peut quand même dire qu'Asprotect utilise des "nasty checks", puisqu'il vérifie non seulement l'intégrité du code, qui détermine l'adresse des APIs à retourner, mais également celui chargé de cette vérification d'intégrité... Il suffit de mettre un bpx sur le not eax en 00B44522 (voir en 2) et d'appuyer sur F9 un moment pour s'en convaincre ;).



Voici ce call-fixer (Aspr.asm fourni) pour Icon Constructor 3 :


; #########################################################################

      title call_fixer
      .386
      .model small, stdcall
      option casemap :none

; #########################################################################
    .code

    TextOffset     equ 00401000h
    TextSize        equ 0007F000h
    IATStart       equ 00480000h
    IATEnd        equ 00480688h
    Aspr             equ 00D80000h
    Aspr_check  equ 00B44508h
    Aspr_API     equ 00B45C94h



start:        pushad
               mov eax,TextOffset
               mov ebx,dword ptr [eax]
               push ebx
               call @delta1
@delta1: pop ebx
               add ebx, offset here2-offset @delta1
               mov eax,Aspr_check
               call patch
               mov eax,Aspr_API
               sub ebx,offset here2-offset here1
               call patch
               mov edx,TextOffset
               mov ecx,TextSize
search_loop:   cmp byte ptr [edx],0E8h
               jne try_again
               mov esi,dword ptr [edx+1]
               add esi,05
               add esi,edx
               cmp esi,Aspr
               jne try_again
               lea eax,dword ptr [edx+5]
               pushad
               mov edi,TextOffset
               push eax
               mov dword ptr [edi],esp
               jmp esi
here1:      mov edx,IATStart
search_iat:   cmp dword ptr [edx],eax
               je got_match
               add edx,04
               cmp edx,IATEnd
               jne search_iat
               nop
got_match:   mov edi,TextOffset
               mov esp,dword ptr [edi]
               pop eax
               mov word ptr [eax-05],15FFh
               mov dword ptr [eax-03],edx
               popad
try_again:   inc edx
               dec ecx
               jne search_loop
               pop ebx
               mov eax,TextOffset
               mov dword ptr [eax],ebx
               popad
               nop

here2:      push eax
               push esi
               call @delta2
@delta2: pop esi
               lea eax,dword ptr DS:[edx+ecx-1]
               cmp eax,Aspr_API+05
               ja @1
               cmp eax,Aspr_API
               jb @1
               sub eax,Aspr_API
               add eax,esi
               add eax,offset here3-offset @delta2+1
               mov bl, byte ptr [eax]
               jmp @3
@1:        cmp eax,Aspr_check+05
               ja @2
               cmp eax,Aspr_check
               jb @2
               sub eax,Aspr_check
               add eax,esi
               add eax,offset here3-offset @delta2+7
               mov bl, byte ptr [eax]
               jmp @3
@2:         mov bl, byte ptr DS:[edx+ecx-1]
@3:         pop esi
               pop eax
               shl ebx,18h
               push Aspr_check+07
here3:      ret

               db 33h,0C0h,8Ah,0C3h,01,45h
               db 8Ah,5Ch,0Ah,0FFh,0C1h,0E3h

patch proc
               mov byte ptr [eax],68h
               mov byte ptr [eax+05],0C3h
               mov dword ptr [eax+01],ebx
               ret
patch endp


end start

- TextOffset est l'adresse à laquelle débute la section .text
- TextSize est la taille de la section .text
- IATStart est l'adresse à laquelle commence l'IAT
- IATEnd est l'adresse à laquelle termine l'IAT
- Aspr (ici, 00D80000) est l'adresse à laquelle sont détournées tous les call ou jmp APIs :



- Aspr_API (ici, 00B45C94) est l'adresse où l'on peut récupérer l'adresse de l'API détournée :



- Aspr_check (ici, 00B44508) est l'adresse où se font les vérifications d'intégrité sur le code d'Aspr :



Note : Pour trouver cette routine, il suffit de poser un "memory breakpoint" en 00B45C94, par exemple (là, où l'on récupère l'adresse de l'API).

Maintenant, je vais expliquer rapidement ce que fait ma routine...
A l'aide de la procédure "patch", elle détourne tout d'abord la routine, qui calcule l'API à émuler partiellement et celle, qui vérifie l'intégrité d'ASProtect .
Ensuite, elle scanne toute la section .text (search_loop) à la recherche d'un "call aspr". Si l'un des ces call est détecté, on émule cet appel avec un push eax avant de stocker le registre esp à l'adresse "TextOffset" (401000h). Le saut jmp esi nous amène directement dans la routine d'aspr... On revient à notre routine en here1 par un push here1/ret (équivalent à un saut), patché au début. On a ainsi récupéré l'adresse de l'API détournée (stockée dans eax). Search_iat permet de rechercher cette adresse dans l'IAT (Import Address Table). Si l'occurence est trouvée, got_match permet alors de fixer le call aspr en question, en ayant préalablement restauré la pile (valeur d'esp en "TextOffset"). J'ai mis un nop juste avant le label got_match au cas où l'adresse de l'API ne serait pas retrouvée dans l'IAT. C'est juste par précaution, mais cela ne devrait pas arriver. Et ainsi de suite...
Quant à here2, c'est pour le détournement des multiples vérifications d'intégrité du code d'aspr. Here2 renvoie les bonnes valeurs via les deux "chaînes" stockées juste après here3, pour qu'aspr ne détecte pas les deux modifications de son code ;). L'instruction shl ebx,18h est rippée de la routine de vérification d'intégrité d'aspr (à cause du détournement).

Remarque importante : Si ce sont des jmp API, qui sont détournés, il suffit de changer "mov word ptr [eax-05],15FFh" en "mov word ptr [eax-05],25FFh" dans le got_match...


Pour une même version d'ASProtect, les adresses au niveau d'Aspr_check et d'Aspr_API sont toujours du type 0xxx4508 et 0xxx5C94...
Une fois ces modifications faites, il ne reste plus qu'à assembler Aspr.asm avec Masm 9 :). On obtient un Aspr.exe .

On lance le programme via Ollydbg et l'on bose un hardware breakpoint à l'OEP pour y breaker...
Dans la fenêtre du code ou des datas, on va en 00400800 (ou ailleurs dans le PE de l'exécutable) -> Go to, Expression, 00400400.
On ouvre le fichier précedemment assemblé via un éditeur hexadécimal (pour moi, ça sera Hex Workshop 2.54), on sélectionne la partie exécutable du fichier que l'on colle en 00400800 (Binary, Binary Paste).
Dans le listing désassemblé, on fait également un Go to 00400800, puis on clique à cette adresse pour effectuer un New Origin here...
On obtient ceci :



On met alors un bp en 00400870 et un en 00400890. On lance (F9) et si tout va bien, on breake en 00400890 en moins d'une seconde :o .
Il suffit de se remettre à l'OEP et de lancer le programme, pour constater que tous les call API ont été correctement fixés...
Important : N'oubliez pas d'effectuer l'étape (*) avant d'exécuter le call-fixer !!!

Voilà, on obtient un dump fonctionnel d'ASProtect (enfin presque...).
Si vous êtes un vieux de la vieille et que vous voulez désassembler avec W32Dasm v8.93, mettez alors un nom aux sections, nom qu' ASProtect a effacé. N'oubliez pas, aussi, de mettre dans les caractéristiques de la section .text, la valeur E0000020...

4) Utiliser l'API hooking pour obtenir un call-fixer (script) générique :

Plus vous étudierez en détail les mécanismes de la protection, plus vous gagnerez en efficacité (script plus puissant et générique).

Pour savoir comment ASProtect retrouve l'API d'un call ASProtect, il nous suffit de tracer ici le call, juste avant l'instruction en 00B45C91 (où eax pointe sur l'API concernée) :



D'abord, il retrouve le module de l'API en question :



Le nom du module est dans une import table d'ASProtect et n'est pas crypté (contrairement aux noms de ses fonctions).
Pour ce module, il recherche le nom de l'API concernée à l'aide d'un identifiant, puisque le nom de l'API est crypté...
Il est encodé sous forme d'un word (0x61A2, ici) et est suivie de la longueur de la chaîne ASCII de l'API, également encodée sous forme d'un word (0x18, ici).
La comparaison se fait ici :





Une fois l'API trouvée, il déplace la chaîne en question dans un buffer pour la décrypter :



On a alors un appel à l'API LoadLibraryA (dont les premières instructions sont émulées) :





Ce qui est génial, c'est qu'à l'appel de cette API, edi pointe vers le nom de l'API détournée :



L'appel à LoadLibraryApeut se faire également à ce niveau (ça ne change rien de toute façon) :



Enfin, ASProtect recherche le nom de l'API détournée par comparaison, dans la table des exports du module en question, puis retrouve son adresse.
Ceci évite un appel direct à l'API GetProcAddress (c'est l'une des premières choses que va rechercher un cracker pour les imports).



Il est donc assez facile d'écrire un call-fixer générique (ici, sous forme de script).

Il suffit de hooker (intercepter les appels à l'API LoadLibraryA).
On peut le faire en mettant un hardware breakpoint après les instructions émulées par ASProtect.
A ce niveau-ci, le break nous permet de retrouver le call appelant et de mettre un hardware breakpoint au retour de l'appel à LoadLibraryA.
Comme LoadLibraryA nous a retourné un handle du module qui contient notre API et comme edi pointe vers le nom de cette dernière, il n'y a plus qu'à simuler un appel à GetProcAddress pour recupérer l'adresse de l'API :).

Voici ce script (ASProtect 2.xx_call-fixer2.txt) :


/*
Aspr 2.xx call-fixer
--------------------
*/

var Aspr
var Count
var Offset
var Stack
var TextFound
var IATStart
var IATEnd
var x

var Count
var GPA_Offset
var LLA_Offset
var Offset
var Stack
var IATStart
var IATEnd



ask "Enter IAT start:"
cmp $RESULT,0
je @err1
mov IATStart,$RESULT
ask "Enter IAT end:"
cmp $RESULT,0
je @err1
mov IATEnd,$RESULT

mov e_lfanew,[0040003C]
add e_lfanew,00400000
mov section_header_offset,e_lfanew
add section_header_offset,0F0
mov text_size,section_header_offset
add text_size,010
mov text_size,[text_size]
mov text_offset,section_header_offset
add text_offset,014
mov text_offset,[text_offset]
mov text_end,00400000
add text_end,text_offset
add text_end,text_size

mov TextFound,00400000
add TextFound,text_offset

@start:
find TextFound, #E8#
cmp $RESULT,0
je @continue
inc $RESULT
mov TextFound,$RESULT
mov x,[$RESULT]
add x,$RESULT
add x,04
cmp x,text_end
jb @start
mov y,x
shl y,010
cmp y,0
jne @start
mov Aspr,x

@continue:
eval "Call ASPr is call {Aspr} !"
msg $RESULT

mov Count,0
mov TextFound,00401000
mov Offset,eip
gpa "GetProcAddress","kernel32.dll"
mov GPA_Offset,$RESULT
gpa "LoadLibraryA","kernel32.dll"
mov LLA_Offset,$RESULT
find LLA_Offset, #74#
mov y,$RESULT
bphws y, "x"
@loop:
find TextFound, #E8#
cmp $RESULT,0
je @end
inc $RESULT
mov TextFound,$RESULT
mov x,[$RESULT]
add x,$RESULT
add x,04
cmp x,Aspr
jne @loop
add $RESULT,04
mov Stack,esp
sub esp,04
mov [esp],$RESULT
mov eip,Aspr
run
mov z,[esp+0C]
bphws z, "x"
run
mov [esp-04],edi
mov [esp-08],eax
mov [esp-0C],eip
sub esp,0C
mov eip,GPA_Offset
run
bphwc z

mov $RESULT,IATStart
@Search_IAT:
cmp [$RESULT],eax
je @APIFound
add $RESULT,04
cmp $RESULT,IATEnd
ja @err2
jmp @Search_IAT

@APIFound:
inc Count
mov x,TextFound
dec x
mov [x],0025FF
add x,02
mov [x],$RESULT
mov esp,Stack
jmp @loop

@err1:
msg "Error! Check these values!"
jmp @exit

@err2:
msg "API not found in IAT!"
jmp @exit

@end:
bphwc y
eval "Script finished! In total {Count} calls are restored!"
msg $RESULT
mov eip,Offset

@exit:
ret

Il suffit de le lancer à l'OEP et il va nous fixer tous les call ASProtect.
Il a l' inconvéniant d'être lent (toujours à cause du find).
Si la section .text est très grande, il y a peu de chance que le message de fin apparaisse (il suffit de faire un Search For > All commands des call ASProtect pour savoir si le script a terminé son travail).
A part ce défaut, il fonctionne très bien et ne demande l'entrée d'aucun paramètre...

5) Fixer les call ASProtect du schéma d'enregistrement :

Il y a en fait encore un trick (dans le schéma d'enregistrement)...

L'exécutable étant unpacké, essayons de voir l'algorithme de vérification du serial.
Si le serial entré est absent ou faux, la boîte de dialogue suivante apparaît :



Mettons un bp MessageBoxA.
On breake alors et au niveau de la pile, on obtient :



Un click droit au niveau de la fenêtre de la pile ( Follow in Disassembler - Enter ) nous amène au code, responsable de l'appel à l'API MessageBoxA :



Lorsque l'on enregistre, le logiciel vérifie d'abord si votre serial fait bien 33 caractères (ou plus)...
Le serial doit aussi commencer par la chaîne "NC3-" :



La comparaison entre les 4 premiers caractères du serial et la chaîne "NC3-" se fait à l'aide de _mbscmp.
Ensuite, le logiciel va vérifier si le serial est blacklisté / volé :



Mais, on crashe à cause d'un call 00EF0004 en 00469DB0...

Il y a aussi d'autres call ASProtect non fixés :



C'est d'ailleurs, plutôt ici, que vous aurez un crash (et non en 00469DB0), si vous n'avez pas créé de keyfile contenant un mauvais serial ;).





Ici, il s'agit de l'API SHGetSpecialFolderPathA...

J'ai fait un script pour retrouver ces call Aspr non fixés (Search_call_aspr_not_fixed.txt) :


Log data :

Call DD0004 found at 42D3DB !
Call EF0004 found at 469DB0 !
Call F10004 found at 469DCE !
Call F30004 found at 469DF2 !
Call F50004 found at 469E0D !
Call F70004 found at 469E1F !
Call F90004 found at 469E2C !

Comment se fait-il qu'il reste des call ASProtect non fixés ?
C'est dû au fait, qu'ASProtect a déjà exécuté ceux-ci (avant l'OEP), ce qui lui a permis de patcher ces calls pour qu'ils soient redirigés en mémoire (allocation dynamique) vers l'API en question (dont les premières instructions sont émulées).
En effet, ASProtect vérifie la licence en exécutant ces fonctions dans le programme unpacké, avant de donner la main à l'OEP de celui-ci.
Il faut donc exécuter le call-fixer (le script ou la routine asm) avant l'exécution de ces routines (elles-mêmes exécutées avant l'OEP).

Il suffit donc de trouver la routine, chargée de calculer et de patcher l'adresse des call ASProtect (dans mon cas, 00D80000).
Ensuite, avec un "Set memory breakpoint on access" sur la section .text, on trouve la 1ère routine du programme unpacké, exécutée avant l'OEP :



On lance le script (142 call ASProtect reconstruits).
Il suffit de dumper la section .text et c'est gagné :).
Si vous dumpez l'intégralité de l'exécutable, vous aurez un nag-screen supplémentaire à supprimer (période d'évaluation expirée) :p.

Note : Apparemment, ASProtect 2 (les dernières versions ?) émulerait directement certains call [API] / jmp [API] en call 0xxx0004 sans passer par l'étape call aspr (call 0xxx0000)...
Quoiqu'il en soit, il faut veiller à bien les restaurer, pour ne pas avoir de mauvaise surprise par la suite.


On reprend et on teste le serial "NC3-01234567890123456789012345678".
On trace le call 00469EB0 en 0046A219 pour arriver à cette routine :

En traçant (trace into) le call 00469D70 en 00469ECB, on repère les jolies crypto-APIs de Microsoft :



A quoi correspond l'API CryptCreateHash ?
Il suffit de chercher dans la MSDN : http://msdn.microsoft.com/en-us/library/aa379908.aspx


CryptCreateHash Function :

The CryptCreateHash function initiates the hashing of a stream of data. It creates and returns to the calling application a handle to a cryptographic service provider (CSP) hash object. This handle is used in subsequent calls to CryptHashData and CryptHashSessionKey to hash session keys and other streams of data.

Syntax :

BOOL WINAPI CryptCreateHash(
__in HCRYPTPROV hProv,
__in ALG_ID Algid,
__in HCRYPTKEY hKey,
__in DWORD dwFlags,
__out HCRYPTHASH *phHash
);


Ici, l'Algid est de 0x00008003 (cf. push 8003, en 00469DC8). Le hash en question est donc un md5.

Le logiciel compare le hash md5 du serial entré à une base de hashes md5 de serials blacklistés / volés (trois en tout). Voici la boucle :



La comparaison est faite ici :



Si vous avez entré un serial volé / diffusé sur Internet, vous avez le message correspondant.
En plus, il se connecte à Internet pour afficher cette page.

Enfin, il refait un hash md5 sur ce serial entré et compare le résultat à une base de hashes md5 de serials valides (5000 en tout)...
Si l'on a un serial légal, on a droit à :



Vu la taille du serial, il est impossible de faire un bruteforce pour trouver un serial valide.
Ce logiciel n'est donc pas "fishable / keygenable", mais il reste "crackable" :).


D) Protections du shareware (en lui-même) :

Comment marche le schéma de protection ?

Tout d'abord, ASProtect 2 unpacke Icon Constructor.exe
Elle vérifie la présence d'une licence en utilisant les fonctions correspondantes dans le code unpacké d'Icon Constructor. Il s'agit d'un schéma d'enregistrement "custom" (hash md5), càd fait par le développeur du logiciel. Il aurait pu en effet utiliser un schéma d'enregistrement via ASProtect.
Lorqu'il n'y a pas de licence valide, deux cas se présentent alors :
- La période d'évaluation de 30 jours est expirée et ASProtect lance alors Registration.exe :



- La période d'évaluation de 30 jours n'est pas expirée et ASProtect lance l'exécutable unpacké en allant à son OEP.
L'exécutable unpacké refait les vérifications, notamment au niveau de la présence d'une licence et met en place les limitations (s'il n'y a pas de licence), à savoir :
nag-screen, état d'enregistrement dans le About et watermark (hidden check) au niveau de la sauvegarde d'icônes...
De plus, l'exécutable unpacké sait detecter si l'unpacking s'est fait pendant la période d'évaluation. Dans le cas contraire, il lance également Registration.exe .

La période d'évaluation (le trial) est donc gérée par ASProtect. Si vous voulez réinitialisez la période d'évaluation, vous pouvez utiliser Trial Reset, qui effaçera les clés correspondantes dans la base de registre.



A ce propos, la version 3.4 Final est sortie, il n'y a pas longtemps (http://www.exetools.com/forum/showthread.php?t=11178).

1) Supprimer l'apparition du nag-screen :



Pour cela, il suffit de regarder dans la pile à l'exécution du programme (et à l'affichage du nag) :



La routine, qui permet l'affichage du nag est la suivante :



routine appelée par :



Pour supprimer le nag-screen, on peut jouer sur ce call, en modifiant 00497088 pour qu'il pointe vers 004013AD (RETN de la routine précédente).
Note : On verra plus loin à quoi correspondent ces octets en apparence aléatoires et non désassemblés.

En faisant la modification le nag-screen est effectivement supprimé, puisque l'on passe directement à la fenêtre suivante :).



2) Modifier l'état d'enregistrement dans le About :



De la même manière, on retrouve la procédure qui affiche le About :



Il suffit de mettre un MOV DWORD PTR SS:[EBP-4],01 en 0046A6C7 :



Maintenant, le programme nous affiche un état enregistré :).




3) Supprimer les possibilités de watermark :

On peut considérer qu'il s'agit d'un hidden check, puisque ce programme est un trial (utilisation limitée à 30 jours) et rien n'annonce la présence éventuelle d'un watermark sur l'icône sauvergardée (il n'apparaît pas pour la sauvegarde d'images)...
En plus, le watermark n'apparaît que pour les sauvegardes d'icônes en 32x32 et 48x48 :



Pour arriver à localiser l'application de ce watermark, on peut déjà examiner les ressources à l'aide Resource Hacker.
On trouve un directory appelé TGA_IMAGE.

Les watermarks sont donc des images au format Targa (cf. wikipedia) :


Truevision Targa ou TGA est un format de fichier image qui a été développé par Truevision à partir de 1984. Le format TGA supporte les images de n'importe quelle taille. Il est principalement utilisé dans les milieux professionnels pour la création d'images couleur. Il permet de développer des images selon trois techniques : Il est capable de coder les couleurs entre 1 et 32 bits.

On fait click droit -> Save all [ TGA_IMAGE ] resources ...
Ensuite, je vous conseille d'installer XnView, qui est un visualiseur, browser & convertisseur multimédia performant, supportant plus de 400 formats graphiques !
On renomme avec XnView les fichiers Data_x.bin (où x est un numéro) en fichiers targa càd Data_x.tga
Avec l'explorateur de XnView, on s'aperçoit que les watermarks "Trial" correspondent aux fichiers Data_20.tga & Data_21.tga
On retourne dans Resource Hacker. Ils correspondent à 217 & 218 dans l'arborescence de [ TGA_IMAGE ].
Leurs offsets sont 000D9B30 & 000E2B60...

On peut modifier l'entête du fichier targa pour ne plus avoir le watermark.

On peut également mettre un ret au début de cette routine, qui réalise l'intégration des watermarks :




4) Les Protected Sections :

De quoi s'agit-il ?
Il s'agit de parties de code, codées par ASProtect et qui, ne sont décodées qu'en présence d'une licence (serial).

Comment les reconnaître ?

Voici la routine, qui détermine l'état enregistré ou non, dans le About de Icon Constructor 3 :



Par la même méthode, on essaie d'obtenir la routine, mais pour Watermark Factory 2 et là on a :




Les bytes "non-désassemblés" sont cryptés et vous remarquerez qu'ASProtect met des sauts courts au format saut long.
Le E93A000000 aurait du être écrit EB3A si ça avait été le compilateur (Merci à TrapZero pour me l'avoir fait remarqué à l'époque ;) ).

Les Protected Sections sont l'équivalent des Secured Sections d'Armadillo (je me demande d'ailleurs, laquelle de ces 2 protections a piqué le concept à l'autre...).

Comment s'en débarasser ?
Normalement, pour récupérer les bytes décodés des Protected Sections, il faut une license / un serial.
Mais, c'est loin d'être toujours le cas...

Plusieurs cas peuvent se présenter :
- Les Protected Sections sont mal implémentées et/ou concernent des fonctions non vitales.
C'est le cas ici. Les Protected Sections ne nous ont nullement empêché de cracker le logiciel.

Les Protected Sections peuvent être bien implémentées, mais si elles ne concernent que des fonctions non vitales (ce n'est pas très malin de faire ça), elles sont
inutiles. C'est le cas de Watermark Factory v2.58 et de Video Watermark Factory v1.0 du même éditeur où la Protected Section au niveau du
About s'enlève facilement en modifiant le code ou en retouchant les ressources, pour faire disparaître certains boutons et en modifiant la chaîne
"UNREGISTERED", à l'aide d'un éditeur hexadécimal...



- Les Protected Sections sont bien implémentées et concernent des fonctions vitales, mais...
C'est le cas des deux logiciels cités précédemment, où la Protected Section portant sur le watermark est bien implémentée...
La protection reste tout de même contournable. En effet, il suffit de modifier ,au niveau des ressources, l'entête de l'image Targa correspondant au watermark,
pour que celui-ci disparaisse...

- Le schéma de vérification du serial est custom et n'est pas celui d'ASProtect.
Dans ce cas, il est possible de décoder les bytes des Protected Sections. Il suffit de faire croire au logiciel, qu'il y a un serial valide :).
Souvenez-vous, le loader d'ASProtect fait des appels aux fonctions de vérification du serial, dans l'exécutable unpacké, avant de le lancer.

Il y a d'abord appel à cette fonction par le loader d'ASProtect :





Cette fonction détermine la présence d'un fichier "licence", appelé ic.key
Soit vous inversez le saut en 00401209 (il faut sauter), soit vous créez un fichier ic.key (chez moi, il est créé dans D:\Documents and Settings\All Users\Application Data\Icon Constructor 3).

Ensuite, le loader d'ASProtect appelle cette fonction :



Elle appelle les fonctions, qui font le hash md5 du serial (contenu dans le fichier ic.key) et le comparent à la base de hashs md5 de serials valides.

Il suffit d'inverser ce saut (il ne faut pas sauter), pour décoder les bytes des Protected Sections et avoir ainsi une version complètement débridée :).

Voici ce que deviennent les Protected Sections au niveau :
- de l'affichage du Nag



- de l'affichage de l'état enregistré dans le About



- de l'insertion de Watermark :



Si vous voulez étudier plus précisemment comment les Protected Sections fonctionnent, vous pouvez aussi utiliser un serial valide :
NC3-9T7TK-U7B7U-XXV5C-77HJN-HSM9H

Merci VDOWN :).

Conclusion : Pour vraiment avoir des Protected Sections efficaces, il faut :
- les affecter à des fonctions vitales
- utiliser le schéma d'enregistrement d'ASProtect et non un custom (fait par l'auteur du shareware)
Dans ce dernier cas, le décodage des bytes se fait à l'aide d'une clé dépendante du serial.
Un exemple de logiciel, où il faut un serial valide pour pouvoir récupérer les Protected Sections décodées (le schéma d'enregistrement est celui d'ASProtect), est : Advanced File Organizer v3.01


II) Manuel unpacking sur Flash Conv v1.3 :

Nothing found *
Scanning -> D:\Program Files\FlashConv\FlashConv\FlashConv.exe
File Type : Exe, Size : 459264 (070200h) Byte(s)
[!] ASProtect v2.x [unknown version] detected !
- Scan Took : 1.328 Seconds

A) Trouver l'OEP :

L'OEP de Flash Conv v1.3 est 0040E133 :

On reconnaît tout suite la présence des call ASProtect :



La routine comportant le jmp eax (eax = valeur de l'OEP) est similaire sans être identique :



Sans redévelopper cette partie, on peut trouver l'OEP, par :

- Utilisation des exceptions mises en place par les SEHs
Comme vous pouvez le constater, le nombre de SEHs utilisé est réduit...
- Utilisation de la pile

- Utilisation les accès en écriture :

Le calcul et la correction des call ASProtect permettant le dernier accès en écriture sur la section .text, on peut s'en servir pour arriver à l'OEP.
On met donc un hardware breakpoint, on write et l'on breake jusqu'à ce soit patché en call aspr (ici, call 06970000).
On met ensuite un Set break-on-access sur cette section. Mais, c'est un deuxième Set break-on-access, qui nous amène à l'OEP.

B) Protections anti-dumping :
Advanced Import Protection v 1 :

Ici, il n'y a rien de particulier à ajouter par rapport à la cible précédente.
L'IAT commence en 00411014 et termine en 004119B8 et l'utilisation d'un Call-Fixer est toujours d'actualité :).



Vous remarquerez qu'il y a des valeurs inhabituelles pour une IAT (en bleu)...

C) Protections du shareware (en lui-même) :
1) Protection via les APIs ASProtect (license manager) :

Certaines protections peuvent être gérées par les APIs ASProtect. Celles-ci correspondent aux adresses encadrées en bleu.
Pourquoi ce terme d'API ?
Parce qu'elles sont incorporées dans l'IAT comme des APIs classiques et les appels se font de la même manière...

Ici, on distingue 4 APIs ASProtect.
Pour retrouver, leurs appels, il suffit d'utiliser la fonction Search for > All constants dans Ollydbg.



Un petit Ctrl+A permet de retrouver les appels :

- API ASProtect 1 (en 00411000),
DS:[00411000]=057ABDE0
Local call from 0040B201



- API ASProtect 2 (en 00411004) ,
DS:[00411004]=057AB97C
Local call from 004068F1




Cette API ASProtect retourne des informations sur l'enregistrement du logiciel, notamment le nom de l'utilisateur enregistré.
Si le logiciel n'est pas enregistré, cette API ne retourne aucune chaîne (pointeur)...

Ensuite, la routine, qui suit l'appel à cette API, détermine si un pointeur vers une chaîne a été renvoyé (le cmp eax, esi en 00406902).
Si un pointeur vers une chaîne (nom d'utilisateur) a été renvoyée, celle-ci est comparée à "Trial Version".
Le programme reteste à nouveau si un pointeur vers une chaîne a été renvoyé (le cmp eax, esi en 0040694E).
Enfin, la routine détermine si la chaîne en question est de taille non nulle.
Si ces quatre conditions sont respectées, le About affiche "Registered to:".
Si ce n'est pas le cas :



Vous remarquerez la présence d'une "Protected Section" (encadrée en vert).
Ca n'a aucun intérêt d'en mettre au niveau du About...
Un exemple de plus, où c'est mal implémenté ;).

- API ASProtect 3 (en 00411008) ,
DS:[00411008]=057ABAB8
Local call from 0040B38F



N'est pas appelée...

- API ASProtect 4 (en 0041100C),
DS:[0041100C]=057ABBF0
Local call from 0040B22C



N'est pas appelée...
Cette API est située juste après la 1ère API ASProtect...

C'est bien beau, mais comment se débarasser de ces APIs ASProtect (license manager) ?

Si vous laissez ces appels, vous vous doutez bien, que le logiciel va planter à un moment ; dans l'exécutable unpacké, le code correspondant à ces APIs ASProtect n'est plus en mémoire.

Plusieurs solutions s'offrent à vous.

a) Etudier les différentes APIs ASProtect en les implémentant dans un programme, spécialement conçu pour l'occasion.
Il faut juste disposer d'une license complète d'ASProtect 2...
C'est la meilleure solution. Elle permet de faire correspondre les différentes identifiants / signatures des APIs ASProtect.

b) Etudier les différentes APIs ASProtect dans la cible en question.

Pour cela, on étudie les arguments passés à l'API ASProtect, les valeurs de retour et ce que fait le programme de ces valeurs (éventuellement tracer l'API).
Par exemple, prenons l'exemple de l'API ASProtect 3 :



Lorsque l'on est au niveau du call 0040EBD8 en 0040B22C, on a comme registres :



Après exécution du call, on a :



Sous Ollydbg, les registres modifiées sont facilement repérables (en rouge).
Ici, la valeur de retour est stockée en eax (00000001).

Parmi les valeurs de retour (registres modifiés), il est important de vérifier si le programme les utilise par la suite ou si elles sont directement écrasées.
Dans ce dernier cas, il ne faut pas en tenir compte...
Il est important de vérifier toute autre modification (par exemple, une API ASProtect, qui stocke une valeur de retour dans la pile) et de surveiller l'état de la pile.

Cette API ASProtect peut donc être émulée comme ceci :



Il est important de corriger la pile, pour éviter tout décalage !!!

Il suffit alors de placer ce code à un endroit où il y a de la place et de modifier en conséquence l'adresse correspondante de l'API dans l'IAT...
Ici, cette API n' a pas beaucoup d'importance, puiqu'elle n'est pas appelée (on laisse par mesure de précaution) !

L'étude de ces APIs ASProtect peut être long et fastidieux, surtout quand c'est bien fait...
Mais, le point positif, c'est qu'une fois que cette étude a été faite, après c'est toujours la même chose pour les autres softs :).

c) Connaître quelqu'un qui a étudié ces APIs ASProtect (je sais, c'est de la triche :p)

On peut utiliser le merveilleux script de VolX (merci à MadMickael pou l'astuce et à VolX pour avoir étudié ces APIs).
Il nous retourne sur ce soft :

Log data :

GetModeInformation 00410030
GetRegistrationInformation 00410070
CheckKey 004100B0
GetKeyDate 004100C0

On trouve une description de ces APIs et leur implémentation dans le fichier d'aide d'ASProtect 2 (chapitre API description / API) :

- GetModeInformation Description : GetModeInformation - this function retrieves the information about currently working mode or any other installed and valid modes. If the function succeeds, the return value is TRUE. In case of incorrect parameters or external protection error, the function will fail and return FALSE.

- GetRegistrationInformation Description : GetRegistrationInformation - this function retrieves registration information of the choosen or currently working mode.

- CheckKey Description : CheckKey - checks the registration key for all implemented modes. This API function retrieves the pointer to the registration key and name. If the function succeeds, the return value is TRUE. If registration key is invalid or there is no valid mode for this key, the function will NOT fail and return FALSE. ModeStatus parameter - points to a TModeStatus structure, where the requested information is to be returned (no matter what function result is). If this parameter is NULL, CheckKey will not retrieve mode information.

- GetKeyDate Description : GetKeyExpirationDate - this function retrieves the creation date for registration key of the choosen or currently working mode. If the function succeeds, the return value is TRUE. If selected mode is not using activation keys or there is no registration key installed, the function will fail and return FALSE.


VolX a émulé ces APIs ASProtect de la sorte :

1ère API ASProtect (GetModeInformation)



2ème API ASProtect (GetRegistrationInformation)



Elle renvoie le nom de l'utilisateur enregistré (pointeur) ainsi qu'un serial (inutile ici, puisque sa présence n'est pas vérifiée par la suite).
Le script de VolX nous fournit même les quelques octets détruits ("Protected Section")...

3ème API ASProtect (CheckKey)



4ème API ASProtect (GetKeyDate)



Elle renvoie la date d'enregistrement (ici, le 1er Janvier 2007).

Après, c'est à vous d'adapter les valeurs à retourner (à émuler correctement les APIs ASProtect) selon le logiciel.
Et n'oubliez pas qu'il n'y a pas qu'une seule façon de résoudre un problème ;).
Donc, la façon dont VolX résoud les APIs ASProtect est une solution parmi tant d'autres...

2) Supprimer le watermark :

Lorsque l'on convertit une video .avi en flash .swf, on obtient alors un joli watermark sur la vidéo flash.
Mais, le plus marrant, c'est qu'il est dynamique et qu'il se déplace apparemment de manière aléatoire :p.

Tout d'abord, on va localiser ce watermark dans les ressources à l'aide de l'excellent plugin GODUP de GodFather+ (ça permet aussi de charger les signatures IDA dans Ollydbg ainsi que les *.map).

On regarde d'abord dans les ressources de FlashConv.exe, mais on ne trouve rien...
C'est à ce moment que l'on se souvient de "cette alerte" d'Ollydbg :



L'auteur a packé en plus de l'exécutable, 4 dlls à savoir :
- MediaLog.dll
- ExportRenderers.dll
- CommonDialogs.dll
- MediaEngine.dll

On fait un Memory map (Alt+M) pour localiser où sont chargées ces différentes .dll
Il ne reste plus qu'à faire un Go to à ces adresses :).

Finalement, on trouve le watermark dans les ressources de MediaEngine.dll :



On prend le numéro de la ressource en question et on convertit en hexadécimal, ce qui donne 6Dh.
Un click droit > Search for > All constants donne un seul résultat :



En remontant progressivement les appels,



on finit par arriver ici :



Il faut donc forcer le saut en 1000A279...

Rentrons à l'intérieur du call précédent :



Vous l'aurez remarqué, vous n'avez pas forcémment les mêmes adresses que moi. Ceci est dû aux relocations...
Si une .dll est déjà chargée à l'image base de défaut de notre .dll, le système va modifier l'image base de celle-ci et la charger ailleurs.
Ceci implique des modifications au niveau du code, etc...
Déjà rien que le fait de débugguer sous Ollydbg modifie les adresses de la .dll par rapport au fait de ne pas debugguer.

Comme les adresses peuvent varier à cause des relocations, comment pouvons-nous faire pour appliquer un patch ?
On pourrait inliner et utiliser du code relogeable, càd un code invariable / indépendant de sa localisation.

Mais, ici, on ne veut pas modifier la .dll sur le disque et encore moins la dumper (relocations à fixer,etc...).
On va donc récupérer l'image base de MediaEngine.dll via l'IAT de l'exécutable (c'est comparable au principe du call delta) :



Merci à TrapZero pour ce code à l'époque ;).

Où va-t-on intégrer ce code dans l'exécutable ?
Puisque l'intégration du watermark se fait à la conversion des fichiers, il suffit donc d'appliquer le patch avant.
On peut donc ajouter ce code, au niveau de la 1ère API ASProtect (que nous avons modifié), puisque celle-ci s'effectue au lancement du soft...


III) Perspectives et conclusion :
A) Perspectives :
1) Advanced Import Protection v 2 ("Import Elimination") :

Vous l'avez peut-être déjà remarqué, l'IAT de beaucoup de cibles protégées par ASProtect 2 est partiellement détruite...
Comment cela marche-t-il ?

Les APIs détruites ne sont bien évidemment pas appelées directement. Elles sont résolues (émulées en partie), puis appelées via les call ASProtect.

Comment peut-on résoudre ceci ?
Des unpackers comme Stripper contourne le problème en construisant une nouvelle IAT.
On peut procéder aussi en ajoutant les APIs manquantes (peu importe l'ordre des APIs) au niveau des pointeurs invalides, au fur et à mesure que l'on reconstruit les call ASProtect. Ensuite, on remet l'ordre dans les APIs (séparées par librairie), comme on l'aurait fait avec l'Import Elimination d'Armadillo...

Personnellement, je trouve ces méthodes assez crades, surtout quand on peut obtenir une IAT impeccable :).

Pour illustrer mon propos, je vais prendre l'exemple d'Icon to Any v3.02 (20 Fév. 2007).
L'IAT ressemble alors à ça :



Comme on peut le voir, ASProtect 2 a volontairement effacé / n'a pas résolu les différents imports à beaucoup d'adresses.
Ceci est possible car les call [API] sont / jmp [API] du code sont détournés en call ASProtect (routine chargée de calculer l'adresse de ces imports).

On pourrait utiliser la méthode du call-fixer, qui tout en reconstruisant les call ASProtect, récupère l'adresse de l'API et la met dans l'IAT (dans l'ordre d'appel des call ASProtect), sauf bien-sûr si elle est déjà présente :).
Donc, pour résumer, on peut utiliser la même méthode que celle de l'Import Elimination d'Armadillo, mais c'est vraiment crade , je trouve...
Je sens que l'on va me prendre pour un maniaque :p. J'étais persuadé que l'on pouvait récupérer une IAT toute propre (celle d'origine) sans trop de difficultés :).

On pose donc un Hardware bp, on Write en 004E61A8 (API résolue) et on tombe là au 6ème break :



En traçant légèrement, on arrive à un ret puis on arrive ici :



On arrive là après le RETN 10 (ensuite, on saute) :



Il ne reste plus qu'à tracer légèrement jusqu'à un call :



On rentre à l'intérieur :



Cette dernière condition détermine si une API doit être résolue dans l'IAT ou non :).
Pour une API résolue, le saut en 00B03BC0 vers 00B03C20 n'est pas effectué (ZF=1).
Inverser juste le flag pour résoudre toutes les APIs ne suffit évidemment pas.
En effet, on obtient une erreur du style :



Il suffit d'étudier le code suivant :



La routine qui déplace dans un buffer la chaîne ascii cryptée de l'API est celle-ci :



En regardant à l'adresse (registre esi), on tombe sur ça :



On a donc le nom de la dll (import) suivi des asciis cryptés, séparés par un 0.
Dans notre cas, le nom de la 1ère fonction commence en 00B1B851 (elle n'est pas résolue dans l'IAT).
La 2ème fonction commence en 00B1B869 (elle est résolue dans l'IAT -> API DeleteCriticalSection).

La routine, qui décrypte la chaîne est celle-ci :



La clé est situé à l'adresse edx :



Le décryptage se fait en boucle via cette routine :



Maintenant, il reste à trouver la clé pour les imports non résolus de l'IAT. En fait, ils sont résolus plus tard.
Il suffit donc de mettre un Hardware bp, on Access en 00B1B851.
On obtient alors la clé (toujours dans ces mêmes routines) :



C'est là que l'on s'aperçoit qu'elle chevauche la clé précédente ;).

Il ne reste plus qu'à faire un script, chargée d'inverser le flag en 00B03BC0 et de faire correspondre la clé suivant la fonction importée en :



En 00B03BFA, il suffit de soustraire la valeur 0xA à ecx :)

Le script minimal pour ODbgScript :


bphws 00B03BC0, "x"
@start:
run

@loop:
cmp !ZF, 1
je @start
mov !ZF, 1
bphws 00B03BFA, "x"
run
bphwc 00B03BFA
sub ecx, 0A
run
jmp @loop

On obtient malgré un crash (l'application se lance), une IAT impeccable très rapidement :) :



C'est quand même mieux, nan ?

Le crash est dû à un leurre d'ASProtect, qui a remplacé l'API GetProcAddress par d'autres APIs à 2 endroits :



En faisant, ces deux modifications, il n'y a plus de problème au lancement du soft...

On peut retoucher ce script pour en avoir un, générique (Aspr2_IAT_rebuilder.txt) :

var address
var add1
var add2
var add3
var value
var kernel32
var shell32
var flag
var IAT_start
var IAT_end



ask "Enter address of {mov dword ptr:[edx], eax} :"
cmp $RESULT, 0
je @err
mov address,$RESULT
gpa "GetProcAddress", "kernel32.dll"
mov value, $RESULT
mov kernel32, 07C800000
mov shell32, 07C9D0000
mov flag, 0

mov add1, address
sub add1, 059
mov add2, address
sub add2, 01F
mov add3, address
add add3, 02E9
add address, 02

bphws add1, "x"
bphws add3, "x"

@start:
run

@loop:
cmp eip, add3
je @end
cmp !ZF, 1
je @start
mov !ZF, 1
bphws add2, "x"
run
bphwc add2
sub ecx, 0A
bphws address, "x"
run
bphwc address
cmp flag, 0
je @IAT_start_save
@fix_gpa:
cmp [edx-4], eax
jne @continue
cmp eax, kernel32
jbe @continue
cmp eax, shell32
jae @continue
mov [edx], value
@continue:
run
jmp @loop

@IAT_start_save:
mov IAT_start, edx
mov flag, 1
jmp @fix_gpa

@end:
bphwc add1
bphwc add3

mov IAT_end, edx
add IAT_end, 04
eval "L'IAT commence en {IAT_start} !"
msg $RESULT
eval "L'IAT termine en {IAT_end} !"
msg $RESULT
Il suffit de lancer une fois l'application, de noter cette adresse :



et de la renseigner au script lorsque l'on relance l'application. Il reconstruit alors l'IAT.
Il corrige également l'IAT au niveau des APIs kernel32 "dédoublées" par l'API GetProcAddress (émulée par ASProtect).
Il vous faudra corriger les variables kernel32 & shell32, qui correspondent aux adresses où sont chargées ces .dll (adresses variant suivant l'OS).

Après, il suffit de combiner l'action d'un call-fixer (assemblé ou sous forme de script) à l'OEP et l'affaire est dans le sac...

2) Schéma d'enregistrement d'ASProtect 2 :

Comment savoir si le logiciel en question utilise le schéma d'enregistrement d'ASProtect ou un schéma custom (celui de l'auteur du shareware) ?
Quelques indices peuvent orienter la réponse...
- la présence d'un Registration / Hardware ID
- la présence d'un fenêtre avec un champ "serial" de très grande longueur, indicatif de la présence d'algorithmes de cryptage (ex: serials de plus 100 caractères) :



- le plus souvent l'absence de message d'indicatif de serials absents ou serials erronés.
(La plupart de temps, l'application demande d'être relancée pour effectuer la vérification du serial au démerrage).

Pour être sûr à 100% que le schéma d'enregistrement est celui d'ASProtect, il faut voir si la vérification du serial se fait dans la .dll d'ASProtect.
Si le schéma est custom (algorithme développé par l'auteur du shareware), la vérification se fait dans le fichier unpacké.
Ex : Icon Constructor 3.

ASProtect utilise notamment l'algorithme RSA avec trois niveaux de protections (RSA-512, RSA-768 & RSA-1024).

Est-ce que ASProtect est keygennable ?
Contrairement à ce que l'on pourrait penser, la réponse est positive. On la nuancera par après...
Quelques exemples où ASProtect a été keygenné :
- ASProtect 1.35 build 06.26 par pDriLl[TMG] (protégé par ASProtect SKE)
- ASProtect SKE 2.2 build 04.25 par Syndrom/ECLiPSE
- ASProtect SKE 2.41 build 02.26 Beta par REVENGE Crew
- BadCopy Pro 4.10 par WoKa/FFF
etc...

SKE = Short Key Edition

"Il est à noter que les programmes protégés par la version SKE peuvent être keygenés, et pas ceux protégés par la version normale" dixit jB.
"Et pour la version normale, la dernière cassable, c'est la 1.1b ou 1.2b". Merci à jB pour les informations :).

Comment est-ce possible avec une telle taille de clés ?
Ils utilisent des failles, notamment sur le générateur de nombres pseudo-aléatoires (PRNG).
A ce sujet, on peut trouver :

Pour le keygenning d'ASProtect 1.x :
How break RSA-1024 on Asprotect 1.0/1.1/1.11c, by Amenesia//TKM!
Cryptographie et reverse engineering en environnement Win32 par Kostya Kortchinsky
http://www.woodmann.com/forum/archive/index.php/t-2013.html

Pour le keygenning d'ASProtect 2 (SKE) :
Attack on Asprotect SKE Activation Key par shooo (il a notamment keygenné Themida :) )

3) La .dll d'ASProtect 2 :

Pour étudier en profondeur ASProtect 2 (les différentes protections, son keygenning notamment), il n'y a rien de mieux que d'unpacker et fixer sa dll.
Je ne peux que vous conseiller de lire cette référence (anciennes versions d'ASProtect) :
AsProtect - A reverse engineering approach par crUsAdEr

Pour ASProtect 2, vous pouvez toujours lire ces 2 tutoriaux de Deroko/ARTeam (il a dévellopé un outil, qui permet de dumper cette dll) :
ASProtect 2.3 SKE (Unpacking Approach)
ASProtect 2.3 SKE (Virtual Machine Analysis)

B) Conclusion & remerciements :

ASProtect reste une protection intéressante, même si elle est dépassée par d'autres protecteurs en terme de protection (anti-debugging, junk code, etc...).
On aurait pû croire que le rachat de la société par StarForce aurait pimenté ASProtect, mais il ne s'agit pour l'instant, que d'une opération financière sans répercution au niveau du protector...


All the rights for the ASPack Software project are assigned to the StarForce Technologies

Dear customer,

We inform you that all the rights for the ASPack Software project are assigned to the StarForce Technologies company from 1st August 2007.

The acquisition of the rights for ASPack Software product line was planned in the StarForce’s development strategy for 2007-2008. This acquisition is aimed for the StarForce product line’s extention and strengthening of the company’s position in the copy protection market. StarForce informs that there won’t be any changes in the price policy in the future. Using it’s long-term experience, StarForce intends to develop and support the ASPack Software products. More particular information about the plans and prospects for this project will be published on the StarForce official site by the end of August 2007.

About StarForce

The StarForce Company is the expert in software and digital content protection against copying and cracking. StarForce is one of the three leaders in the world copy protection market and is the leading developer of protection tools on Russian multimedia market, already for many years. Integration of StarForce solutions into any software products and digital content allows applying various schemes of distribution and its management. StarForce provides a wide variety of reliable tools for protection against home copying, emulation and professional cracking. The particular specialization of StarForce ensures the development of technologically perfect products, while guaranteeing high reliability and quality level.

The company successfully works on business software and mobile content market since 2006.

http://www.aspack.com/news.aspx?Id=4


Ce tutorial est loin d'être complet et ne constitue qu'une introduction à ASProtect 2.
Pour être exhaustif, il aurait fallu aborder en détail : la protection sur l'OEP, l'inline patching, le "stolen code" et la VM, l'unpacking de la dll d'ASProtect et le keygenning, la protection des ressources, l'algorithme de compression, etc... sans compter la possibilité de "vérifications de l'enveloppe" par l'application ansi que divers tricks customs. En effet, comme pour Armadillo, il existe des custom builds d'ASProtect, qui auront forcémment des protections supplémentaires par rapport à la version normale...
Peut-être dans un autre tutorial :p (après, il faut trouver une cible en rapport)...

Après, tout membre du forum peut toujours faire une requête pour détailler un de ces aspects de la protection sur une cible qu'il connaît :).
Vous pouvez aussi me signaler toute erreur dans ce tutorial.

En conclusion, ASProtect peut-être une bonne protection à condition d'utiliser le schéma d'enregistrement d'ASProtect associé à des Protected Sections sur des fonctions vitales du soft, la protection sur l'OEP, le stolen code sur des fonctions sensibles, la protection sur les APIs (mais dans une mondre mesure). Si l'on utilise les APIs ASProtect, il faut qu'elles soient suffisamment liées à certaines fonctions du programme. Les autres options de protection d'ASProtect 2 (anti-debugging / checksum / protection sur les ressources) ne sont qu'un plus, qui ne fait pas vraiment pencher la balance vers un programme plus sûr...

Remerciements :

Remerciements à : Christal et tous ses compères, R!SC, +Frog's Print & +Spath, ARTeam, FRET et bien évidemment, tous les membres de FFF...
Merci à tous ceux, qui contribuent activement au cracking
Merci aux lecteurs, qui auront eu la patience d'aller jusqu'au bout :p

Un petit coucou à Baboon, Kaine, Kirjo, mars, Spoke, les administrateurs / modérateur du forum de deez, tous les membres du forum, tous ceux que j'apprécie, qu'ils soient crackeurs / reverseurs ou non :).


Voilà c'est fini...



"There is a crack, a crack in everything... That's how the light gets in."

uLysse_31