Domanda

Sto cercando di imparare a reverse engineering, usando prato fiorito come un esempio di applicazione.Ho trovato questo Articolo di MSDN su un semplice WinDbg comando che si rivela in tutte le miniere, ma è vecchio, non è spiegato in ogni dettaglio e davvero non è quello che sto cercando.

Ho IDA Pro disassembler e il WinDbg debugger e ho caricato winmine.exe in tutte e due.Qualcuno può fornire alcuni consigli pratici per uno di questi programmi in termini di trovare la posizione della struttura dati che rappresenta il campo minato?

In WinDbg posso impostare punti di interruzione, ma è difficile per me immaginare a che punto per impostare un punto di interruzione e in quale locazione di memoria.Allo stesso modo, quando l'ho vista la statica del codice in IDA Pro, io non sono sicuro di dove iniziare a trovare la funzione o la struttura dati che rappresenta il campo minato.

Ci sono Reverse engineer su Stackoverflow che mi punto nella giusta direzione?

È stato utile?

Soluzione

Parte 1 di 3


Se siete seriamente in reverse engineering - dimenticare formatori e cheat engine.

Buona decodificare deve prima conoscere OS, le funzioni API di base, programma di struttura generale (anello ciò che viene eseguito, strutture finestre, le routine di gestione degli eventi), formato di file (PE). classici "Programming Windows" di Petzold può aiutare (www.amazon.com/exec/obidos/ISBN=157231995X), così come in linea di MSDN.

In primo luogo si dovrebbe pensare a dove routine di inizializzazione campo minato può essere chiamato. Ho pensato di seguire:

  • Quando si avvia il gioco
  • Quando si fa clic faccia felice
  • Quando si sceglie Game-> Nuovo o premere F2
  • Quando si modifica il livello di difficoltà

Ho deciso di controllare il comando F2 dell'acceleratore.

Per trovare il codice di gestione di acceleratore si è di trovare procedura di gestione dei messaggi finestra (WndProc). Si può essere fatta verso il basso da chiamate CreateWindowEx e RegisterClass.

Per leggere:

Aprire IDA, la finestra Imports, trovare "CreateWindow *", saltare e utilizzare "Jump xref all'operando (X)" il comando per vedere dove è chiamato. Ci dovrebbe essere una sola chiamata.

Ora guarda soprattutto per la funzione RegisterClass ed è parametro WndClass.lpfnWndProc. Ho già chiamato funzione MainWndProc nel mio caso.

.text:0100225D                 mov     [ebp+WndClass.lpfnWndProc], offset mainWndProc
.text:01002264                 mov     [ebp+WndClass.cbClsExtra], edi
.text:01002267                 mov     [ebp+WndClass.cbWndExtra], edi
.text:0100226A                 mov     [ebp+WndClass.hInstance], ecx
.text:0100226D                 mov     [ebp+WndClass.hIcon], eax

.text:01002292                 call    ds:RegisterClassW

Hit Invio sul nome di funzione (usare 'N' per rinominarlo in qualcosa di meglio)

Ora date un'occhiata a

.text:01001BCF                 mov     edx, [ebp+Msg]

Questo è il messaggio id, che in caso di tasto F2 stampa dovrebbe contenere il valore WM_COMMAND. Tu sei per trovare dove si è confrontato con 111h. Esso può essere fatto sia tracciando giù edx in IDA o modificando breakpoint condizionale in WinDbg e premendo F2 nel gioco.

In entrambi i casi conduce a qualcosa di simile

.text:01001D5B                 sub     eax, 111h
.text:01001D60                 jz      short loc_1001DBC

Fare clic destro su 111h e l'uso "costante simbolica" -> "Usa livello costante simbolica", tipo WM_ e Invio. Si dovrebbe ora avere

.text:01001D5B                 sub     eax, WM_COMMAND
.text:01001D60                 jz      short loc_1001DBC

Si tratta di un modo semplice per scoprire i valori ID messaggio.

Per capire la gestione dell'acceleratore check out:

E 'un bel po' di testo per una sola risposta. Se siete interessati posso scrivere un altro paio di post. Per farla breve campo minato memorizzato come un array di byte [24x36], 0x0F dimostra che di byte non è utilizzato (campo di gioco più piccolo), 0x10 - campo vuoto, 0x80 -. mine

