Wie finde ich die Datenstruktur, die für mine layout von Minesweeper in Erinnerung?
-
06-09-2019 - |
Frage
Ich bin versucht zu lernen, über reverse-engineering, mit Minesweeper, wie Sie eine Beispielanwendung.Ich habe dies gefunden MSDN-Artikel auf eine einfache WinDbg-Befehl, der zeigt, alle die Minen, aber es alt ist, wird nicht erläutert, in jedem detail und ist wirklich nicht das, was ich Suche.
Ich habe IDA Pro disassembler und die WinDbg-debugger und ich habe geladen winmine.exe in beiden von Ihnen.Kann jemand einige praktische Tipps für die entweder diese Programme in Hinblick auf die Suche nach dem Speicherort der Daten-Struktur, stellt das Bergwerk-Feld?
In WinDbg, ich kann breakpoints setzen, aber es ist schwierig für mich, mir vorzustellen, an welcher Stelle einen breakpoint zu setzen und zu welchem Speicherort.Ebenso, wenn ich eine statische code in IDA Pro, ich bin mir nicht sicher, wo Sie beginnen sogar zu finden, die die Funktion oder Struktur der Daten, die für die mine-Feld.
Gibt es irgendwelche Reverse Engineers auf Stackoverflow, die können zeigen Sie mich in die richtige Richtung?
Lösung
Teil 1 von 3
Wenn Sie ernsthaft in reverse-engineering - vergessen-Trainer und cheat-engines.
Gute reverse engineer, sollte zunächst wissen, OS, core-API-Funktionen, - Programm-Allgemeine Struktur (was ist run loop, windows Strukturen, event-handling-Routinen), Datei-format (PE).Petzold ' s classics "Windows-Programmierung" kann helfen (www.amazon.com/exec/obidos/ISBN=157231995X) sowie online-MSDN.
Zunächst sollten Sie überlegen, wo Minenfeld Initialisierungsroutine aufgerufen werden kann.Ich dachte an Folgendes:
- Wenn Sie das Spiel starten
- Wenn Sie auf glückliches Gesicht
- Wenn Sie auf Spiel->Neu oder drücken Sie F2
- Wenn Sie ändern Schwierigkeitsgrad
Ich beschloss zu prüfen, F2 accelerator Befehl.
Zu finden accelerator-handling-code, den Sie finden Fenster, message-handling-Verfahren (WndProc).Es können verfolgt werden nach unten durch CreateWindowEx und RegisterClass Aufrufe.
Zu Lesen:
- CreateWindowEx http://msdn.microsoft.com/en-us/library/ms632680%28VS.85%29.aspx
- RegisterClass http://msdn.microsoft.com/en-us/library/ms633586%28VS.85%29.aspx
- Petzold Kapitel 3 "Windows und Nachrichten"
Öffnen IDA, Importe Fenster, finden die "CreateWindow*" springen und mit "Jump xref an operand (X)" - Befehl, um zu sehen, wo es aufgerufen wird.Es sollte nur ein Anruf.
Jetzt schauen Sie oben für RegisterClass Funktion und parameter WndClass.lpfnWndProc.Ich habe bereits benannt function mainWndProc in meinem Fall.
.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 auf Funktion name (mit 'N', um Sie umzubenennen, um etwas besseres)
Nun nehmen Sie einen Blick auf
.text:01001BCF mov edx, [ebp+Msg]
Dies ist die message-id, die im Falle der F2-Taste drücken soll enthalten WM_COMMAND Wert.Sie sind zu finden, wo es ist im Vergleich zu 111h.Es kann getan werden entweder durch die Verfolgung down edx in IDA oder durch Einstellung bedingten Haltepunkt in WinDbg, und drücken Sie F2 in das Spiel.
Entweder Weg führt zu etwas wie
.text:01001D5B sub eax, 111h
.text:01001D60 jz short loc_1001DBC
Klicken Sie rechts auf 111h und "Symbolische Konstante" -> "Verwenden Sie ein standard-symbolische Konstante", geben Sie WM_ und Enter.Sollten Sie jetzt haben
.text:01001D5B sub eax, WM_COMMAND
.text:01001D60 jz short loc_1001DBC
Es ist eine einfache Möglichkeit, um herauszufinden, message-id-Werten.
Um zu verstehen, accelerator Umgang check out:
- Mithilfe Von Zugriffstasten
- Resource hacker (http://angusj.com/resourcehacker/)
Es ist ziemlich viel text für eine einzige Antwort.Wenn Sie interessiert sind, ich kann schreiben, ein paar Beiträge.Lange Geschichte kurz Minenfeld gespeichert werden als ein array von bytes [24x36], 0x0F, zeigt dieses byte wird nicht verwendet (auf vielen kleineren Feld), 0x10 - leer-Feld, 0x80 - mine.
Teil 2 von 3
Ok, lass uns gehen mit der F2-Taste.
Nach Mithilfe Von Zugriffstasten wenn die F2-Taste gedrückt wird wndProc-Funktion
...erhält eine WM_COMMAND-oder WM_SYSCOMMAND Nachricht.Das niederwertige Wort des wParam-parameter enthält die Kennung des Gaspedals.
Ok, wir haben schon gefunden, wo WM_COMMAND verarbeitet wird, aber wie Sie feststellen entsprechenden wParam-parameter-Wert?Dies ist, wo Resource hacker ins Spiel kommt.Füttern Sie es mit Binär-und es zeigt Ihnen alles, was.Wie Beschleuniger Tabelle für mich.
alt-text http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg
Hier können Sie sehen, dass die F2-Taste entspricht 510, wParam.
Jetzt kommen wir zurück zu code verarbeitet WM_COMMAND.Es vergleicht wParam mit unterschiedlichen 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 im Kontext-Menü oder " H " - Tastenkombination zum anzeigen von Dezimalzahlen und Sie können sehen, unser springen
.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 code-Block ruft einige proc-und Ausfahrten wndProc.
.text:01001EC8 loc_1001EC8: ; CODE XREF: mainWndProc+20Fj
.text:01001EC8 call sub_100367A ; startNewGame ?
.text:01001EC8
.text:01001ECD jmp callDefAndExit ; default
Ist, dass die Funktion, initiiert neue Spiel?Finden Sie heraus, dass im letzten Teil!Stay tuned.
Teil 3 von 3
Werfen wir einen Blick auf den ersten Teil der 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) Lesen Sie in Register eax und ecx und im Vergleich zu anderen zwei Werte (dword_1005164, dword_1005338).
Werfen Sie einen Blick auf die tatsächlichen Werte mit WinDBG ('bp 01003696';in der Pause 'p eax;p ecx") - es schien, als Minenfeld Dimensionen für mich.Spielen mit benutzerdefinierten Minenfeld Größe zeigte, das erste paar sind, neue Dimensionen und zweite - aktuelle Dimensionen.Lassen Sie uns den neuen 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
Ein wenig später neue Werte überschreiben die aktuelle 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 völlig sicher, dass ich es gefunden Minenfeld array.Ursache des Zyklus die inits 360h bytes Länge array (dword_1005340 ) mit 0xF.
Warum 360h = 864?Es gibt einige Hinweise unterhalb dieser Zeile dauert 32 bytes 864 werden können, geteilt durch 32, so-array halten kann 27*32 Zellen (obwohl UI können max 24*30 Feldes, es ist ein byte Polsterung um array-Grenzen).
Folgende code erzeugt Minenfeld oberen und unteren Grenzen (0x10 byte).Ich hoffe, Sie können sehen, Schleife iteration in das Chaos ;) ich musste einfach mit Papier und Stift
.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 den rest der Unterroutine zieht Links und rechts 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
Smart Verwendung von WinDBG-Befehle können bieten Sie kühlen Minenfeld dump (benutzerdefinierte Größe 9x9).Überprüfen Sie heraus die Grenzen!
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, sieht aus wie werde ich brauchen, ein weiterer Beitrag um das Thema zu schließen
Andere Tipps
Es scheint, wie Sie versuchen zu zerlegen die Quelle aber, was Sie tun müssen, ist, sich die Speicher Raum des Laufenden Programms.Das hex-editor HxD hat eine Funktion, mit der Sie genau das.
Sobald Sie in den Speicher, es ist eine Frage der Schnappschüsse der Erinnerung, während Sie Durcheinander herum mit die Bord.Isolieren, was sich ändert und was nicht.Wenn Sie denken, Sie haben einen Griff auf, wo die Daten-Struktur liegt in hex Gedächtnis, versuchen Sie, es zu editieren, während es in den Speicher und sehen, ob das board Veränderungen als Folge.
Der Prozess, den Sie wollen, ist nicht anders als die Errichtung einer "trainer" für ein Videospiel.Diese basieren in der Regel auf der Suche nach wo Werte wie Gesundheit und Munition Leben in Erinnerung und verändern Sie Sie im Handumdrehen.Sie können in der Lage sein zu finden, einige gute tutorials auf, wie zu bauen Spiel-Trainer.
Check out this code project Artikel, es ist ein wenig mehr in die Tiefe als der blog-Beitrag, den Sie erwähnt.
http://www.codeproject.com/KB/trace/minememoryreader.aspx
Bearbeiten
Und dieser Artikel, obwohl Sie nicht über minesweeper direkt, gibt Ihnen eine gute Schritt für Schritt Anleitung, die Jagd durch Speicher mit WinDbg:
http://www.codingthewheel.com/archives/extracting-hidden-text-with-windbg
Bearbeiten 2
Wieder, dies ist nicht etwa minesweeper, aber es hat sich auf jeden Fall mir ein paar Denkanstöße für meine Speicher-debugging, gibt es eine fülle von tutorials hier:
http://memoryhacking.com/forums/index.php
Laden Sie außerdem CheatEngine (erwähnt von Nick D.) und arbeiten Sie durch das tutorial kommt mit.
"In WinDbg ich kann breakpoints setzen, aber es ist für mich schwierig zu vorstellen was ist der Punkt, um einen Haltepunkt zu setzen und zu was Speicherort.Ähnlich, wenn Ich sehe die statische code in IDA Pro, ich bin nicht sicher, wo zu beginnen, auch zu finden die Funktion oder datastructure, dass stellt das Bergwerk-Feld."
Genau!
Auch Sie können suchen Routinen wie random (), die aufgerufen wird, während der Bau der Minen-Tabelle.Diese Buch hat mir sehr geholfen, wenn ich war das Experimentieren mit reverse engineering.:)
Im Allgemeinen, gute Plätze für die Einstellung Pause Punkte sind Anrufe in message-Boxen, Anrufe zu spielen eine sound, Timer und andere win32-API-Routinen.
BTW, ich bin Scannen minesweeper jetzt mit OllyDbg.
Update: nemo erinnerte mich ein großartiges Werkzeug, Cheat Engine von Eric "Dark Byte" Heijnen.
Cheat Engine (CE), ist ein großes Werkzeug für das ansehen und ändern von andere Prozesse Speicher.Darüber hinaus basic Anlage, CE hat mehr spezielle Funktionen wie die Anzeige der geordneten Speicher eines Prozesses und die Injektion von code in andere Prozesse.
(die real Wert der Projekt ist, können Sie den Quellcode herunterladen -Delphi - und sehen Sie, wie diese Mechanismen umgesetzt werden konnten - ich habe das vor vielen Jahren :o)
Einen ziemlich guten Artikel über dieses Thema finden Sie unter Uninformiert.Es deckt Umkehrung Minesweeper (als Einführung in reverse engineering Win32-apps) in ziemlich großem detail und ist rundum eine ziemlich große Ressource.
Diese website hilfreich:
http://www.subversity.net/reversing/hacking-minesweeper
Der Allgemeine Weg zu gehen über das tun dies ist:
- Irgendwie bekommt-source-code.
- Zerlegen und hoffen übrig gebliebenen Symbole, die Ihnen helfen können.
- Erraten Sie den Daten-Typ und versuchen, Sie zu manipulieren und einen memory-scanner zu begrenzen die Möglichkeiten.
In Reaktion auf Bounty
Gut, auf eine zweite Lesung, scheint es, als wollten Sie eine Anleitung, wie man einen debugger wie WinDBG, statt der üblichen Frage, wie man reverse Engineering.Ich habe bereits gezeigt, Ihnen die website, die Ihnen sagt, dass die Werte, die Sie benötigen, zu suchen, die Frage ist also, wie tun Sie suchen für es?
Ich bin mit dem Editor in diesem Beispiel, weil ich nicht haben, Minesweeper installiert.Aber die Idee ist die gleiche.
Sie geben
s <options> <memory start> <memory end> <pattern>
Drücken Sie "?"und dann "s" zu sehen, die helfen.
Sobald Sie gefunden haben, die memory-Muster, das Sie wollen, Sie können drücken Sie dann alt+5 zu bringen, bis die memory viewer für eine schöne Anzeige.
WinDBG ist gewöhnungsbedürftig, aber es ist genauso gut wie jeder andere debugger gibt.
Ein guter Punkt zum starten der Ablaufverfolgung im debugger auf der Maus nach oben.So finden Hauptfenster Verfahren (ich denke tools wie spyxx überprüfen können, windows-Eigenschaften und event-handler-Mail-Adresse von Ihnen).Unterbrechen Sie es und finden, wo es Griffe Maus-events -- es wird ein Schalter, wenn Sie erkennen können es in assembler (Blick auf den Wert WM_XXX für die Maus in windows.h).
Setzen Sie es einen Haltepunkt und starten stepping in.Irgendwo zwischen der Zeit, die Sie veröffentlicht Maus-Taste und der Bildschirm aktualisiert wird die victum Zugriff auf die datastructure, die Sie suchen.
Seien Sie geduldig, versuchen Sie zu ermitteln, was getan wird, zu jeder Zeit, aber nicht die Mühe der Suche zu tief in die code Sie vermuten, der uninteressant für Ihr Aktuelles Ziel.Es kann dauern, mehrere Läufe im debugger to nail it down.
Kenntnisse der normalen win32-Anwendungen workflow hilft auch.
Die Minen wahrscheinlich wird gespeichert werden in eine Art von zwei-dimensionales array.Dies bedeutet, dass es entweder ein array von Zeigern oder eine einzelne C-Stil-array von booleans.
Wenn das Formular mit einem mouse-up-Ereignis, diese Datenstruktur wird verwiesen.Der index wird berechnet, indem man die Maus-Koordinaten, wohl mit integer-division.Das bedeutet, dass Sie wahrscheinlich Aussehen für eine cmp
oder eine ähnliche Anweisung, wo einer der Operanden berechnet einen offset und x
, wo x
ist das Ergebnis einer Berechnung mit integer-division.Der offset wird dann der Zeiger auf den Anfang der Daten-Struktur.
Es ist ziemlich vernünftig anzunehmen, dass Informationen über Minen gelegt aus im Speicher zusammenhängend mindestens für die Zeilen (d.h.es ist ein 2D-array oder ein array von arrays).Also, ich würde versuchen, öffnen mehrere angrenzende Zellen in der gleichen Zeile, so dass Speicherabbilder des Prozesses, wie ich gehe, und dann diff Ihnen und suchen nach einer sich wiederholenden Veränderungen in der gleichen Speicherbereich (d.h.1 byte geändert am ersten Schritt, das nächste byte geändert, um exakt denselben Wert für den nächsten Schritt, etc).
Es gibt auch die Möglichkeit, dass es eine gepackte bit-array (3 bits pro mine sollte ausreichend sein, um den Datensatz aller möglichen Staaten, geschlossen/offen, mine/no-mine, markiert/nicht markiert), so würde ich schauen, dass auch (die Muster würde auch wiederholbar sein, obwohl schwieriger zu erkennen).Aber es ist nicht eine praktische Struktur zu behandeln, und ich glaube nicht, dass die Speicherauslastung war ein Engpass für Minesweeper, so ist es unwahrscheinlich, dass diese Art von Dingen verwendet werden würde.
Während nicht streng ein "reverse-engineer 's tool", und eher ein Spielzeug selbst ein idiot wie ich verwenden konnte, check out Cheat Engine.Es macht es ein wenig einfach zu verfolgen, welche Teile des Speichers geändert haben, wenn, und hat sogar Vorschriften für die überwachung des geänderten Speicher-Teile über Zeiger (obwohl Sie wahrscheinlich nicht brauchen werden).Ein schönes interaktives Lernprogramm enthalten ist.