Another ReverseMe that the whole family will love!
by SantMat
Tutorial de Lucifer48 [Immortal Descendants]
(1er Juillet 2000)
On commence par le plus facile, à savoir patcher la nag; voiçi le tout début du reverseme:
XXXX:00401000 6A00 PUSH 00
XXXX:00401002 E859010000 CALL KERNEL32!GetModuleHandleA
XXXX:00401007 A39C304000 MOV [0040309C], EAX
XXXX:0040100C 6A00 PUSH 00 ;pas de valeur à passer (lparam)
XXXX:0040100E 6842104000 PUSH 00401042 ;offset DlgProc
XXXX:00401013 6A00 PUSH 00 ;pas de fenêtre parente
XXXX:00401015 6800304000 PUSH 00403000 ;MEMO
XXXX:0040101A FF359C304000 PUSH DWORD PTR [0040309C] ;hInstance
XXXX:00401020 E81D010000 CALL USER32!DialogBoxParamA
Remarque: Les appels qui suivent (LoadLibrary, FreeLibrary, GetProcAdress) vont nous aider !
On change juste deux petites valeurs:
XXXX:0040100C 6A00 PUSH 00 ;pas de valeur à passer (lparam)
XXXX:0040100E 68BF104000 PUSH 004010BF ;bonne DlgProc
XXXX:00401013 6A00 PUSH 00 ;pas de fenêtre parente
XXXX:00401015 6805304000 PUSH 00403005 ;GAME
XXXX:0040101A FF359C304000 PUSH DWORD PTR [0040309C] ;hInstance
XXXX:00401020 E81D010000 CALL USER32!DialogBoxParamA
Deux octets à changer, c'est pas trop dur !
Passons à l'activation des deux boutons. Voilà les deux control-ID dont nous avons besoin:
Name: GAME, # of Controls=008, Caption:"Two-Player Number Battler!", ClassName:""
001 - ControlID:FFFF, Control Class:"STATIC" Control Text:"Player 1, use the mouse or letter "z" ..."
002 - ControlID:03EF, Control Class:"EDIT" Control Text:"" <- sur la droite
003 - ControlID:03F0, Control Class:"EDIT" Control Text:"" <- sur la gauche
....
Pour le jeu proprement dit, voilà comment je compte organiser les choses:
J'ai besoin de 5 octets:
- Score player 1
- Score player 2
- Status : 4 cas s'imposent
- 0 : personne n'a encore joué : les deux editbox sont vides
- 1 : player 1 joue (mais player 2 n'a pas encore joué)
- 2 : player 2 joue (mais player 1 n'a pas encore joué)
- 3 : player 1 joue (et player 2 a déjà joué) ou player 2 joue (et player 1 a déjà joué)
(pour ce dernier cas, on modifie les scores et efface les deux editbox ; et eventuellement fin du jeu)
- Valeur player 1
- Valeur player 2
Voilà un morceau de WM_COMMAND qui nous interesse bien !
XXXX:004010DF 817D0C11010000 CMP DWORD PTR [EBP+0C], 00000111;WM_COMMAND
XXXX:004010E6 7547 JNZ 0040112F
XXXX:004010E8 8B4510 MOV EAX, [EBP+10] ;wparam
XXXX:004010EB 663DED03 CMP AX, 03ED ;bouton "Player 1"
XXXX:004010EF 751B JNZ 0040110C
XXXX:004010F1 C1E810 SHR EAX, 10
XXXX:004010F4 660BC0 OR AX, AX ;pas vraiment utile... (BN_CLICKED)
XXXX:004010F7 7513 JNZ 0040110C ;.if ...
XXXX:004010F9 6A00 PUSH 00 ;MB_OK
XXXX:004010FB 680A304000 PUSH 0040300A ;"Number Game"
XXXX:00401100 6816304000 PUSH 00403016 ;"This is the part you need to change ..."
XXXX:00401105 6A00 PUSH 00 ;pas de hwnd (et dword ptr [ebp+4] ?)
XXXX:00401107 E842000000 CALL USER32!MessageBoxA
Comme la place à la fin du .code n'est pas suffisante (pour moi!), je vais ajouter une nouvelle section.
XXXX:004010F9 800D5761400001 OR BYTE PTR [00406157], 01
XXXX:00401100 E8FB4E0000 CALL 00406000
XXXX:00401105 EB31 JMP 00401138
Je fais de même pour le player 2:
XXXX:0040110C 663DEE03 CMP AX, 03EE ;bouton "Player 2"
XXXX:00401110 7526 JNZ 00401138
XXXX:00401112 C1E810 SHR EAX, 10
XXXX:00401115 660BC0 OR AX, AX
XXXX:00401118 7513 JNZ 0040112D
XXXX:0040111A 6A00 PUSH 00
XXXX:0040111C 680A304000 PUSH 0040300A ;"Number Game"
XXXX:00401121 6856304000 PUSH 00403056 ;"This is the other part you need to change ..."
XXXX:00401126 6A00 PUSH 00 ;pas de hwnd
XXXX:00401128 E821000000 CALL USER32!MessageBoxA
XXXX:0040112D EB09 JMP 00401138
et je remplace par:
XXXX:0040111A 800D5761400002 OR BYTE PTR [00406157], 02
XXXX:00401121 E8DA4E0000 CALL 00406000
XXXX:00401126 EB10 JMP 00401138
Occupons nous maitenant du code à ajouter en 0046000. J'ajoute donc une nouvelle section ; je modifie légèrement
le PE (l'en-tête uniquement), comme suit:
Name V.Size V.Offset R.Size R.Offset Characteristics
-----------------------------------------------------------------
.lucy 00000400 00006000 00000400 00001E00 C0000040
N'oublions pas d'ajouter 1000h à Size of image.
Une fois le PE modifié, reste plus qu'a ajouter physiquement 1024 octets au fichier, pour cela j'utilise
Hex Workshop. On a maintenant un peu plus de place :)
J'ai besoin du message WM_INITDIALOG pour faire quelques initialisations (principalement pour fixer les adresses
des API dont j'ai besoin). Heureusement SantMat a tout prévu :)
XXXX:004010BF 55 PUSH EBP ;debut de la DlgProc
XXXX:004010C0 8BEC MOV EBP, ESP
XXXX:004010C2 817D0C10010000 CMP DWORD PTR [EBP+0C], 000110 ;.if uMsg==WM_INITDIALOG
XXXX:004010C9 7502 JNZ 004010CD
XXXX:004010CB EB6B JMP 00401138 ;on va changer ce saut
XXXX:004010CD 837D0C10 CMP DWORD PTR [EBP+0C], 10 ;.if uMsg==WM_CLOSE
Je vais donc faire un saut juste au dessus de cette DlgProc, il y a la DlgProc de la première boîte de dialogue qui ne nous
sert plus à rien désormais.
XXXX:004010CB EB98 JMP 00401065
Voilà donc le code d'initialisation:
XXXX:00401065 E8F1500000 CALL 0040615B ;trouve les adresse des api dont j'ai besoin
XXXX:0040106A 6825624000 PUSH 00406225 ;"Player 1 (&z)"
XXXX:0040106F 68ED030000 PUSH 000003ED ;bouton de gauche
XXXX:00401074 FF7508 PUSH DWORD PTR [EBP+08] ;handle de la boîte de dialogue
XXXX:00401077 FF1511624000 CALL [00406209] ;USER32!SetDlgItemTextA
XXXX:0040107D 68ED030000 PUSH 000003ED
XXXX:00401082 FF7508 PUSH DWORD PTR [EBP+08]
XXXX:00401085 FF1511624000 CALL [00406211] ;USER32!GetDlgItem
XXXX:0040108B A31D624000 MOV [0040621D], EAX ;sauvegarde l'handle du bouton (gauche)
XXXX:00401090 6833624000 PUSH 00406233 ;"Player 2 (&m)"
XXXX:00401095 68EE030000 PUSH 000003EE ;bouton de droite
XXXX:0040109A FF7508 PUSH DWORD PTR [EBP+08]
XXXX:0040109D FF1509624000 CALL [00406209] ;USER32!SetDlgItemTextA
XXXX:004010A3 68EE030000 PUSH 000003EE
XXXX:004010A8 FF7508 PUSH DWORD PTR [EBP+08]
XXXX:004010AB FF1511624000 CALL [00406211] ;USER32!GetDlgItem
XXXX:004010B1 A321624000 MOV [00406221], EAX ;sauvegarde l'handle du bouton (droit)
XXXX:004010B6 B801000000 MOV EAX, 00000001
XXXX:004010BB C9 LEAVE
XXXX:004010BC C21000 RET 0010
Pour le code qui se trouve dans la section .lucy, je ne vais pas le recopier ici. Jetez un coup d'oeil
là dessus.
Dernières Remarques:
- Mon générateur de nombre aléatoire n'est pas aléatoire du tout (il est situé tout à la fin de la section, c'est
facilement modifiable).
- L'unique autre façon que j'ai trouvé pour creer les raccourcis clavier, c'est d'utiliser SetWindowsHookEx;
en effet, les boîtes de dialogue créées par DialogBoxParam ne recoivent pas WM_CHAR, WM_KEYUP et WM_KEYDOWN.
De plus comme il n'y a pas de boucle de message (celle-ci étant gérée en interne), on ne peut pas utiliser les
accelerator (CreateAcceleratorTable, ...).
- Afficher les scores aurait été un plus aussi.
- Le jeu continue jusqu'à ce que quelqu'un ait atteint 5 points et pas 50.
- etc etc.
Greetings: All the #immortaldescendants channel. And SantMat, congratulations for your bady !
(c) Lucifer48. All rights reserved & reversed