Zoom Icon

Lezione6 zmaster solution

From UIC

Soluzione lezione 6

Contents


Infos
Author: Zmaster
Email: zmaster.adsl@gmail.com
Website:
Date: 27/09/2008 (dd/mm/yyyy)
Level: Working brain required
Language: Italian Image: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 malevoli 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.