Wie finde ich die Datenstruktur, die mein Layout von Minesweeper darstellt, im Speicher?


94

Ich versuche, etwas über Reverse Engineering zu lernen, indem ich Minesweeper als Beispielanwendung verwende. Ich habe diesen MSDN-Artikel in einem einfachen WinDbg-Befehl gefunden, der alle Minen enthüllt, aber er ist alt, wird nicht im Detail erklärt und ist wirklich nicht das, wonach ich suche.

Ich habe IDA Pro Disassembler und den WinDbg-Debugger und ich habe winmine.exe in beide geladen. Kann jemand einige praktische Tipps für eines dieser Programme geben, um den Ort der Datenstruktur zu finden, die das Minenfeld darstellt?

In WinDbg kann ich Haltepunkte setzen, aber es fällt mir schwer, mir vorzustellen, an welchem ​​Punkt ein Haltepunkt gesetzt werden soll und an welchem ​​Speicherort. Wenn ich den statischen Code in IDA Pro ansehe, bin ich mir nicht sicher, wo ich überhaupt anfangen soll, die Funktion oder Datenstruktur zu finden, die das Minenfeld darstellt.

Gibt es Reverse Engineers bei Stackoverflow, die mich in die richtige Richtung weisen können?


27
Was für eine großartige Idee für eine Aufgabe für Studenten. Es ist wie ein Anatomielabor mit Minensuchboot als Katze.
Ojblass

3
Für unsere internationalen Leser, die verwirrt sein könnten, ist Minensuchboot die amerikanische Version des Happy Flower Finding-Spiels, das mit Windows Vista geliefert wird. microsoft.blognewschannel.com/index.php/archives/2006/09/28/…
Kip

16
Glückliches Blumenfindungsspiel? O_o Politische Korrektheit ist zu weit gegangen.
Eugene

10
Nun, die Minensuchboot-Version ist zumindest in der schwedischen Version von Vista die Standardeinstellung. Ich nehme an, sie verwenden standardmäßig die Happy-Flowers-Version an Orten, an denen Minen dazu neigen, Kinder in Stücke zu sprengen.
JesperE

1
Also ... nur auf zufällige Felder zu klicken, um zu sehen, ob es sich um Minen handelt, ist dafür nicht hilfreich, oder?
Smandoli

Antworten:


125

Teil 1 von 3


Wenn Sie sich ernsthaft mit Reverse Engineering beschäftigen, vergessen Sie Trainer und Cheat-Engines.

Ein guter Reverse Engineer sollte zuerst das Betriebssystem, die Kernfunktionen der API, die allgemeine Programmstruktur (was ist eine Ausführungsschleife, Windows-Strukturen, Routinen zur Ereignisbehandlung) und das Dateiformat (PE) kennenlernen. Petzolds Klassiker "Programming Windows" können helfen (www.amazon.com/exec/obidos/ISBN=157231995X) sowie Online-MSDN.

Zuerst sollten Sie sich überlegen, wo die Minenfeld-Initialisierungsroutine aufgerufen werden kann. Ich dachte an Folgendes:

  • Wenn Sie das Spiel starten
  • Wenn Sie auf glückliches Gesicht klicken
  • Wenn Sie auf Spiel-> Neu klicken oder F2 drücken
  • Wenn Sie den Schwierigkeitsgrad ändern

Ich beschloss, den F2-Beschleunigerbefehl zu überprüfen.

Um den Code für die Handhabung von Beschleunigern zu finden, müssen Sie die Prozedur für die Behandlung von Fensternachrichten (WndProc) suchen. Es kann durch CreateWindowEx- und RegisterClass-Aufrufe zurückverfolgt werden.

Lesen:

Öffnen Sie das IDA-Fenster "Importe", suchen Sie "CreateWindow *", springen Sie dorthin und verwenden Sie den Befehl "Jump xref to operand (X)", um zu sehen, wo es aufgerufen wird. Es sollte nur einen Anruf geben.

Suchen Sie oben nach der RegisterClass-Funktion und ihrem Parameter WndClass.lpfnWndProc. In meinem Fall habe ich bereits die Funktion mainWndProc benannt.

.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

Drücken Sie die Eingabetaste für den Funktionsnamen (verwenden Sie 'N', um ihn in etwas Besseres umzubenennen).

Nun schauen Sie sich an

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