Parte 2 di 3

Ok, andiamo avanti con il tasto F2.

Utilizzando tastiera acceleratori funzione WndProc quando si preme il tasto F2

  

... riceve un WM_COMMAND o WM_SYSCOMMAND   Messaggio. La parola di ordine del   parametro wParam contiene il   identificatore dell'acceleratore.

Ok, abbiamo già trovato dove WM_COMMAND viene elaborato, ma come determinare corrispondente valore del parametro wParam? Questo è dove Resource Hacker entra in gioco. Alimentarlo con binario e vi mostra tutto. Come tabella di acceleratori per me.

alt text http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg

Si può vedere qui, che il tasto F2 corrisponde a 510 in wParam.

Ora torniamo al codice, che gestisce WM_COMMAND. Esso mette a confronto wParam con diverse costanti.

.text:01001DBC HandleWM_COMMAND:                       ; CODE XREF: mainWndProc+197j
.text:01001DBC                 movzx   eax, word ptr [ebp+wParam]
.text:01001DC0                 mov     ecx, 210h
.text:01001DC5                 cmp     eax, ecx
.text:01001DC7                 jg      loc_1001EDC
.text:01001DC7
.text:01001DCD                 jz      loc_1001ED2
.text:01001DCD
.text:01001DD3                 cmp     eax, 1FEh
.text:01001DD8                 jz      loc_1001EC8

menu Usa contestuale o 'H' scorciatoia da tastiera per visualizzare i valori decimali e si può vedere il nostro salto

.text:01001DBC HandleWM_COMMAND:                       ; CODE XREF: mainWndProc+197j
.text:01001DBC                 movzx   eax, word ptr [ebp+wParam]
.text:01001DC0                 mov     ecx, 528
.text:01001DC5                 cmp     eax, ecx
.text:01001DC7                 jg      loc_1001EDC
.text:01001DC7
.text:01001DCD                 jz      loc_1001ED2
.text:01001DCD
.text:01001DD3                 cmp     eax, 510
.text:01001DD8                 jz      loc_1001EC8 ; here is our jump

Si porta a pezzo di codice che chiama alcuni proc ed esce WndProc.

.text:01001EC8 loc_1001EC8:                            ; CODE XREF: mainWndProc+20Fj
.text:01001EC8                 call    sub_100367A     ; startNewGame ?
.text:01001EC8
.text:01001ECD                 jmp     callDefAndExit  ; default

è che la funzione che avvia nuovo gioco? Trova che nell'ultima parte! Restate sintonizzati.

Parte 3 di 3

Diamo uno sguardo alla prima parte di tale funzione

.text:0100367A sub_100367A     proc near               ; CODE XREF: sub_100140C+CAp
.text:0100367A                                         ; sub_1001B49+33j ...
.text:0100367A                 mov     eax, dword_10056AC
.text:0100367F                 mov     ecx, uValue
.text:01003685                 push    ebx
.text:01003686                 push    esi
.text:01003687                 push    edi
.text:01003688                 xor     edi, edi
.text:0100368A                 cmp     eax, dword_1005334
.text:01003690                 mov     dword_1005164, edi
.text:01003696                 jnz     short loc_10036A4
.text:01003696
.text:01003698                 cmp     ecx, dword_1005338
.text:0100369E                 jnz     short loc_10036A4

Ci sono due valori (dword_10056AC, Valore U) in lettura nei registri eax e ecx e rispetto ad altri due valori (dword_1005164, dword_1005338).

Date un'occhiata a valori reali utilizzando WinDBG ( 'BP 01.003.696'; in pausa 'p EAX; p ecx') - sembravano dimensioni campo minato per me. Giocando con dimensioni campo minato personalizzato ha dimostrato che prima coppia sono nuove dimensioni e la seconda - dimensioni attuali. Fissiamo nuovi nomi.

