Zoom Icon

Lezione6 zmaster solution

From UIC Archive

Soluzione lezione 6

Contents


Lezione6 zmaster solution
Author: Zmaster
Email: [email protected]
Website:
Date: 27/09/2008 (dd/mm/yyyy)
Level: Working brain required
Language: Italian Flag Italian.gif
Comments: Azzua bel lavoro ndPnluck



Introduzione

Il compito per casa della Lezione 6 era decompilare una subroutine (cioè passare dal codice macchina al codice sorgente, in questo caso passando per l’asm come step intermedio).
Per fare questo ho utilizzato IDA come disassemblatore, ha il vantaggio di essere più completo di OllyDbg e permette man mano che si reversa il codice di rinominare variabili, costanti, ecc. ecc. con testi più significativi.


Tools

IDA 4.9 free


Essay

Iniziamo: apriamo l’eseguibile con IDA e andiamo a cercare la funzione all’indirizzo 401170: .text:00401170 sub_401170 proc near  ; DATA XREF: DialogFunc+A6_o .text:00401170 .text:00401170 hWnd = dword ptr 8 .text:00401170 arg_4 = dword ptr 0Ch .text:00401170 wParam = dword ptr 10h .text:00401170 lParam = dword ptr 14h .text:00401170 .text:00401170 push edi .text:00401171 mov edi, [esp+arg_4] .text:00401175 cmp edi, 87h .text:0040117B jnz short loc_401186 .text:0040117D mov eax, 4 .text:00401182 pop edi .text:00401183 retn 10h .text:00401186 ; --------------------------------------------------------------------------- .text:00401186 .text:00401186 loc_401186:  ; CODE XREF: sub_401170+B_j .text:00401186 push esi .text:00401187 mov esi, [esp+4+hWnd] .text:0040118B cmp edi, 101h .text:00401191 jnz short loc_4011F4 .text:00401193 push 14h  ; nMaxCount .text:00401195 push offset word_40AC90 ; lpString .text:0040119A push esi  ; hWnd .text:0040119B call ds:GetWindowTextW .text:004011A1 add eax, 0FFFFFFFBh .text:004011A4 cmp eax, 0Eh .text:004011A7 ja short loc_4011F4 .text:004011A9 mov ecx, offset aCesare ; "CESARE" .text:004011AE mov eax, offset word_40AC90 .text:004011B3 .text:004011B3 loc_4011B3:  ; CODE XREF: sub_401170+63_j .text:004011B3 mov dx, [eax] .text:004011B6 cmp dx, [ecx] .text:004011B9 jnz short loc_4011D9 .text:004011BB test dx, dx .text:004011BE jz short loc_4011D5 .text:004011C0 mov dx, [eax+2] .text:004011C4 cmp dx, [ecx+2] .text:004011C8 jnz short loc_4011D9 .text:004011CA add eax, 4 .text:004011CD add ecx, 4 .text:004011D0 test dx, dx .text:004011D3 jnz short loc_4011B3 .text:004011D5 .text:004011D5 loc_4011D5:  ; CODE XREF: sub_401170+4E_j .text:004011D5 xor eax, eax .text:004011D7 jmp short loc_4011DE .text:004011D9 ; --------------------------------------------------------------------------- .text:004011D9 .text:004011D9 loc_4011D9:  ; CODE XREF: sub_401170+49_j .text:004011D9  ; sub_401170+58_j .text:004011D9 sbb eax, eax .text:004011DB sbb eax, 0FFFFFFFFh .text:004011DE .text:004011DE loc_4011DE:  ; CODE XREF: sub_401170+67_j .text:004011DE test eax, eax .text:004011E0 jnz short loc_4011F4 .text:004011E2 push eax  ; uType .text:004011E3 push offset Caption  ; "Lezione 3" .text:004011E8 push offset aPasswordCorret ; "Password Corretta" .text:004011ED push eax  ; hWnd .text:004011EE call ds:MessageBoxW .text:004011F4 .text:004011F4 loc_4011F4:  ; CODE XREF: sub_401170+21_j .text:004011F4  ; sub_401170+37_j ... .text:004011F4 mov eax, [esp+4+lParam] .text:004011F8 mov ecx, [esp+4+wParam] .text:004011FC mov edx, dwNewLong .text:00401202 push eax  ; lParam .text:00401203 push ecx  ; wParam .text:00401204 push edi  ; Msg .text:00401205 push esi  ; hWnd .text:00401206 push edx  ; lpPrevWndFunc .text:00401207 call ds:CallWindowProcW .text:0040120D pop esi .text:0040120E pop edi .text:0040120F retn 10h .text:0040120F sub_401170 endp Come è stato spiegato nella lezione questa subroutine è una nuova WindowProc che viene utilizzata per realizzare un SubClassing della Textbox dove si inserisce la password.
Questo ci dice che si tratta di una funzione che riceve i 4 parametri di tutte le WndProc.
Nel listato qui sopra ho già utilizzato la funzionalità di IDA “Create Function” per farmi analizzare l’uso dello stack e mostrarmi chiaramente l’utilizzo degli argomenti. IDA non ha riconosciuto il secondo parametro: aiutiamolo con un click destro su arg_4 e rinominiamolo in uMsg.