Dies ist die Nachrichten-ID, die bei Drücken der Taste F2 den Wert WM_COMMAND enthalten sollte. Sie müssen herausfinden, wo es mit 111h verglichen wird. Dies kann entweder durch Aufspüren von edx in IDA oder durch Festlegen eines bedingten Haltepunkts erfolgen in WinDbg und Drücken von F2 im Spiel erfolgen.

So oder so führt zu so etwas

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

Klicken Sie mit der rechten Maustaste auf 111h und verwenden Sie "Symbolische Konstante" -> "Standardmäßige symbolische Konstante verwenden", geben Sie WM_ und Enter ein. Das solltest du jetzt haben

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

Es ist eine einfache Möglichkeit, Nachrichten-ID-Werte herauszufinden.

Informationen zum Handling des Gaspedals finden Sie unter:

Es ist ziemlich viel Text für eine einzelne Antwort. Wenn Sie interessiert sind, kann ich noch ein paar Beiträge schreiben. Langes, kurzes Minenfeld, gespeichert als Array von Bytes [24x36], 0x0F zeigt, dass Byte nicht verwendet wird (kleineres Feld spielen), 0x10 - leeres Feld, 0x80 - Mine.

Teil 2 von 3


Ok, lass uns mit der F2-Taste weitermachen.

Gemäß Verwenden von Tastaturbeschleunigern, wenn die Taste F2 gedrückt wird, wndProc-Funktion

... empfängt eine WM_COMMAND- oder WM_SYSCOMMAND-Nachricht. Das niederwertige Wort des Parameters wParam enthält die Kennung des Beschleunigers.

Ok, wir haben bereits gefunden, wo WM_COMMAND verarbeitet wird, aber wie kann der entsprechende wParam-Parameterwert ermittelt werden? Hier kommt der Resource Hacker ins Spiel. Füttere es mit Binär und es zeigt dir alles. Wie Beschleunigertisch für mich.

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

Sie können hier sehen, dass die F2-Taste 510 in wParam entspricht.

Kommen wir nun zum Code zurück, der WM_COMMAND behandelt. Es vergleicht wParam mit verschiedenen Konstanten.

.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

Verwenden Sie das Kontextmenü oder die Tastenkombination 'H', um Dezimalwerte anzuzeigen, und Sie können unseren Sprung sehen

.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

Es führt zu einem Codeblock, der einen Prozess aufruft und wndProc beendet.

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

Ist das die Funktion, die ein neues Spiel initiiert? Finden Sie das im letzten Teil heraus! Bleib dran.

Teil 3 von 3

Werfen wir einen Blick auf den ersten Teil dieser Funktion

.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

Es gibt zwei Werte (dword_10056AC, uValue), die in die Register eax und ecx eingelesen und mit zwei weiteren Werten verglichen werden (dword_1005164, dword_1005338).

Sehen Sie sich die tatsächlichen Werte mit WinDBG an ('bp 01003696'; bei Pause 'p eax; p ecx') - sie schienen mir Minenfelddimensionen zu sein. Das Spielen mit der benutzerdefinierten Minenfeldgröße zeigte, dass das erste Paar neue Dimensionen und das zweite aktuelle Dimensionen sind. Setzen wir neue Namen.

.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

Wenig später werden neue Werte zum Überschreiben von Strom und Unterprogramm aufgerufen

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

Und als ich es sah

.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

Ich war mir völlig sicher, dass ich ein Minenfeld-Array gefunden habe. Ursache des Zyklus, der ein Array mit einer Länge von 360 Stunden (dword_1005340) mit 0xF einleitet.

Warum 360h = 864? Es gibt einige Hinweise darunter, dass die Zeile 32 Bytes benötigt und 864 durch 32 geteilt werden kann, sodass das Array 27 * 32 Zellen enthalten kann (obwohl die Benutzeroberfläche maximal 24 * 30 Felder zulässt, wird das Array für Ränder mit einem Byte aufgefüllt).

Der folgende Code generiert obere und untere Minenfeldränder (0x10 Byte). Ich hoffe, Sie können Schleifeniteration in diesem Durcheinander sehen;) Ich musste Papier und Stift verwenden

.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

Und der Rest des Unterprogramms zeichnet linke und rechte Grenzen

.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