.text:0100367A startNewGame    proc near               ; CODE XREF: handleButtonPress+CAp
.text:0100367A                                         ; sub_1001B49+33j ...
.text:0100367A                 mov     eax, newMineFieldWidth
.text:0100367F                 mov     ecx, newMineFieldHeight
.text:01003685                 push    ebx
.text:01003686                 push    esi
.text:01003687                 push    edi
.text:01003688                 xor     edi, edi
.text:0100368A                 cmp     eax, currentMineFieldWidth
.text:01003690                 mov     dword_1005164, edi
.text:01003696                 jnz     short loc_10036A4
.text:01003696
.text:01003698                 cmp     ecx, currentMineFieldHeight
.text:0100369E                 jnz     short loc_10036A4

Un po 'più tardi nuovi valori sovrascrivono attuale e subroutine si chiama

.text:010036A7                 mov     currentMineFieldWidth, eax
.text:010036AC                 mov     currentMineFieldHeight, ecx
.text:010036B2                 call    sub_1002ED5

E quando l'ho visto

.text:01002ED5 sub_1002ED5     proc near               ; CODE XREF: sub_1002B14:loc_1002B1Ep
.text:01002ED5                                         ; sub_100367A+38p
.text:01002ED5                 mov     eax, 360h
.text:01002ED5
.text:01002EDA
.text:01002EDA loc_1002EDA:                            ; CODE XREF: sub_1002ED5+Dj
.text:01002EDA                 dec     eax
.text:01002EDB                 mov     byte ptr dword_1005340[eax], 0Fh
.text:01002EE2                 jnz     short loc_1002EDA

ero del tutto sicuro che ho trovato matrice campo minato. Causa di ciclo che INITs lunghezza byte 360h array (dword_1005340) con 0xF.

Perché 360h = 864? Ci sono alcuni spunti sotto quella riga richiede 32 byte e 864 può essere diviso per 32, quindi array può contenere 27 * 32 cellule (sebbene UI permette max 24 * 30 campo, c'è un'imbottitura byte intorno array per bordi).

A seguito di codice genera alto campo minato e bordi inferiori (0x10 byte). Spero che si può vedere iterazione del ciclo in quel casino;) Ho dovuto usare carta e penna

.text:01002EE4                 mov     ecx, currentMineFieldWidth
.text:01002EEA                 mov     edx, currentMineFieldHeight
.text:01002EF0                 lea     eax, [ecx+2]
.text:01002EF3                 test    eax, eax
.text:01002EF5                 push    esi
.text:01002EF6                 jz      short loc_1002F11    ; 
.text:01002EF6
.text:01002EF8                 mov     esi, edx
.text:01002EFA                 shl     esi, 5
.text:01002EFD                 lea     esi, dword_1005360[esi]
.text:01002EFD
.text:01002F03 draws top and bottom borders
.text:01002F03 
.text:01002F03 loc_1002F03:                            ; CODE XREF: sub_1002ED5+3Aj
.text:01002F03                 dec     eax
.text:01002F04                 mov     byte ptr MineField?[eax], 10h ; top border
.text:01002F0B                 mov     byte ptr [esi+eax], 10h       ; bottom border
.text:01002F0F                 jnz     short loc_1002F03
.text:01002F0F
.text:01002F11
.text:01002F11 loc_1002F11:                            ; CODE XREF: sub_1002ED5+21j
.text:01002F11                 lea     esi, [edx+2]
.text:01002F14                 test    esi, esi
.text:01002F16                 jz      short loc_1002F39

E il resto della subroutine disegna bordi sinistro e destro

.text:01002F18                 mov     eax, esi
.text:01002F1A                 shl     eax, 5
.text:01002F1D                 lea     edx, MineField?[eax]
.text:01002F23                 lea     eax, (MineField?+1)[eax+ecx]
.text:01002F23
.text:01002F2A
.text:01002F2A loc_1002F2A:                            ; CODE XREF: sub_1002ED5+62j
.text:01002F2A                 sub     edx, 20h
.text:01002F2D                 sub     eax, 20h
.text:01002F30                 dec     esi
.text:01002F31                 mov     byte ptr [edx], 10h
.text:01002F34                 mov     byte ptr [eax], 10h
.text:01002F37                 jnz     short loc_1002F2A
.text:01002F37
.text:01002F39
.text:01002F39 loc_1002F39:                            ; CODE XREF: sub_1002ED5+41j
.text:01002F39                 pop     esi
.text:01002F3A                 retn

