VBox 4.2 - Ready Made Protection
Bye bye VBox !Introduction
Je vais ici expliquer comment contrer VBox 4.20 à jamais. Pour ceux qui ne connaissent pas VBox, c'est une Ready Made protection écrite par WeiJunLi utilisé principalement par Symantec, Adobe et autres. Depuis sa création, VBox à fait beaucoups de progrès. Voici quelques une des caractéristiques de la protection :1. Vboxt420.DLL et VBoxz420.DLL crypté.
2. CRC Check de la DLL par le programme protégé.
3. Anti-Sice et Anti-WDasm.
4. ...Le point 2 est tout particulièrement intéressant car il empèche de modifier la DLL. Il faut donc modifier chaque programme protégé séparemment. Ceci est la principale différence avec la version précédente et va nous compliquer un peu les choses. La méthode que je vais exposée ici ne s'adresse pas aux débutant car je vais toucher au coeur du système. En clair, on va appliquer notre patch non pas aux programme protégé, mais à Kernel32.DLL et User32.DLL. Pour les personnes qui aimeraient rester prudente, on peut remplacer très facilement les modifications disk par une modification mémoire aux démarrage de Windows par exemple, il faudra simplement écrire le Memory Patch que je laisse en exercice :).
Outils nécessaires
Windows 98 SE Fr ( Je le note pour des raisons d'addresses qui risquent d'être différentes avec d'autres versions )
SofICE v4.0
HView v6.15
TurboDebugger v5
Target
Deep Paint 1.0c (by Right Hemisphere Ltd). http://www.rightemisphere.com
Explications
1. L'Anti-SiceExodus:01E768F0 55 push ebp
:01E768F1 56 push esi
:01E768F2 57 push edi
:01E768F3 8BEC mov ebp,esp
:01E768F5 B989179000 mov ecx,00901789
:01E768FA BECE517400 mov esi,007451CE
:01E768FF 33F1 xor esi,ecx ;ESI = 901789 XOR 7451CE = E44647
:01E76901 B8C4320500 mov eax,000532C4
:01E76906 03C1 add eax,ecx ;EAX = 901789 + 532C4 = 954A4D
:01E76908 33FF xor edi,edi
:01E7690A 97 xchg edi,eax ;EDI = EAX = 954A4D
:01E7690B 3BC1 cmp eax,ecx ;EAX = 0 != ECX = 901789 => Toujours différent !
:01E7690D 7501 jne 01E76910 ;Ce jne est donc en réalité un jump inconditionnel
:01E7690F 8B
:01E76910 CC int 3 ;Interruption 3 avec DI = 4A4D ( Magic Number 1 )
; et SI = 4647 ( Magic Number 2 )
:01E76911 8BC1 mov eax,ecx
:01E76913 5F pop edi
:01E76914 5E pop esi
:01E76915 5D pop ebp
:01E76916 C3 ret:0700F795 FF65FC jmp [ebp-04]
:0700F79833C0 xor eax,eax ;On revient iciDe manière à ne pas pouvoir modifier directement dans la DLL cette portion de code est décrypté en mémoire dans de l'espace alloué avec VirtualAlloc, puis, après exécution, effacée avec VirtualFree. On ne peut donc pas mettre de BPM en 01E76910 car cette addresse change tout le temps. La solution est donc de mettre le BPM en 0700F795. Maintenant que nous avons cela, on peut retourner sous Sice, et mettre un BPM 0700F795 X après le lancement avec le Symbol Loader. Je rapelle que le BPM ... X permet de ne pas modifier le code en mémoire et ainsi éviter des erreurs aux cas d'un CRC Check par exemple. Lorsqu'on breakera, il suffira dès lors de tracé jusqu'à l'Int 3 et de remplacer SI ou DI par une autre valeur avant son exécution.
2. La DialogBox
Maintenant, nous nous retrouvons devant le même shéma de protection que les anciennes version de VBox. Je réexplique rapidement. L'appuis sur la touche Try renvois 0 dans EAX. Ensuite, un peu après la DialogBox, un appel à RaiseException affiche les messages d'erreurs liés aux temps, etc.. Donc, le patch consistera à forcé le renvois de 0 dans EAX par la DialogBox et à ne pas exécuté RaiseException tout en faisant bien garde à rétablir la pile. Tout ceci peut être fait à l'aide de Softice très simplement.
0177:080078EC 8B0D68C90D08 MOV ECX,[080DC968]
0177:080078F2 A1D03E0D08 MOV EAX,[080D3ED0]
0177:080078F7 57 PUSH EDI
0177:080078F8 68B07E0008 PUSH 08007EB0
0177:080078FD 8B513C MOV EDX,[ECX+3C]
0177:08007900 8B4808 MOV ECX,[EAX+08]
0177:08007903 52 PUSH EDX
0177:08007904 68CB000000 PUSH 000000CB
0177:08007909 51 PUSH ECX
0177:0800790A FF1560670E08 CALL [USER32!DialogBoxParamA]Après l'appel à DialogBoxParamA on fait un R EAX 0 pour mettre EAX à 0. On trace jusqu'au RaiseException situé ici :
0177:070570D1 52 PUSH EDX
0177:070570D2 8B54240C MOV EDX,[ESP+0C]
0177:070570D6 50 PUSH EAX
0177:070570D7 51 PUSH ECX
0177:070570D8 52 PUSH EDX
0177:070570D9 FF15585A0807 CALL [KERNEL32!RaiseException]Arrivé en :070570D9 il suffit de faire R EIP EIP+6 pour éviter ce call et R ESP ESP+10 pour rétablir la pile ( 4 Paramètres ). Maintenant que nous savons cela, nous pouvons commencer le patch.
3. Idée Intuitive
Comme je disais en introduction, nous allons appliquer notre patch non pas sur l'éxécutable lui-même car alors il faudrait recommencer à chaque fois, ni sur la DLL à cause du CRC-Check mais nous allons dévier l'appel aux Fonctions API concernée. Je rappelle que ces fonctions sont DialogBoxParamA de User32.DLL et RaiseException de Kernel32.DLL. En gros, il suffira de vérifié si c'est VBox qui appel la fonction, et si c'est le cas on applique les modification sinon on donne la main à la fonction original.
4. RaiseException - Kernel32.DLL
Commencons par le plus facile. Nous devons d'abord trouver de la place libre que nous trouvons facilement à la fin du fichier ( dans Kernel32.DLL ) :
:BFFE4800 0000 add [eax],al @Offset 00074800 in File:Kernel32.DLL
...
:BFFE4820 0000 add [eax],alEnsuite, nous allons modifier l'Export Table pour que lors de l'appel à la fonction, on passe d'abord par notre fonction. Pour cela, on désassemble Kernel32.DLL et on reguarde l'addresse de la fonction :
Exported fn(): RaiseException - Ord:0273h
:BFFA0ACB 9C pushfd @Offset 00030ACB in File:Kernel32.DLLMaintenant, avec HView on recherche CB 0A 03 00 dans Kernel32.DLL et on le remplace par 00 48 07 00. On rajoute enfin notre fonction:
.BFFE4800: 813C24DF700507 cmp d,[esp],0070570DF ;Vérifie si on vient de VBox
.BFFE4807: 7405 je .0BFFE480E ;Si oui, on saute
.BFFE4809: E9BDC2FBFF jmp .0BFFA0ACB ;sinon, Jmp RaiseException
.BFFE480E: 83C414 add esp,014 ;On retablit la pile
.BFFE4811: FF6424EC jmp d,[esp][-0014] ;et on retourne dans VBox5. DialogBoxParamA - User32.DLL
Maintenant, nous allons nous attaquer au gros morceau. Nous allons, comme pour Kernel32.DLL, dévier grace à l'Export Table DialogBoxParamA vers notre fonction que nous écriverons à la fin du fichier User32.DLL. Il nous faudra aussi 2 DWord où sauveguarder Adresse de Retour ainsi que l'Adresse de la Dialog Proc. Pour les 2 DWord, nous avons le champs libre dans la section .DATA en 0BFF5D000 et 0BFF5D004.
Exported fn(): DialogBoxParamA - Ord:0091h
:BFF52FD5 B12E mov cl, 2E @Offset 00002FD5 in File:User32.DLL:BFF605D0 0000 add [eax],al @Offset 000105D0 in File:User32.DLL
...Il faut donc rechercher et remplacer D52F0000 par D0050100 dans l'Export Table. Ensuite on écris notre fonction :
:BFF605D0 51 push ecx ;Sauve le registre
:BFF605D1 8B4C2404 mov ecx, dword ptr [esp+04] ;Récupère l'Adresse de Ret
:BFF605D5 890D00D0F5BF mov dword ptr [BFF5D000], ecx ;Sauve l'AddDeRet
:BFF605DB 81398B0D48C9 cmp dword ptr [ecx], C9480D8B ;Reguarde si on viens de VBox
:BFF605E1 7512 jne BFF605F5 ;Sinon on saute
:BFF605E3 8B4C2414 mov ecx, dword ptr [esp+14] ;Si oui, on récupère la WinProcAdresse
:BFF605E7 890D04D0F5BF mov dword ptr [BFF5D004], ecx ;On la sauve
:BFF605ED C74424141906F6BF mov [esp+14], BFF60619 ;Et on la remplace par notre Proc* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:BFF605E1(C)
|
:BFF605F5 59 pop ecx ;On restaure le registre
:BFF605F6 83C404 add esp, 00000004 ;
:BFF605F9 E8D729FFFF call BFF52FD5 ;DialogBoxParamA
:BFF605FE 83EC04 sub esp, 00000004 ;
:BFF60601 51 push ecx ;On sauve le registre
:BFF60602 8B0D00D0F5BF mov ecx, dword ptr [BFF5D000] ;On récupère l'AddDeRet
:BFF60608 894C2404 mov dword ptr [esp+04], ecx ;On la remet sur la pile
:BFF6060C 81398B0D48C9 cmp dword ptr [ecx], C9480D8B ;On reguarde si on vient de VBox
:BFF60612 7502 jne BFF60616 ;Sinon on saute
:BFF60614 33C0 xor eax, eax ;Si oui, EAX == 0* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:BFF60612(C)
|
:BFF60616 59 pop ecx ;On restaure le registre
:BFF60617 C3 ret ;On redonne la main au programme
:BFF60618 90 nop ;DialogProc
:BFF60619 837C240818 cmp dword ptr [esp+08], 00018 ;Chargement de la DialogBox terminée ?
:BFF6061E 7510 jne BFF60630 ;Sinon on saute
:BFF60620 C744240811010000 mov [esp+08], 00000111 ;Si oui, on injecte le message
;WM_COMMAND avec comme paramètre
:BFF60628 C744240C95040000 mov [esp+0C], 00000495 ;l'ID du bouton EXIT* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:BFF6061E(C)
|
:BFF60630 FF2504D0F5BF jmp dword ptr [BFF5D004] ;On redonne la main à la DialogProcMaintenant que les modifications ont été faites, vous devez quittez Windows ( Redémarrage en mode MS-Dos ) et remplacer les Kernel32.DLL et User32.DLL par les fichiers modifiés.
Je ne sais pas si ce crack fonctionnera pour tout les programmes VBoxés. Cependant, rien n'empèche à ce cours d'évoluer et donc, si il existe des erreurs, ou si des optimisations peuvent arriver par la suite, je les rajouterai avec grand plaisir. De plus, les seules modifications qui pourraient, à mon avis, arriver serait le moyen de savoir si on vient bien de VBox ce qui est loin d'être la plus grosse difficulté. Je terminerai par dire que même si l'API Spoofing est une technique très intéressante, je ne vous conseille pas de modifier Kernel32.DLL comme je le fait ici pour toute les protections existantes sans quoi vous risqué de gros ralentissement. Sur ce, je vous laisse et espère vous avoir appris quelquechose.GreetzRem : Ce crack n'a été utilisé qu'avec DeepPaint. Car il semble qu'il y ai une différence de version de VBox entre celui fourni avec DeepPaint et GoLive.. et je n'ai que ceux là. Si vous pourriez tester cette métode et me tenir au courant, j'aimerais vérifié au plus vite ! Merci.
Je voudrais saluer principalement Christal et toutes les personnes motivées de la scène francophone qui ne se prennent pas la tête !