Durch die intelligente Verwendung von WinDBG-Befehlen erhalten Sie einen coolen Minenfeld-Dump (benutzerdefinierte Größe 9x9). Schauen Sie sich die Grenzen an!

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, es sieht so aus, als würde ich einen weiteren Beitrag brauchen, um das Thema zu schließen


1
@ Stanislav, gute Antwort Stanislav. Wenn Sie es überhaupt näher erläutern können, tun Sie dies bitte. Diese langen, informativen Antworten sind die besten. Vielleicht ein bisschen mehr darüber, wie Sie sich auf die Minenfelddatenstruktur konzentriert haben?
KingNestor

@ Stanislav, ich habe deine Antwort akzeptiert, weil das Kopfgeld von 250 Wiederholungen endete. Herzliche Glückwünsche!
KingNestor

1
@ Stanislav, ich habe Ihre mehrteilige Antwort in eine einzige Antwort umgewandelt. Sie haben die Größenbeschränkung Ihrer einzelnen Antwort nicht erreicht, und ich denke, es wird normalerweise bevorzugt, eine Antwort zu haben, anstatt mehrere zu posten. Sie können Ihre ursprüngliche Antwort (diese) jederzeit bearbeiten und nach Belieben ergänzen.
mmcdole

2
Auch epische Antwort Stanislav. Vielen Dank für Ihre harte Arbeit!
mmcdole

15

Es scheint, als würden Sie versuchen, die Quelle zu zerlegen, aber Sie müssen sich nur den Speicherplatz des laufenden Programms ansehen. Der Hex-Editor HxD verfügt über eine Funktion, mit der Sie genau das tun können .

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

Sobald Sie sich im Speicherbereich befinden, müssen Sie Schnappschüsse des Speichers erstellen, während Sie mit dem Board herumspielen. Isolieren Sie, was sich ändert und was nicht. Wenn Sie der Meinung sind, dass Sie wissen, wo sich die Datenstruktur im Hex-Speicher befindet, versuchen Sie, sie zu bearbeiten, während sie sich im Speicher befindet, und prüfen Sie, ob sich die Karte dadurch ändert.

Der gewünschte Prozess ist nicht anders als der Aufbau eines "Trainers" für ein Videospiel. Diese basieren normalerweise darauf, herauszufinden, wo Werte wie Gesundheit und Munition im Gedächtnis leben, und sie im laufenden Betrieb zu ändern. Möglicherweise finden Sie einige gute Tutorials zum Erstellen von Spieltrainern.


2
Nun, Sie können den Speicherort durch statische Demontage lokalisieren. Sie können den Montageanweisungen folgen, um nach Funktionen wie rand () zu suchen, die aufgerufen werden, um das Minenfeld zu generieren, und dann von dort aus nachverfolgen, an welcher Stelle das Feld im Speicher gespeichert ist (und wie).
mmcdole

Beide Ansätze sind herausfordernd. Ich habe in der Vergangenheit versucht, Anwendungen zu zerlegen, und ich fand es sehr schmerzhaft. Wie genau erkennen Sie eine rand () - Funktion?
James McMahon

Vielen Dank für Ihre Antwort nemo.
KingNestor

11

Schauen Sie sich diesen Artikel zum Codeprojekt an, er ist etwas ausführlicher als der von Ihnen erwähnte Blog-Beitrag.

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

Bearbeiten

Und dieser Artikel, obwohl nicht direkt über Minensuchboot, gibt Ihnen eine gute Schritt-für-Schritt-Anleitung zum Durchsuchen des Speichers mit WinDbg:

http://www.codingthewheel.com/archives/extracting-hidden-text-with-windbg

Bearbeiten 2

Auch hier geht es nicht um Minensuchboot, aber es hat mir definitiv einige Denkanstöße für mein Speicher-Debugging gegeben. Hier gibt es eine Fülle von Tutorials:

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

Laden Sie auch CheatEngine (von Nick D. erwähnt) herunter und arbeiten Sie das mitgelieferte Tutorial durch.


9

"In WinDbg kann ich Haltepunkte setzen, aber es fällt mir schwer, mir vorzustellen, an welchem ​​Punkt und an welchem ​​Speicherort ein Haltepunkt gesetzt werden soll. Wenn ich den statischen Code in IDA Pro ansehe, bin ich mir nicht sicher, wo ich überhaupt anfangen soll um die Funktion oder Datenstruktur zu finden, die das Minenfeld darstellt. "

Genau!