Utilizzo intelligente di WinDBG comandi in grado di fornire la pelle fresca discarica campo minato (formato 9x9 personalizzato). Controlla le frontiere!

0:000> db /c 20 01005340 L360
01005340  10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005360  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005380  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010053a0  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010053c0  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010053e0  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005400  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005420  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005440  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005460  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005480  10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010054a0  0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010054c0  0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010054e0  0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................

Hmm, sembra che io avrò bisogno un altro post per chiudere l'argomento

Altri suggerimenti

Sembra che si sta tentando di smontare la fonte, ma quello che dovete fare è guardare lo spazio di memoria del programma in esecuzione. L'editor esadecimale HxD ha una caratteristica che ti permette proprio questo.

http://www.freeimagehosting.net/uploads/fcc1991162.png

Una volta entrato nello spazio di memoria, si tratta di una questione di prendere istantanee della memoria, mentre si scherza con la scheda. Isolare cosa cambia rispetto a ciò che non lo fa. Quando si pensa di avere una maniglia su cui la struttura di dati risiede in memoria esadecimale, provare a modificare mentre è nella memoria e vedere se i cambiamenti di bordo di conseguenza.

Il processo che si desidera non è dissimile la costruzione di un 'allenatore' per un videogioco. Coloro che sono di solito basate sulla ricerca in cui i valori come la salute e munizioni vivono in memoria e cambiare al volo. Si può essere in grado di trovare alcuni buoni tutorial su come costruire formatori di gioco.

Dai un'occhiata a questo articolo del progetto di codice, è un po 'più in profondità rispetto al post sul blog che lei ha citato.

http://www.codeproject.com/KB/trace/minememoryreader.aspx

Modifica

E questo articolo, anche se non si tratta di Minesweeper direttamente, ti dà una buona guida passo passo sulla caccia attraverso la memoria utilizzando WinDbg:

http://www.codingthewheel.com/archives/extracting- nascosto-text-con-windbg

Modifica 2

Anche in questo caso, non si tratta di campo minato, ma mi ha sicuramente dato alcuni spunti di riflessione per il mio debug di memoria, c'è una ricchezza di tutorial qui:

http://memoryhacking.com/forums/index.php

Inoltre, scarica cheat engine (citato da Nick D.) e di lavoro attraverso il tutorial si tratta con.

  

"In WinDbg posso impostare i punti di interruzione, ma   è difficile per me immaginare a   che punto per impostare un punto di interruzione e al   quale posizione di memoria. Analogamente, quando   Considero il codice statico in IDA Pro, sono   Non sai da dove cominciare, anche per trovare   la funzione o che datastructure   rappresenta il campo minato ".

Esattamente!
Beh, si può guardare per le routine come Random () che verranno chiamati durante la costruzione del tavolo miniere. Questo libro mi ha aiutato molto quando stavo sperimentando con il reverse engineering. :)

In generale, buoni posti per l'impostazione di punti di interruzione sono chiamate a finestre di messaggio, invita a riprodurre un suono, timer e altre routine API Win32.
BTW, sto a scannerizzare campo minato in questo momento con OllyDbg .

Aggiornamento: nemo mi ha ricordato un grande strumento, Trucchi motore da Eric "dark Byte" Heijnen.
Cheat Engine (CE) è un grande strumento per la visione e la modifica di altri processi di spazio di memoria. Al di là che base struttura, CE ha caratteristiche speciali come la visualizzazione della memoria smontato di un processo e l'iniezione di codice in altri processi.
( reale il valore di quel progetto è che si può scaricare il codice sorgente -Delphi- e vedere come sono stati attuati quei meccanismi - ho fatto molti anni fa: o)

Un buon articolo su questo argomento sono disponibili all'indirizzo Uninformed . Esso copre inversione Minesweeper (come introduzione al reverse engineering Win32 apps) in abbastanza grande dettaglio ed è tutto intorno a un grazioso grande risorsa.

Questo sito web potrebbe essere più utile:

http://www.subversity.net/reversing/hacking-minesweeper