Iniziamo a dare un occhio all’assembly: .text:00401170 push edi .text:00401171 mov edi, [esp+uMsg] .text:00401175 cmp edi, 87h .text:0040117B jnz short loc_401186 .text:0040117D mov eax, 4 .text:00401182 pop edi .text:00401183 retn 10h In pratica in queste righe viene copiato l’argomento uMsg in EDI e viene controllato se è uguale a 0x87. Se è diverso il programma salta più avanti, continuando l’esecuzione all’interno della funzione, altrimenti setta EAX a 4 e ritorna.
0x87 è il codice del messaggio WM_GETDLGCODE, win32.hlp ci spiega che viene usato da windows per chiedere ad un controllo che tasti è in grado di processare. Scrivere 4 in EAX significa ritornare DLGC_WANTALLKEYS.

Nel caso uMsg sia diverso l’esecuzione prosegue a 401186: .text:00401186 push esi .text:00401187 mov esi, [esp+4+hWnd] .text:0040118B cmp edi, 101h .text:00401191 jnz short loc_4011F4 .text:00401193 push 14h  ; nMaxCount .text:00401195 push offset word_40AC90 ; lpString .text:0040119A push esi  ; hWnd .text:0040119B call ds:GetWindowTextW .text:004011A1 add eax, 0FFFFFFFBh .text:004011A4 cmp eax, 0Eh .text:004011A7 ja short loc_4011F4 .text:004011A9 mov ecx, offset aCesare ; "CESARE" .text:004011AE mov eax, offset word_40AC90 .text:004011B3 .text:004011B3 loc_4011B3:  ; CODE XREF: sub_401170+63_j .text:004011B3 mov dx, [eax] .text:004011B6 cmp dx, [ecx] .text:004011B9 jnz short loc_4011D9 .text:004011BB test dx, dx .text:004011BE jz short loc_4011D5 .text:004011C0 mov dx, [eax+2] .text:004011C4 cmp dx, [ecx+2] .text:004011C8 jnz short loc_4011D9 .text:004011CA add eax, 4 .text:004011CD add ecx, 4 .text:004011D0 test dx, dx .text:004011D3 jnz short loc_4011B3 .text:004011D5 .text:004011D5 loc_4011D5:  ; CODE XREF: sub_401170+4E_j .text:004011D5 xor eax, eax .text:004011D7 jmp short loc_4011DE .text:004011D9 ; --------------------------------------------------------------------------- .text:004011D9 .text:004011D9 loc_4011D9:  ; CODE XREF: sub_401170+49_j .text:004011D9  ; sub_401170+58_j .text:004011D9 sbb eax, eax .text:004011DB sbb eax, 0FFFFFFFFh Viene controllato se il messaggio è 0x101, che sarebbe WM_KEYUP, se non lo è salta più avanti a 4011F4.
Se il messaggio è proprio WM_KEYUP l’esecuzione prosegue: viene chiamata GetWindowTextW per leggere il testo dalla Textbox in un buffer che si trova a 40AC90, dimensione massima 0x14 == 20 bytes. La funzione ritorna in EAX il numero di caratteri letti. La successiva ADD non fa altro che sommare un numero in complemento a 2, cioè un valore negativo. Anche qui IDA ci risparmia di tirare fuori la calcolatrice: un click sul tasto “Change sign” e scopriamo che il valore è -5.
Le istruzioni seguenti sono banali, nel complesso questo blocco di istruzioni significa:
Se (LunghezzaStringa-5) > 14 vai a 4011F4, altrimenti carica in ECX l’offset della stringa “CESARE” e in EAX l’offset della stringa letta dalla Textbox.