Nun, Sie können nach Routinen wie random () suchen, die während der Erstellung der Minentabelle aufgerufen werden. Dieses Buch hat mir sehr geholfen, als ich mit Reverse Engineering experimentiert habe. :) :)

Gute Orte zum Setzen von Haltepunkten sind im Allgemeinen Aufrufe von Meldungsfeldern, Aufrufe zum Abspielen eines Sounds, Timer und andere Win32-API-Routinen. Übrigens scanne

ich gerade mit OllyDbg Minensuchboot .

Update: nemo erinnerte mich an ein großartiges Tool, Cheat Engine von Eric "Dark Byte" Heijnen.

Cheat Engine (CE) ist ein großartiges Tool zum Beobachten und Ändern des Speicherplatzes anderer Prozesse. Über diese grundlegende Funktion hinaus verfügt CE über weitere spezielle Funktionen wie das Anzeigen des zerlegten Speichers eines Prozesses und das Einfügen von Code in andere Prozesse.

(Der wahre Wert dieses Projekts besteht darin, dass Sie den Quellcode -Delphi- herunterladen und sehen können, wie diese Mechanismen implementiert wurden - das habe ich vor vielen Jahren getan: o)


5

Ein ziemlich guter Artikel zu diesem Thema ist bei Uninformed zu finden . Es behandelt das Umkehren von Minesweeper (als Einführung in das Reverse Engineering von Win32-Apps) sehr detailliert und ist eine großartige Ressource.


4

Diese Website könnte hilfreicher sein:

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

Der allgemeine Weg, dies zu tun, ist:

  1. Irgendwie Quellcode bekommen.
  2. Zerlegen und hoffen Sie, dass übrig gebliebene Symbole Ihnen helfen können.
  3. Erraten Sie den Datentyp und versuchen Sie, ihn zu manipulieren. Verwenden Sie einen Speicherscanner, um die Möglichkeiten einzuschränken.

Als Antwort auf Bounty

Nun, in einer zweiten Lesung scheint es, als wollten Sie eine Anleitung zur Verwendung eines Debuggers wie WinDBG anstelle der üblichen Frage zum Reverse Engineering. Ich habe Ihnen bereits die Website gezeigt, auf der die Werte angegeben sind, nach denen Sie suchen müssen. Die Frage ist also, wie suchen Sie danach?

In diesem Beispiel verwende ich Notepad, da Minesweeper nicht installiert ist. Aber die Idee ist dieselbe.

Alt-Text

Du tippst

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

Drücken Sie "?" Und dann "s", um die Hilfe anzuzeigen.

Sobald Sie das gewünschte Speichermuster gefunden haben, können Sie Alt + 5 drücken, um den Speicher-Viewer für eine schöne Anzeige aufzurufen.

Alt-Text

WinDBG ist gewöhnungsbedürftig, aber es ist so gut wie jeder andere Debugger da draußen.


1
"Irgendwie Quellcode bekommen" ist eine dumme Aussage, da Minesweeper ohne Quelle gesendet wird. Und Reverse Engineering mit Quelle ist kein Reverse Engineering ... es ist eine Quellcode-Analyse.
Mrduclaw

@mrduclaw Es gibt Anwendungen, die Assembly in die Ausgangssprache dekompilieren können. Es gibt keinen Begriff namens "Quellcode-Analyse".
Unbekannt

1
@Unbekannt Es gibt Anwendungen, die versuchen, ein Programm in einer Ausgangssprache aus einer bestimmten kompilierten Binärdatei zu rekonstruieren. Sie können jedoch keinen "Quellcode" mit den Kommentaren und Zitaten des Autors aus einer kompilierten Binärdatei erhalten. Sicher, einige dieser "Dekompilierer" machen einen besseren Job als andere, aber sie geben Ihnen nicht den Code, den der Autor geschrieben hat (compileroptimierter Code unterscheidet sich oft stark vom Code des Programmierers). Und haben Sie noch nie Qualitätssicherungstests durchgeführt? Was machen Tools wie PREfast und Sparse? Statische Quellcode-Analyse.
Mrduclaw

Die statische Quellcode-Analyse in PREfast und Sparse unterscheidet sich grundlegend vom manuellen Lesen dekompilierten Codes, um ihn zu hacken. Ich glaube nicht, dass irgendjemand diese beiden unterschiedlichen Ideen miteinander verwechseln würde.
Unbekannt

