Défi Main Rouge
Avril 2000
By Christal
Avant propos :
Ce défi, original en soit même, pose un petit problème.
Comme il s’agit de transformer une version FreeWare en version ShareWare, le code doit, par la force des choses, être rajouté là où c’est possible.
L’un des inconvénients majeurs de cette obligation, réside dans le fait que dès que vous tenez un bout de fil du schéma de protection, toute la pelote vient avec...
Pour embrouiller les choses, j’ai essayé d’avoir recours à quelques subterfuges, sans être certain que vous en serez dupes, mais en faisant aussi en sortes que les différents éléments d’une routine soient rapides à trouver dans l’idée de « récompenser » vos recherches et rendre la suite stimulante. J’aurais pu m’amuser à mieux cacher mes petites chausse-trappes, mais ça n’aurais fait que retarder le moment de la mise à mort...
|
Let’s Go On :
Il n’y a que deux boites de messages (ce sont des points d’entrées trop faciles),
et toute « faute » est sanctionnée par la fermeture immédiate de la fenêtre en
cours (ExitProcess ou EndDialog suivant le cas). Pas très élégant, mais fichtrement désagréable!
A savoir, 100 pour le champ Name, 66 pour le champ Serial, et 1000 pour le bouton
(soit respectivement 64h, 42h et 03E8h).
Sous ExeEscope, rien n’est plus simple que de les bidouiller, et par exemple de
griser (Grayed) l’Item « Slide Show). * Possible Ref to Menu: BROWSERMENU, Item: "A propos..."
|
:00421B99 3DBF000000 cmp eax, 000000BF
:00421B9E 0F84F6010000 je 00421D9A
:00421BA4 31C0 xor eax, eax
:00421BA6 C3 ret
> ou en mettant la main directement sur la DialogBox :004010F8 51 PUSH ECX :004010F9 52 PUSH EDX :004010FA 6A00 PUSH 00 > dwInitParam :004010FC 68D8104000 PUSH 004010D8 > adresse DialogProc :00401101 50 PUSH EAX > hWndParent :00401102 687C104C00 PUSH 004C107C > template :00401107 6A00 PUSH 00 :00401109 2EFF15D0F84B00 CALL CS:[KERNEL32!GetModuleHandleA] :00401110 50 PUSH EAX > hInstance :00401111 2EFF159CF64B00 CALL CS:[USER32!DialogBoxParamA] :00401118 5A POP EDX :00401119 59 POP ECX :0040111A C3 RET int DialogBoxParam(
La gestion des messages envoyés par la DialogBox va être traitée
à partir de l’adresse 004010D8.
Ce qui donne, après modification de l'adresse de la DialogBoxProcédure, :004010FC 68E4025100 PUSH 005102E4 > vers ma nouvelle DialogProc :00401101 50 PUSH EAX :00401102 687C104C00 PUSH 004C107C pour arriver ici : :005102E4 55 PUSH EBP :005102E5 8BEC MOV EBP,ESP :005102E7 817D0C11010000 CMP DWORD PTR [EBP+0C],00000111 > WM_COMMAND :005102EE 7504 JNZ 005102F4 > message arrivé ? :005102F0 7418 JZ 0051030A > Oui -> traitement de l'événement :005102F2 EB12 JMP 00510306 > boucle :005102F4 837D0C10 CMP DWORD PTR [EBP+0C],10 > clic sur le X (fermeture) :005102F8 750C JNZ 00510306 > non -> boucle :005102FA 6A00 PUSH 00 > oui -> push hDlg :005102FC FF7508 PUSH DWORD PTR [EBP+08] > nResult :005102FF 2EFF15B8F64B00 CALL CS:[USER32!EndDialog] :00510306 C9 LEAVE :00510307 C21000 RET 0010
:0051030D 8B4510 MOV EAX,[EBP+10] > message dans EAX :00510310 663DE803 CMP AX,03E8 > est-ce un appui sur Register ? :00510314 7548 JNZ 0051035E > va voir si appui sur un autre bouton :00510316 BE44055100 MOV ESI,00510544 > buffet de stockage :0051031B 90 NOP > Oups! :0051031C 6A10 PUSH 10 > nb de caractères maxi :0051031E 56 PUSH ESI > buffet de stockage :0051031F 6A64 PUSH 64 > ID 1er champ :00510321 FF7508 PUSH DWORD PTR [EBP+08] > Handle DBox :00510324 2EFF15F4F64B00 CALL CS:[USER32!GetDlgItemTextA]
:00510331 6A10 PUSH 10 > et fait de même pour 2d champ :00510333 56 PUSH ESI :00510334 6A66 PUSH 66 > Identificateur 2d champ :00510336 FF7508 PUSH DWORD PTR [EBP+08] :00510339 2EFF15F4F64B00 CALL CS:[USER32!GetDlgItemTextA] :00510340 83C604 ADD ESI,04 > au moins 4 caractères entrés :00510343 803E00 CMP BYTE PTR [ESI],00 :00510346 7421 JZ 00510369 > EndDialog si pas le cas :00510348 803D4805510000 CMP BYTE PTR [00510548],00 :0051034F 7418 JZ 00510369 > idem champ 2 :00510351 EB28 JMP 0051037B > vers Générateur de code :00510353 E800000000 CALL 00510358 > code bidon pour :00510358 58 POP EAX > empoisonner les :00510359 A348055100 MOV [00510548],EAX > crackers :0051035E 663DE903 CMP AX,03E9 > test pour un éventuel 2d bouton :00510362 7405 JZ 00510369 > fermeture DialogProc :00510364 61 POPAD > quitte la procédure :00510365 C9 LEAVE :00510366 C21000 RET 0010 Avec juste les Call API à corriger et implanter le saut vers le générateur
de code. 000BEDE0 400D 0C00 0000 0000 4144 5641 5049 3332 @.......ADVAPI32 000BEDF0 2E64 6C6C 006F 6C65 3332 2E64 6C6C 0047 .dll.ole32.dll.G 000BEE00 4449 3332 2E64 6C6C 0053 4845 4C4C 3332 DI32.dll.SHELL32 000BEE10 2E64 6C6C 0055 5345 5233 322E 646C 6C00 .dll.USER32.dll. 000BEE20 4B45 524E 454C 3332 2E64 6C6C 0043 4F4D KERNEL32.dll.COM 000BEE30 4354 4C33 322E 646C 6C00 4D50 522E 646C CTL32.dll.MPR.dl 000BEE40 6C00 636F 6D64 6C67 3332 2E64 6C6C 0000 l.comdlg32.dll.. Puis d'implanter à une adresse disponible le nom des API à catcher: 001098D0 5F6C 6F70 656E 0000 0000 0000 0100 0000 _lopen.......... 001098E0 5368 656C 6C41 626F 7574 4100 0000 0000 ShellAbout ..... Voici la routine en question: :00510074 60 PUSHAD > sauvegarde des registres :00510075 BE09FA4B00 MOV ESI,004BFA09 > pousse l'@ de SHELL32.dll :0051007A BF800D4C00 MOV EDI,004C0D80 > pousse l'@ de ShellAboutA :0051007F E81B000000 CALL 0051009F > choppe l'adresse de l'API :00510084 A3700D4C00 MOV [004C0D70],EAX > et la stock en mémoire :00510089 BE20FA4B00 MOV ESI,004BFA20 > pousse l'@ de KERNEL32.dll :0051008E BF700D4C00 MOV EDI,004C0D70 > pousse l'@ de _lopen :00510093 E807000000 CALL 0051009F > choppe l'adresse de l'API :00510098 A3740D4C00 MOV [004C0D74],EAX > la stocke dans la Table (2) :0051009D EB12 JMP 005100B1 > et continue
:0051009F 56 PUSH ESI > pousse l'@ de la dll :005100A0 2EFF1518F94B00 CALL CS:[KERNEL32!LoadLibraryA] :005100A7 57 PUSH EDI > pousse le nom de l'API :005100A8 50 PUSH EAX > eax contient l'adresse de la dll :005100A9 2EFF15E0F84B00 CALL CS:[KERNEL32!GetProcAddress] :005100B0 C3 RET > eax contient l'adresse de l'API dans la dll Au retour du Call GetProcAdress, le registre EAX contiendra l’adresse de l’API désirée,
ou la valeur 00 si la fonction a échouée.
Il suffit de repérer dans cette liste, le nom de l’API que vous voulez appeler,
et de faire un :
Et de mettre EAX de coté dans la table (2) pour pouvoir réutiliser
l'adresse de l'API dans la DLL par la suite. :005100B1 61 POPAD > restaure la pile :005100B2 E800000000 CALL 005100B7 > place l'adresse 5100B7 sur la pile :005100B7 58 POP EAX > récupère cette adresse dans EAX :005100B8 2D9C224000 SUB EAX,0040229C > soustrait cette valeur à celle :005100BD 8B80AA224000 MOV EAX,[EAX+004022AA] > d'origine :005100C3 FFE0 JMP EAX Le Call 005100B7 va simplement servir à pousser sur la pile l'adresse qui
servirait de retour après un RET. Le POP EAX va récupérer cette adresse sur la pile, et le
SUB EAX, 0040229C va calculer la différence entre les adresses de cette routine, et celle que vous aviez
écrites au départ: :00401570 33C0 XOR EAX,EAX > mise à 0 des registres :00401572 33DB XOR EBX,EBX > qui vont être utilisés :00401574 33C9 XOR ECX,ECX > pour le cryptage :00401576 B901000000 MOV ECX,00000001 > initialisation de la clé de cryptage :0040157B 33D2 XOR EDX,EDX > mise à 0 du registre EDX :0040157D 8B45E4 MOV EAX,[0051053E]> place le nom dans EAX :00401580 8A18 MOV BL,[EAX] > met un caractère du nom dans BL :00401582 32D9 XOR BL,CL > crypte ce caractère :00401584 8818 MOV [EAX],BL > le place dans EAX :00401586 41 INC ECX > ajoute 1 à la clé de cryptage :00401587 40 INC EAX > caractère suivant :00401588 803800 CMP BYTE PTR [EAX],00 > reste-t-il des caractères? :0040158B 75F3 JNZ 00401580 > oui -> boucle :0040158D 33C0 XOR EAX,EAX > non, passe au sérial :0040158F 33DB XOR EBX,EBX > en mettant les :00401591 33C9 XOR ECX,ECX > registres à 0 :00401593 B90A000000 MOV ECX,0000000A > initialisation de la clé de cryptage :00401598 33D2 XOR EDX,EDX :0040159A 8B45F0 MOV EAX,[00510127]> place le sérial dans EAX :0040159D 8A18 MOV BL,[EAX] > 1 caractère du sérial dans BL :0040159F 32D9 XOR BL,CL > crypte ce caractère :004015A1 8818 MOV [EAX],BL > le place dans EAX :004015A3 41 INC ECX > ajoute 1 à la clé de cryptage :004015A4 40 INC EAX > caractère suivant :004015A5 803800 CMP BYTE PTR [EAX],00 > encore des caractères ? :004015A8 75F3 JNZ 0040159D > oui -> boucle :004015AA 8B45E4 MOV EAX,[EBP-1C] > place le nom crypté dans EAX :004015AD 8B55F0 MOV EDX,[EBP-10] > place le sérial crypté dans EDX :004015B0 33C9 XOR ECX,ECX > ECX mis à 00 :004015B2 8A18 MOV BL,[EAX] > 1 caractère du nom dans BL :004015B4 8A0A MOV CL,[EDX] > 1 caractère du sérial dans CL :004015B6 3AD9 CMP BL,CL > compare ces 2 caractères :004015B8 7509 JNZ 004015C3 > si <> saute en EndDialog :004015BA 40 INC EAX > caract suivant du nom :004015BB 42 INC EDX > caract suivant du sérial :004015BC 803800 CMP BYTE PTR [EAX],00 > encore des caractères pour le nom ? :004015BF 75EF JNZ 004015B0 > oui -> boucle Analysons un peu ces lignes: :00510420 803800 CMP BYTE PTR [EAX],00 :00510423 75EB JNZ 00510510 > oui -> boucle :00510425 B8D0D71000 MOV EAX,0010D7D0 > pointeur :0051042A 40 INC EAX > pour ne pas mettre :0051042B 48 DEC EAX > de NOP, trop :0051042C 40 INC EAX > rapide à voir :0051042D 48 DEC EAX :0051042E C6051009510036 MOV BYTE PTR [00510910],36 > Flag UEnregistré :00510435 E883000000 CALL 005104BD > enable menu Item :0051043A E846000000 CALL 00510485 > modifie la KeyFile :0051043F E925FFFFFF JMP 00510369 Le Call qui s’occupe de modifier la KeyFile va réécrire celle ci en utilisant le flag qui a été mis à 36 (caractère ASCII du chiffre « 6 »). :00510486 C7805030400076696577MOV DWORD PTR [EAX+00403050],77656976 = view :00510490 66C7804D304000786E MOV WORD PTR [EAX+0040304D],6E78 = xn EAX joue le rôle de pointeur pour permettre au programme de trouver les adresses des différents PUSH. Ainsi je me réservais la possibilité de déplacer une procédure entière en ayant juste à modifier le pointeur. :00510499 8D8850304000 LEA ECX,[EAX+00403050] > eax est le pointeur :0051049F 8D904D304000 LEA EDX,[EAX+0040304D] :005104A5 8DB020314000 LEA ESI,[EAX+00403120] :005104AB 8DB89E304000 LEA EDI,[EAX+0040309E] :005104B1 57 PUSH EDI > Path FileName :005104B2 56 PUSH ESI > Buffet :005104B3 52 PUSH EDX > Key (xn) :005104B4 51 PUSH ECX > Section (view) :005104B5 2EFF15A0F94B00 CALL CS:[KERNEL32!WritePrivateProfileStringA] Je reviendrais plus tard sur l’activation de l’Item « Slide Show ».
lpFileName est le Path pour un fichier bidon nxview.dll qui va être utilisé pour lire ou écrire deux types d’informations, dont le statut utilisateur. En utilisant un éditeur hexadécimal, vous pourrez trouver: 0010A020 0000 0000 0041 4244 3547 3852 3144 3548 .....ABD5G8R1D5H 0010A030 3135 3446 3435 4434 4635 3447 4834 4831 154F45D4F54GH4H1 0010A040 5744 3534 4635 3447 4831 3346 3138 3751 WD54F54GH13F187Q 0010A050 4552 5353 4B48 4A4B 4C4C 4735 4539 3656 ERSSKHJKLLG5E96V 0010A060 3254 3542 3251 4659 4851 5948 3800 633A 2T5B2QFYHQYH8.c: 0010A070 5C77 696E 646F 7773 5C73 7973 7465 6D5C \windows\system\ 0010A080 786E 7669 6577 2E64 6C6C 0063 3A5C 7769 xnview.dll.c:\wi lpString pointe vers un buffet dans lequel le caractère ASCII 35 (le chiffre
« 5 ») a été remplacé par le caractère 36 (le chiffre « 6 »). :005100B2 E830010000 CALL 005101E7 > test Shareware :005100B7 B814824300 MOV EAX,00438214 > pousse l’OEP :005100BC 90 NOP :005100BD 8DB8AA224000 LEA EDI,[EAX+004022AA] > code bidon :005100C3 FFE0 JMP EAX > et Zou !
:00510445 C7805030400076696577MOV DWORD PTR [EAX+00403050],77656976 = view :0051044F 8D8850304000 LEA ECX,[EAX+00403050] :00510455 66C7804D304000786E MOV WORD PTR [EAX+0040304D],6E78 = xn :0051045E 8D904D304000 LEA EDX,[EAX+0040304D] :00510464 8D9820314000 LEA EBX,[EAX+00403120] :0051046A 8DB09E304000 LEA ESI,[EAX+0040309E] :00510470 56 PUSH ESI > lpFileName :00510471 6A50 PUSH 50 > nSize :00510473 53 PUSH EBX > lpReturnedString :00510474 6A00 PUSH 00 > lpDefault :00510476 52 PUSH EDX > lpKeyName :00510477 51 PUSH ECX > lpAppName :00510478 2EFF15DCF84B00 CALL CS:[KERNEL32!GetPrivateProfileStringA
Puis par les tests d’usage : :005101F2 686E085100 PUSH 0051086E > pousse paramètre API :005101F7 803DF008510000 CMP BYTE PTR [005108F0],00 > 1er lancement de xnview? :005101FE 7507 JNZ 00510207 > si oui, création de xnview.dll :00510200 6825085100 PUSH 00510825 > sinon pousse le buffet :00510205 EB1D JMP 00510224 > et continue :00510207 803D1009510036 CMP BYTE PTR [00510910],36 > version enregistrée ? :0051020E 7425 JZ 00510235 > saute toutes les autres vérifications :00510210 FE0D1A095100 DEC BYTE PTR [0051091A] > Time Limit :00510216 803D1A09510041 CMP BYTE PTR [0051091A],41 > si = « A » :0051021D 741D JZ 0051023C > Out Of Time ! :0051021F 68F0085100 PUSH 005108F0 > réécrit la KeyFile :00510224 681D085100 PUSH 0051081D > pour enregistrer la :00510229 6820085100 PUSH 00510820 > modification apportée :0051022E 2EFF15A0F94B00 CALL CS:[KERNEL32!WritePrivateProfileStringA] Sur le même principe qu’en écriture, cette routine va lire le fichier
nxview.dll et l’écrire (adresse du Buffer) juste en dessous des codes de la KeyFile trouvables avec un éditeur
hexadécimal :0051023C C780D33040004F757420MOV DWORD PTR [EAX+004030D3],2074754F > Out :00510246 C780D73040006F662054MOV DWORD PTR [EAX+004030D7],5420666F > Of T :00510250 C780DB304000696D6521MOV DWORD PTR [EAX+004030DB],21656D69 > ime! :0051025A 8D88D3304000 LEA ECX,[EAX+004030D3] :00510260 8D901E304000 LEA EDX,[EAX+0040301E] :00510266 6A00 PUSH 00 > uType -> MB_OK :00510268 52 PUSH EDX > lpCaption :00510269 51 PUSH ECX > lpText :0051026A 6A00 PUSH 00 > hWnd :0051026C 2EFF1584F74B00 CALL CS:[USER32!MessageBoxA] :00510273 EB67 JMP 005102DC > vers ExitProcess
Version Shareware :00510276 8D880C304000 LEA ECX,[EAX+0040300C] :0051027C 8D901E304000 LEA EDX,[EAX+0040301E] :00510282 6A00 PUSH 00 > bouton OK :00510284 52 PUSH EDX > Version Shareware :00510285 51 PUSH ECX > Enregistrez-vous ! :00510286 6A00 PUSH 00 > handle :00510288 2EFF1584F74B00 CALL CS:[USER32!MessageBoxA] Le titre et le message de cette Box sont lisibles sous éditeur hexadécimal. :0051028F BE03055100 MOV ESI,00510503 > Adresse de Départ :00510294 BF40075100 MOV EDI,00510740 > Adresse d’arrivée :00510299 B941000000 MOV ECX,00000041 > Nb d’octets à déplacer :0051029E F3A4 REPZ MOVSB > Zou ! :005102A0 E89B040000 CALL 00510740 > appelle la routine déplacée :005102A5 40 INC EAX > +1 pour éviter un FFFFFFFF :005102A6 7513 JNZ 005102BB > SoftIce Detected? :005102A8 6A00 PUSH 00 > prépare Anti FrogsIce :005102AA 68F00A5100 PUSH 00510AF0 > \\.\FROGSICE :005102AF B830015100 MOV EAX,00510130 > charge _lopen :005102B4 FF10 CALL [EAX] > Call Kernel32!_lopen :005102B6 40 INC EAX > +1 pour éviter un FFFFFFFF :005102B7 7502 JNZ 005102BB > FrogsIce Detected :005102BB 68FB045100 PUSH 005104FB > pousse sur la pile l'@ d'ExitProcess :005102C0 C3 RET > et simule un retour sur Call Le Call 00510740 commence ainsi: :00510740 C705D00A51005C5C2E5CMOV DWORD PTR [00510AD0],5C2E5C5C :0051074A C705D40A510053494345MOV DWORD PTR [00510AD4],45434953 :00510754 C705F00A51005C5C2E5CMOV DWORD PTR [00510AF0],5C2E5C5C :0051075E C705F40A510046524F47MOV DWORD PTR [00510AF4],474F5246 :00510768 C705F80A510053494345MOV DWORD PTR [00510AF8],45434953 :00510772 C3 RET Après avoir écrit dynamiquement les chaînes qui vont être à trouver, le programme va s’occuper de les chercher. :005107D5 6A00 PUSH 00 > iReadWrite :005107D7 68D00A5100 PUSH 00510AD0 > lpPathName :005107DC B830015100 MOV EAX,00510130 > charge _lopen :005107E1 FF10 CALL [EAX] > appel _lopen :005107E3 C3 RET
La fonction _lopen ouvre un fichier existant et place un pointeur au début
de celui ci. Elle reste utilisée pour la compatibilité entre les versions 16 et 32 bits de Windows.
Les versions 32 bits utilisent en général l'API CreateFileA.
La première fois que j'ai vu _lopen d'utilisé dans un schéma
de protection, c'était dans ASProtect, pour éviter le traditionnel BPX CreateFileA dans le cas de
détection MeltIce. :0051037B BE98055100 MOV ESI,00510598 > adresse de départ :00510380 BF98035100 MOV EDI,00510398 > adresse d'arrivée :00510385 B930000000 MOV ECX,00000030 > taille du bloc :0051038A 8A06 MOV AL,[ESI] > place un caractère dans AL :0051038C 3435 XOR AL,35 > le décrypte avec la clé 53h :0051038E 8807 MOV [EDI],AL > place caractère crypté à l'@ d'arrivée :00510390 46 INC ESI > incrémente l'adresse de départ :00510391 47 INC EDI > puis celle d'arrivée :00510392 49 DEC ECX > décrémente le compteur :00510393 83F900 CMP ECX,00 > bloc entier lu? :00510396 75F2 JNZ 0051048A > non -> boucle La routine décryptée commence à la ligne suivante. Ainsi vous pourrez la voir apparaître, et vous n'aurez pas à la chercher: 68A4045100 PUSH 005104A4 > c:\windows\w32dasm8.ini 6803000000 PUSH 00000003 > lecture de trois caractères 6847055100 PUSH 00510547 > à mettre dans un Buffet 6A00 PUSH 00 > default 68CC045100 PUSH 005104CC > clé « w » 68C5045100 PUSH 005104C5 > section « screen » E81573A6BF CALL KERNEL32!GetPrivateProfileStringA 3D00000000 CMP EAX,00000000 > le fichier existe ? 7405 JZ 0051053B > non -> continue E8BDCFA7BF CALL KERNEL32!ExitProcess > oui -> Bye Bye C3 RET Le path de Wdasm, et les noms de clé et section ont été écrits
sous éditeur hexadécimal.
Par exemple, je vais vérifier qu’à l’adresse 005102B7 j’ai bien un 75, puis un autre à l’adresse 005102A6, et ainsi de suite… :005104DF 60 PUSHAD :005104E0 B904000000 MOV ECX,00000004 > nombre de contrôle :005104E5 BE50314000 MOV ESI,00403150 > 1ere adresse de la table :005104EA 8B3E MOV EDI,[ESI] > mise dans EDI :005104EC 8A4604 MOV AL,[ESI+04] > récupère OpCode de la condition :005104EF 3807 CMP [EDI],AL > et vérifie que tout baigne :005104F1 7508 JNZ 005104FB > Bad Boy Exit Process :005104F3 83C605 ADD ESI,05 > passe à la 2d adresse :005104F6 49 DEC ECX > décrémente le compteur :005104F7 75F3 JNZ 005105EC > boucle si différent de NULL :005104F9 61 POPAD > restauration des registres :005104FA C3 RET > continue Dans une telle boucle, il suffit juste de changer la valeur du compteur, et de rajouter
des adresses sensibles avec leurs OpCodes, sans que ce soit plus long que ça... 00101F90 7500 7200 6500 2E00 2E00 2E00 0000 0100 u.r.e........... 00101FA0 1000 5300 6C00 6900 6400 6500 2000 5300 ..S.l.i.d.e. .S. 00101FB0 6800 6F00 7700 2E00 2E00 2E00 0900 4300 h.o.w.........C. Le 01 (= Grayed), 4 bytes avant la première lettre du nom de l’Item va indiquer
son statut. En le remplaçant par 00 vous retrouverez l’Item Slide Slow intact. Un éditeur de ressources
comme ExeEscope fait la même chose…
Pour pouvoir l’utiliser, il faut connaître le handle des menus.
Cette fois ci, c’est le Handle de la fenêtre qu’il faut catcher. Il va falloir trouver un Appel à API ayant également besoin de ce handle, et par lequel le programme passe assez rapidement pour que l’on puisse la catcher et l’utiliser dès que possible. En partant à la recherche de ce type d’API, je me suis rendu compte que le programme utilisait de nombreuses [mémoires] différentes pour stocker ce handle, et que bien souvent c’est la valeur NULL qui s’y trouvait (rendant l’appel à l’API inopérant). A force de recherches et de tests sous SI, j’ai fini par coincer une partie du code où j’avais ce fameux handle : :004232D5 893560934E00 mov dword ptr [004E9360], esi > ici
:004232DB E80CFEFEFF call 004130EC
* Possible StringData Ref from Data Obj ->"NviewViewAcc"
|
:004232E0 686C294C00 push 004C296C
:004232E5 8B2D78934E00 mov ebp, dword ptr [004E9378]
:004232EB 55 push ebp
A l’aide d’un petit détournement, j’ai mis le handle au chaud dans une autre [mémoire] que j’aurais ensuite possibilité d’appeler quand il me plaira : :004232D5 893560934E00 MOV [004E9360],ESI :004232DB E8AECF0E00 CALL 0051028E > détour et catchage du handle :0051028E 89370005100 MOV [00510070],ESI > choppe hWnd :00510294 E8532EF0FF CALL 004130EC > restauration :00510299 C3 RET > et continue Au moment opportun un JUMP sur cette adresse va réactiver l’Item : :005104C3 61 PUSHAD > sauve les registres :005104C4 FF3570005100 PUSH DWORD PTR [00510070] > récupère hWnd :005104CA 2EFF1500F74B00 CALL CS:[USER32!GetMenu] > Handle menu placé dans EAX :005104D1 6A00 PUSH 00 > Menu Flag (00 = enabled) :005104D3 6A10 PUSH 10 > ID du menu :005104D5 50 PUSH EAX > Handle des menus :005104D6 2EFF15B0F64B00 CALL CS:[USER32!EnableMenuItem] :005104DD 61 POPAD > restauration des registres :005104DE C3 RET > continue
:00510574 803D1009510036 CMP BYTE PTR [00510910],36 > Flag U.Registered :0051057B 7516 JNZ 00510593 > non -> saute :0051057D 6A00 PUSH 00 > hIcon :0051057F 6807085100 PUSH 00510807 > "Registered Version" :00510584 68F0164C00 PUSH 004C16F0 > Titre: XNVIEW :00510589 6A00 PUSH 00 > handle :0051058B A135015100 MOV EAX,[SHELL32!ShellAboutA] > charge @ API :00510590 FFD0 CALL EAX > appel API :00510592 C3 RET L'API ShellAboutA a pour seule fonction d'afficher une "Shell About Dialog
Box".
Bien souvent, elle sera précédée par un call à l'API
LoadIcon qui se chargera de récupérer l'icône spécifiée dans les ressources de
l'exécutable. :0042220C E8E7EEFDFF CALL 004010F8 > vers DialogBoxProc :00422211 31C0 XOR EAX,EAX :00422213 C3 RET Le F10 suivant vous montre comment le programme gère les différentes sélections d'Items. :0040DE62 6689DA MOV DX,BX :0040DE65 89C3 MOV EBX,EAX :0040DE67 89F8 MOV EAX,EDI :0040DE69 FF5604 CALL [ESI+04] > appel procédure :0040DE6C EB19 JMP 0040DE87 Un "D EDI" affichera 000000BF, l'ID de l'Item "A Propos" dans la fenêtre des Datas. :004CEE78 BF 00 00 00 74 05 51 00-C0 00 00 00 14 22 42 00 ....t.Q......"B. et un "D EDI+4", l'adresse de la procédure de branchement :004CEE7C 0C 22 42 00 C0 00 00 00-14 22 42 00 C1 00 00 00 t.Q......"B..... En fait l'ID de l'Item va être utilisé pour pointer dans une table
sur l'adresse de début de la gestion de la procédure associé à cet Item. 000CE070 1200 0000 F821 4200 BF00 0000 0C22 4200 .....!B......"B. 000CE080 C000 0000 1422 4200 C100 0000 1C22 4200 ....."B......"B. Rien de plus facile maintenant que de changer cette valeur par celle qui branchera sur le test Is_Registered avant d'aiguiller vers l'une ou l'autre des procédures d'affichage DialogBoxRegistration, ou ShellAboutBox. |
Bonne Journée
Christal