| |
Corso 8
MFC reverse engineering |
|
14/6/2000 |
by wonder |
|
|
UIC's Home Page |
Published by Quequero |
Mi sono rotto il culo con sto' corso
|
La soluzione è abbastanza chiara e ti faccio i miei
complimenti, però non hai spiegato il perchè si dovessero premere i tasti shift, ctrl
ecc...E non hai spiegato le ultime tre istruzioni finali, bravo cmq :) |
|
| UIC's form |
E-mail: wonder@zxmail.com |
UIC's form |
Difficoltà
|
(x)NewBies
(x)Intermedio ( )Avanzato ( )Master |
|
Salve a tutti. In questo corso andremo a caccia di uova o egg. Scopriremo quali e
quante sono le mosse necessarie per far scattare l'uovo che si trova nel QuePad. Inoltre
ho usato questa opportunita' per spiegare come funziona la MFC ed in particolare come
funzionano i messagi in Windowz.
- Corso 8
MFC reverse engineering
- Written by wonder
- Il programma scritto da Que (i.e. QuePad) nasconde un uovo. Un uovo non e' altro che un
programma nascosto dentro il programma principale che viene eseguito solamente quanto
certi eventi e l'ordine degli eventi e' giusto.
SoftIce
W32dasm Non serve
veramente
DumpBin questo fa parte del Visual C++. Se non
l'avete usate qualsiasi tool che puo' fare un dump del PE
Il sito di Quequero (www.uic-spippolatori.com)
- Le parole di Que: "Bene bene, il programma allegato altro non è che il QuePad,
cioè un editor che devo ancora finire scritto completamente in C++ (tranne qualche
routine) e che serve principalmente per aiutare tutti i nuovi utilizzatori del mitico PGP,
non è detto che non supporterà anche altri programmi, ma visto che Roma è stata
costuita mattone per mattone, allora anche il QuePad sarà costruito routine per routine
:). "
- Il QuePad e' un programma scritto in C++ usando la MFC. La MFC non e' altro che un
wrapper per delle Windows API.
- Asp, come un wrapper? MFC ovvero Microsoft Foundation Class è una
serie di librerie che includono tante belle e comode funzioncine per gestire la parte
grafica delle finestre e non solo, riconosco effettivamente il loro overbloated code, ma a
mio avviso sono molto comode per buttarsi nello sviluppo del programma senza doversi
preoccupare eccessivamente di tutto ciò che riguarda la parte grafica delle applicazioni
NdQuequero
- Inoltre, la MFC procura un framework per il programmatore che vuole scrivere programmi
per Windows. Comunque, secondo me sto' framework fa più casini che bene. Se avete mai
scritto programmi usando la MFC noterete che la mitica WinMain() e la mitica WndProc non
si vedeno. Lo so lo so che ca!&o c'azzecca tutto questo con sto' tutorial. La vostra
pazienza sara' premiata... :) Continuiamo... Sappiamo che ogni programma in Windows non fa
altro che consumare i messaggi che vengono inviati ad esso. E gia' questo e' il mondo del
event-driven dove il motore principale di ogni applicazione per Windows e' WndProc(), la
funzione di smistamento dei messaggi inviati dal Systema Operativo. Ai vecchi tempi,
quando i programmi Windows erano scritti in C, la WndProc non era altro che un enorme
swich che conteneva la logica per tutti i messaggi che il programma voleva smistare
direttamente. Ebbene ora siamo nel mondo della MFC dove l' enorme switch scompare (non
proprio) ed una nuova technica appare. E gia' la MFC usa MESSAGE MAP macro meccanismo, una
AFX_MSGMAP struttura chiamata messageMap e una funzione per trovate la message map di una
Window class per far si che il programma possa rispondere ai messaggi inviati ad esso. Mi
state capendo?... Bene! Allora sapete gia' come crackare o meglio reversare questo
programma. :) Siete ancora qui? Cosa... non lo sapete.... volete imparare.... va bene
fatevi una tazza di te' o qualsiasi altra cosa che vi piaccia bere e seguitemi nel mondo
oscuro della MFC. ;o)
Siete pronti? Via.... Si parte....
Ora seguiamo i passi - i casini - in ordine che la MFC usa per smistare i messaggi:
AfxWndProc() la madre per tutti i programmi per Windows scritti
usando MFC
AfxCallWndProc()
WindowProc() importante funzione. Questa funzione prima
chiama OnWndMsg() e dopo forse DefWindowProc
OnWndMsg() se volete risolvere questa lezione lui ha la
risposta ;o)
In parole povere che cosa succede?!? Ogni volta che un messaggio viene trasmesso dal
Systema Oprativo, la MFC chiama AfxWndProc() che trova il window in
questione che poi ricevera' il messaggio. Dopodiche' chiama AFXWndProc()
che non fa' altro che conservare i messaggi che passano per la sua via per magari
riferenziarli in futuro... poi chiama WindowProc(). WindowProc()
chiama prima OnWndMsg() e poi chiama DefWindowProc()
solamente se - ed e' molto importante - OnWndMsg() non e' riuscito
nel suo compito. Qual' e' il compito di OnWndMsg()?!? Il suo compito
e' di trovare l' handler per il messaggio in questione. E dove lo va cercando?!? Certo..
nella messageMap struttura.
Vediamo un po' che tipo e' questa messageMap
struct AFX_MSGMAP_ENTRY
{
- UINT nMessage; -----> ma che carino ;o) Questo rappresenta il
messaggio
- ...........
- ...........
- UINT nSig; -----> dobbiamo pur
sapere qual'e' la funzione guista. No?!? Questo valore e' usato nello switch dall' MFC per
trovare la funzione per quel particolare messaggio
- AFX_PSMG pfn; -----> mi domando dove punta ;o) E gia' la MFC
crea una link lists per tutti i messaggi che la finestra puo' smistare.
- }
Ok! Credo che sia abbastanza introduzione per questo corso... Armati di questa conoscenza
e' giunta l'ora di trovare l'uovo.
Io ho risolto il corso facendo uso del bpx comando in SofIce.
All'inizio ho provato ad usare il bmsg comando... mi sono totalmente
ubriacato.... Non ci capivo una sega. A sto' punto avevo capito che era meglio lasciare il
corso per un po' e capire sta' ca%$o di MFC. Una volta studiata per benino ho scoperto la
nuova fiamma di Que. Bravo Que! Complimenti a te ed alla tua fiamma :) Ho finito lo
prometto! I tamburi prego....
Fate partire il QuePad ed andate al font dialog... Lo sapete no... Quello che ha come
titolo "Font.... (Ancora incompleto)". E meno male che e' incompleto... :)
1) Entrate in SoftIce.
2) Mette un bel bpx su WindowProc(). Cosa?!? Non funziona!! V'ho fregato.... hiiihih . Ve
lo detto che mi sono rotto il culo... Il problema e' che la MFC42.dll esporta non i nomi
delle sue funzioni, bensi' usa ordinali per riferire alle varie funzioni. Vi ricordate
DumpBin? Ebbene usatelo e scoprirete che WindowProc() non e' altro che ordinale 18E6.
Riproviamo... bpx mfc42!ord_18E6 if (esp->4) ==
WM_LBUTTONDOWN. E gia' ci conviene mettere una condizione se no usciamo pazzi!! Ora
tutto funziona.
Eccoci qua:
:5F401B41 push
EBP
prologo dello stack per la nuova funzione
:5F401B42 mov EBP, ESP
questa e' la funzione WindowProc()
: .
: .
:5F401B5D call [eax+A4]
chiama OnWndMsg(). Entrare
dentro la funzione.
Andiamo a vedere la parte che c'interessa di OnWndMsg()
:5F401CB4 push
00
stiamo passando parametri
alla funzione
:5F401CB6 push 00
:5F401CB8 push ECX
chissa' che parametro e' questo ;)
:5F401CBC call mfc42!ord_0479
che funzione e' questa?? Ma certo la
nostra amica AfxFindMessageEntry
ma che bel nome che ha questa funzione!! Ce la cucchiamo?!
Ceeerrto... entrate anche dentro questa
funzione. C'e' una bella
sorpresa ;)
Andiamo a vedere la parte interessante della AfxFindMessageEntry()
:5F402022 push
EBP
sempre il solito stack
:5F402023 mov EBP,ESP
:5F402026 mov EBX,[EBP+8]
punta alla messageMap stuttura
:5F402029 mov EAX,[EBP+c]
il numero del messaggio da smistare
:5F40202C mov EDX,[EBP+10]
nCode parametro
:5F40202F mov EDX,[EBP+14]
nID parametro
:5F402032 cmp DWORD PTR [EBX+10],00 inizio loop. Credo che sia un while loop
:5F402036 jz 5F402055
se e'
zero esci dal loop
:5F402038 cmp EAX,[EBX]
se no continua.
Guardate un po' cosa riporta EBX. ;)
:5F40203A jz 5F402041
ma guarda un po' che fortuna. Abbiamo trovato un' entrata
:5F40203C add EBX,18
sfortuna. Vediamo la prossima entrata nella messageMap
;)
:5F40203F jmp 5F402032
E il giro intorno al mondo continua ;)
Questa funzione la troverete su ogni programma scritto usando la MFC e vi dira'
esattamente quali sono i messaggi che la finestra in questione smistera'. Ma che bella
cosa. Ora sapete come trovare quanti e quali messaggi qualsiasi finestra smista sempre che
e' stata scritta usando la MFC. :)))
Ritorniamo a noi. Guardate in memoria (EBX+18) e scoprirete le mosse segrete del QuePad
;o). Questo e quanto appare in memoria:
MEM MSG# Traduzione
- 0102 201
WM_LBUTTONDOWN
- 0602 206
WM_RBUTTONDBLCLK
- 0300 003
WM_MOVE
- 0010 100
WM_KEYDOWN
Avete visto... So' gia' tutti i messaggi che la finestra Font smistera'. Ma che figata!!
Ci siamo quasi. Dobbiamo vedere ora se le funzioni che smistano i messaggi guardano se lo Shift o Ctrl key sono premuti. Continuiamo con il
code....
Dopo che siete usciti dalla funzione AfxFindMessageEntry()
ritornerete nella funzione OnWndMsg(). Continuate a steppare....
questa funzione fa un paio di cose carine. Una delle cose carine che fa' e' il grande
switch logic che e' usato in ogni programma per Windows per smistare i messaggi. E gia' il
grande switch non e' sparito.... e' la nascosto dentro una marea di code. E anche nello
switch c'e' differenza da come saranno abituati coloro che programmano in C. Scusate se
non vi mostro tutto il code. Questo tutorial rischia di diventare troppo lungo. Gia'
scommetto che vi state rompendo le balle!! Forza! E' quasi finita.... Ok! siamo arrivati
qua:
:5F401E91 call
EBX MFC all' opera.
Entrate dentro questa chiamta e vi spedira' dentro il QuePad
Questa e' la funzione che gestisce il messaggio WM_LBUTTONDOWN
:00402A2D push ebp
Lo stack viene preparato
:00402A2E mov ebp, esp
:00402A30 push ecx
conserviamo il valore di ECX
:00402A31 mov dword ptr [ebp-04], ecx
il valore di ECX viene copiato in una variable locale
:00402A34 cmp dword ptr [ebp+08], 00000005 Che cosa e' questo?? E'un check. Vi conviene premere shift
:00402A38 jne 00402A47
Se non avete usato shift niente uovo....
:00402A3A mov eax, dword ptr [0040B4E4] La viariable che tiene conto delle tue mosse
:00402A3F add eax, 00000001
Un punto a
te se hai usato SHIFT + WM_LBUTTONDOWN
:00402A42 mov dword ptr [0040B4E4], eax Il valore viene poi ricopiato in memoria. Global Variable.. Nessuno?!?
La stessa cosa succede nel WM_RBUTTONDBLCLK
:00402A61 push ebp
Inizio Stack
:00402A62 mov ebp, esp
:00402A64 push ecx
conserviamo il valore di ECX
:00402A65 mov dword ptr [ebp-04], ecx
il valore di ECX viene copiato in una variable locale
:00402A68 cmp dword ptr [ebp+08], 0000000E Facile No? CTRL+SHIFT
:00402A6C jne 00402A7B
Hai toppato alla grande :)
:00402A6E mov eax, dword ptr [0040B4E4] La nostra cara amica :)
:00402A73 add eax, 00000001
Due
punti a te se hai usato SHIFT + CTRL + WM_RBUTTONDBLCLK
:00402A76 mov dword ptr [0040B4E4], eax
Il prossimo messaggio (WM_MOVE)
non e' niente di particolare... Stesse cose senza l'uso del CTRL o SHIFT
Ed ora il gran finale.... WM_KEYDOWN. Questo mi ha buttato un po' fuori pista. Erano le 3
e mezza di notte... Che cosa volete.
:00402AC8 push ebp
Lo stack viene preparato
:00402AC9 mov ebp, esp
:00402ACB sub esp, 0000006C
Lo
stack viene aggiustato
.
.
:00402AD4 cmp dword ptr [0040B4E4], 00000003 Le
avete fatte le 3 mosse segrete?!?
:00402ADB jne 00402D02
Spero che l'abbiate
fatte. Se no tutti a casa :)
:00402AE1 inc dword ptr [0040A96C]
Questo e' la memoria che tiene conto del
numero dei tasti premuti
:00402AE7 mov ecx, dword ptr [0040A96C] Il suo valore e' poi copiato sul registero
:00402AED mov eax, dword ptr [ebp+08]
:00402AF0 mov dword ptr [ecx+0040B498], eax
:00402AF6 cmp ecx, 00000048
Qua c'e' il
check. Avete premuto 47h tasti?!?
:00402AF9 je 00402B00
Spero di si se no....
:00402AFB jmp 00402D02
Riprova e controlla :)
:00402B00 inc dword ptr [0040A968]
Azzeriamo il nostro contatore
:00402B06 mov ecx, dword ptr [0040A968] ECX diventa il nostro contatore
:00402B0C mov al, byte ptr [ecx+0040B498] Spostiamo la prima lettera che e' stata schiacciata
:00402B12 xor al, 2E
Questo e' il primo XOR. E gia' uno non bastava.
Vero Que?!? :) E sennò come te la complicavo
la vita? :))) NdQUequero
:00402B14 xor al, 6B
Un altro ancora.
:00402B16 mov byte ptr [ecx+0040B498], al Il nuovo carattere viene cosi' creato. Avete capito??!
:00402B1C cmp ecx, 00000048
Abbiamo
cryptato tutti i caratteri?!?
:00402B1F jne 00402B00
Fine del loop
:00402B21 mov [ebp-4C], 14
Trovere
una marea di ste cose.
:00402B25 mov [ebp-4B], 10
Lo
sapete che cos'e. Vero?!?
:00402B29 mov [ebp-4A], 04
Io non
avevo capito. L'ho scoperto molto dopo
Avete capito che cosa sta succedendo!?! Dovrete scrivere la frase giusta per far scattare
l'uovo. Se volete prendetevi un foglietto e scoprite la frase magica. Oppure guardate alla
soluzione.
Allora sei proprio un sfaticato?? Scherzo :) Prendiamo il primo carattere... 14.
14h xor 6Bh = 7Fh e poi un altro xor
7Fh xor 2Eh = 51h = Q
10h xor 6Bh = 7Bh e poi un altro xor
7Bh xor 2Eh = 55h = U
La frase finale e' " QUANDO AVRAI FINITO DI SCRIVERE QUESTA FRASE SARA
ORA DI MORIRE ".
Cosa?!? Non succede niente. Ebbene, ricordate il numero 47h. Il numero totale di lettere
non e' 47h. Non fa' niente. Schiacciate qualsiasi lettera che volete finche' l'uovo non
esce. Godetevi l'uovo :) Oh! Un'altra cosa.... Il programma e' chiamato QueFlame.com ;)
-
- Beh, in realtà la frase finale era: QUANDO AVRAI FINITO DI
SCRIVERE QUESTA FRASE SARA ORA DI MORIRE DEH HI HI, quindi non so come ti possa essere
uscito l'uovo senza le ultime lettere, ad ogni modo la frase può essere scritta anche in
minuscolo.
Feel the code, Luke
Vorrei ringraziare Que per la grande opportunita' che mi dato. Welcome to the dark...
errrr. ...enlightment side. Hiihihihi
- Nessuno :). Grazie Que...Prego :)