@Unbekannt Ich gehe noch einen Schritt weiter und stimme zu, dass Sie Reverse Engineering Disassembly nicht mit dem Betrachten von Quellcode verwechseln sollten (dekompiliert oder auf andere Weise, wenn Sie die Quelle haben, für die Sie eine Quellcode-Analyse durchführen). Das war mein ganzer Punkt. Also bitte hör auf, die beiden zu verwechseln. :)
Mrduclaw

0

Ein guter Punkt, um mit der Ablaufverfolgung im Debugger zu beginnen, ist die Maus hoch. Finden Sie also die Hauptfensterprozedur (ich denke, Tools wie spyxx können die Fenstereigenschaften überprüfen, und die Adresse des Ereignishandlers ist eine davon). Brechen Sie ein und finden Sie heraus, wo Mausereignisse behandelt werden - es wird einen Schalter geben, wenn Sie ihn im Assembler erkennen können (sehen Sie sich den Wert von WM_XXX für die Maus in windows.h an).

Setzen Sie dort einen Haltepunkt und treten Sie ein. Irgendwann zwischen dem Loslassen der Maustaste und dem Aktualisieren des Bildschirms greift das Opfer auf die gesuchte Datenstruktur zu.

Seien Sie geduldig, versuchen Sie herauszufinden, was zu einem bestimmten Zeitpunkt getan wird, aber schauen Sie nicht zu tief in den Code, von dem Sie vermuten, dass er für Ihr aktuelles Ziel uninteressant ist. Es kann mehrere Läufe im Debugger dauern, um es festzunageln.

Kenntnisse über den normalen Workflow von Win32-Anwendungen sind ebenfalls hilfreich.


0

Die Minen werden wahrscheinlich in einer Art zweidimensionaler Anordnung gelagert. Dies bedeutet, dass es sich entweder um ein Array von Zeigern oder um ein einzelnes Array von Booleschen Werten im C-Stil handelt.

Immer wenn das Formular ein Mouse-Up-Ereignis empfängt, wird auf diese Datenstruktur verwiesen. Der Index wird unter Verwendung der Mauskoordinate berechnet, wahrscheinlich unter Verwendung einer Ganzzahldivision. Das bedeutet, dass Sie wahrscheinlich nach einer cmpoder einer ähnlichen Anweisung suchen sollten , bei der einer der Operanden mit einem Offset berechnet wird und xbei der xdas Ergebnis einer Berechnung mit ganzzahliger Division ist. Der Offset ist dann der Zeiger auf den Anfang der Datenstruktur.


0

Es ist ziemlich vernünftig anzunehmen, dass Informationen über Minen zumindest für Zeilen zusammenhängend im Speicher angeordnet sind (dh es handelt sich um ein 2D-Array oder ein Array von Arrays). Daher würde ich versuchen, mehrere benachbarte Zellen in derselben Zeile zu öffnen, Speicherauszüge des Prozesses zu erstellen, diese dann zu differenzieren und nach sich wiederholenden Änderungen in demselben Speicherbereich zu suchen (dh 1 Byte wurde im ersten Schritt, im nächsten geändert Byte im nächsten Schritt auf genau denselben Wert geändert usw.).

Es besteht auch die Möglichkeit, dass es sich um ein gepacktes Bit-Array handelt (3 Bits pro Mine sollten ausreichen, um alle möglichen Zustände aufzuzeichnen - geschlossen / offen, Mine / keine Mine, markiert / nicht markiert), also würde ich auch darauf achten ( Die Muster wären auch wiederholbar, wenn auch schwerer zu erkennen. Aber es ist keine bequeme Struktur, mit der man sich befassen muss, und ich glaube nicht, dass die Speichernutzung ein Engpass für Minesweeper war, daher ist es unwahrscheinlich, dass so etwas verwendet wird.


0

Cheat Engine ist zwar nicht unbedingt ein "Reverse Engineer's Tool" und eher ein Spielzeug, das selbst ein Idiot wie ich benutzen könnte . Es macht es etwas einfach zu verfolgen, welche Teile des Speichers sich wann geändert haben, und es gibt sogar Vorkehrungen zum Verfolgen der geänderten Speicherteile durch Zeiger (obwohl Sie das wahrscheinlich nicht benötigen). Ein schönes interaktives Tutorial ist enthalten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.