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

Introduzione

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.

Tools usati

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

URL o FTP del programma

Il sito di Quequero (www.uic-spippolatori.com)

Notizie sul programma 

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 :). "

Essay

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
Note finali

Vorrei ringraziare Que per la grande opportunita' che mi dato. Welcome to the dark... errrr. ...enlightment side. Hiihihihi

Disclaimer

Nessuno :). Grazie Que...Prego :)

UIC's page of reverse engineering, scegli dove andare:
Home   Anonimato   Assembly    CrackMe   ContactMe   Forum   Iscrizione
Lezioni    Links   Linux   NewBies   News   Playstation
Tools   Tutorial   Search   UIC Faq
UIC