Il modo per farlo è:

  1. In qualche modo ottenere il codice sorgente.
  2. Smontare e speranza avanzi di simboli può aiutare.
  3. Indovinare il tipo di dati e cercare di manipolare e utilizzare uno scanner della memoria a limitare le possibilità.

In risposta a Bounty

Beh, in seconda lettura, sembra come se si voleva una guida su come utilizzare un debugger come WinDBG, piuttosto che la solita questione di come decodificare.Ho già mostrato il sito che ti dice i valori è necessario per la ricerca, quindi la domanda è, come si cerca?

Sto usando il blocco note in questo esempio perché non ho Dragamine installato.Ma l'idea è la stessa.

alt text

Si tipo

s <options> <memory start> <memory end> <pattern>

Premere il tasto "?"e poi "s" per vedere la guida in linea.

Una volta trovata la memoria il modello che si desidera, è possibile premere alt+5 per visualizzare il visualizzatore di memoria per un bel display.

alt text

WinDBG prende un po per abituarsi, ma è buono come qualsiasi altro debugger là fuori.

Un buon punto per iniziare la traccia nel debugger sarebbe il mouse verso l'alto. Così trovare procedura di finestra principale (credo strumenti come spyxx può ispezionare finestre proprietà e l'indirizzo di gestore di eventi è uno di loro). Rodare ad esso e trovare dove gestisce gli eventi del mouse - ci sarà un interruttore, se si può riconoscere in assembler (vedi valore del WM_XXX per il mouse in windows.h)

.

Mettere un punto di interruzione e iniziare a fare un passo. Da qualche parte tra il momento in cui rilasciato il pulsante del mouse e schermo in fase di aggiornamento del victum accederà al datastructure che stai cercando.

Sii paziente, cercare di individuare cosa si sta facendo in un dato momento, ma non preoccupatevi guardare troppo in profondità nel codice si sospetta di essere poco interessante per il vostro obiettivo attuale. Si potrebbe prendere diverse piste in debugger per inchiodare giù.

La conoscenza del normale flusso di lavoro di applicazioni Win32 aiuta anche.

Le miniere saranno probabilmente conservati in una sorta di matrice bidimensionale. Ciò significa che è o un array di puntatori o di un singolo array stile C di booleani.

Ogni volta che il modulo riceve un evento mouse-up questa struttura di dati viene fatto riferimento. L'indice verrà calcolato utilizzando la coordinata mouse, probabilmente mediante divisione intera. Ciò significa che probabilmente si dovrebbe cercare un cmp o un'istruzione simile, in cui uno degli operandi viene calcolato utilizzando un offset e x, dove x è il risultato di un calcolo che coinvolge divisione intera. L'offset sarà poi il puntatore all'inizio della struttura dati.

È abbastanza ragionevole supporre che le informazioni relative mine è spiegate in modo contiguo in memoria almeno per righe (cioè è un 2D-array, o una matrice-di-array). Così, proverei aprire più celle adiacenti sulla stessa riga, facendo dump di memoria del processo come vado, e poi li diff e cercare eventuali cambiamenti ripetuti nella regione stessa memoria (cioè 1 byte modifica del primo passo, il successivo byte cambiato esattamente lo stesso valore sul passo successivo, ecc).

C'è anche la possibilità che si tratta di una matrice di bit al sacco (3 bit per miniera dovrebbero essere sufficienti per registrare tutti gli stati possibili - chiuso / aperto, il mio / no-mina, contrassegnato / non contrassegnato), quindi mi piacerebbe guardare fuori per anche questo (i modelli sarebbe anche ripetibile, anche se più difficili da individuare). Ma non è una struttura comoda da affrontare, e non credo che l'utilizzo della memoria è stato un collo di bottiglia per Minesweeper, quindi è improbabile che questo genere di cose sarebbe stato utilizzato.

Anche se non strettamente "strumento di reverse engineering" un, e più di un giocattolo, anche un idiota come me potrebbe utilizzare, controlla cheat Engine . Lo rende un po 'facile rintracciare quali parti della memoria sono cambiate, quando, e ha anche disposizioni per il monitoraggio delle parti di memoria modificata tramite puntatori (anche se probabilmente non avete bisogno di questo). Un bel tutorial interattivo è incluso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top