Segue un ciclo di istruzioni che come si può facilmente intuire andrà a confrontare le due stringhe.
L’unica cosa curiosa degna di nota è che il confronto viene fatto su due word per volta invece che una.
Se le stringhe corrispondono viene settato EAX=0.

Segue: .text:004011DE loc_4011DE:  ; CODE XREF: sub_401170+67_j .text:004011DE test eax, eax .text:004011E0 jnz short loc_4011F4 .text:004011E2 push eax  ; uType .text:004011E3 push offset Caption  ; "Lezione 3" .text:004011E8 push offset aPasswordCorret ; "Password Corretta" .text:004011ED push eax  ; hWnd .text:004011EE call ds:MessageBoxW Se EAX == 0, cioè se la stringa nella Textbox è “CESARE”, viene visualizzata la MessageBox di password corretta.

Nell’ultimo pezzo viene chiamata la WindowProc base del controllo Textbox. Notare che la funzione base viene invocata sempre, tranne nel caso del messaggio WM_GETDLGCODE. .text:004011F4 loc_4011F4:  ; CODE XREF: sub_401170+21_j .text:004011F4  ; sub_401170+37_j ... .text:004011F4 mov eax, [esp+4+lParam] .text:004011F8 mov ecx, [esp+4+wParam] .text:004011FC mov edx, dwNewLong .text:00401202 push eax  ; lParam .text:00401203 push ecx  ; wParam .text:00401204 push edi  ; Msg .text:00401205 push esi  ; hWnd .text:00401206 push edx  ; lpPrevWndFunc .text:00401207 call ds:CallWindowProcW .text:0040120D pop esi .text:0040120E pop edi .text:0040120F retn 10h .text:0040120F sub_401170 endp Ok, dopo aver fatto quest’analisi riporto l’assembly con i simboli rinominati in base alle mie interpretazioni, ora è più leggibile: .text:00401170 sub_401170 proc near  ; DATA XREF: DialogFunc+A6_o .text:00401170 .text:00401170 hWnd = dword ptr 8 .text:00401170 uMsg = dword ptr 0Ch .text:00401170 wParam = dword ptr 10h .text:00401170 lParam = dword ptr 14h .text:00401170 .text:00401170 push edi .text:00401171 mov edi, [esp+uMsg] .text:00401175 cmp edi, WM_GETDLGCODE .text:0040117B jnz short loc_401186 .text:0040117D mov eax, DLGC_WANTALLKEYS .text:00401182 pop edi .text:00401183 retn 10h .text:00401186 ; --------------------------------------------------------------------------- .text:00401186 .text:00401186 loc_401186:  ; CODE XREF: sub_401170+B_j .text:00401186 push esi .text:00401187 mov esi, [esp+4+hWnd] .text:0040118B cmp edi, WM_KEYUP .text:00401191 jnz short InvocazioneWndProcBase .text:00401193 push 14h  ; nMaxCount .text:00401195 push offset StringaTextbox ; lpString .text:0040119A push esi  ; hWnd .text:0040119B call ds:GetWindowTextW .text:004011A1 add eax, -5 .text:004011A4 cmp eax, 0Eh .text:004011A7 ja short InvocazioneWndProcBase .text:004011A9 mov ecx, offset aCesare ; "CESARE" .text:004011AE mov eax, offset StringaTextbox .text:004011B3 .text:004011B3 LoopConfronto:  ; CODE XREF: sub_401170+63_j .text:004011B3 mov dx, [eax] .text:004011B6 cmp dx, [ecx] .text:004011B9 jnz short StringheDiverse .text:004011BB test dx, dx .text:004011BE jz short StringheUguali .text:004011C0 mov dx, [eax+2] .text:004011C4 cmp dx, [ecx+2] .text:004011C8 jnz short StringheDiverse .text:004011CA add eax, 4 .text:004011CD add ecx, 4 .text:004011D0 test dx, dx .text:004011D3 jnz short LoopConfronto .text:004011D5 .text:004011D5 StringheUguali:  ; CODE XREF: sub_401170+4E_j .text:004011D5 xor eax, eax .text:004011D7 jmp short loc_4011DE .text:004011D9 ; --------------------------------------------------------------------------- .text:004011D9 .text:004011D9 StringheDiverse:  ; CODE XREF: sub_401170+49_j .text:004011D9  ; sub_401170+58_j .text:004011D9 sbb eax, eax .text:004011DB sbb eax, -1 .text:004011DE .text:004011DE loc_4011DE:  ; CODE XREF: sub_401170+67_j .text:004011DE test eax, eax .text:004011E0 jnz short InvocazioneWndProcBase .text:004011E2 push eax  ; uType .text:004011E3 push offset Caption  ; "Lezione 3" .text:004011E8 push offset aPasswordCorret ; "Password Corretta" .text:004011ED push eax  ; hWnd .text:004011EE call ds:MessageBoxW .text:004011F4 .text:004011F4 InvocazioneWndProcBase:  ; CODE XREF: sub_401170+21_j .text:004011F4  ; sub_401170+37_j ... .text:004011F4 mov eax, [esp+4+lParam] .text:004011F8 mov ecx, [esp+4+wParam] .text:004011FC mov edx, dwNewLong .text:00401202 push eax  ; lParam .text:00401203 push ecx  ; wParam .text:00401204 push edi  ; Msg .text:00401205 push esi  ; hWnd .text:00401206 push edx  ; lpPrevWndFunc .text:00401207 call ds:CallWindowProcW .text:0040120D pop esi .text:0040120E pop edi .text:0040120F retn 10h .text:0040120F sub_401170 endp Ora non ci resta che fare l’ultimo passo: la traduzione in C dell’assembly. Tornare al codice sorgente originale in senso stretto non è possibile ma possiamo dire che da un punto di vista funzionale era qualcosa del genere: LRESULT CALLBACK NuovaWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { int Len; WORD *pStr1, *pStr2;

if(uMsg == WM_GETDLGCODE) return DLGC_WANTALLKEYS;

if(uMsg == WM_KEYUP) { Len = GetWindowTextW(hWnd, StrTextbox, 20); if(Len < 20) { pStr1 = StrTextbox; pStr1 = StrCesare;

while(1) { if(*pStr1 != *pStr2) break; if(*pStr1 == 0) { MessageBoxW(0, "Password Corretta", "Lezione 3", 0); break; } } } }

return CallWindowProcW(pVecchiaWndProc, hWnd, uMsg, wParam, lParam); }


Note Finali

C’è voluto più tempo a scrivere il tute che non a reversare la funzione :) Saluto tutti i membri della UIC, in particolare pnluck [mi chiamo Pnluck, azz! ndPnluck] che come dice Que ha prodotto in fretta e furia la Lezione 6.


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.