Dieses kleine Tutorial soll Schritt für Schritt zeigen, wie sich DMA überwinden lässt.
Als Beispiel muss hier Icy Tower (
) herhalten.Wir wollen ein Tool schreiben, das den aktuellen Punktestand ausliest.
Tools Of The Trade
UPX -

OllyDbg -

PEiD -

TSearch -

Finde die Adresse!
Wir starten IcyTower, springen rum und sehen unsere Punkte links unten.
Nun starten wir TSearch, suchen nach einem 4-Byte-Integer mit der jeweiligen Punktzahl und finden sogar eine Adresse.
Wir behalten diese nun im Auge, während wir in Icy Tower weiter rumhüpfen und sehen, dass insbesondere bei Combos die Adresse nicht mehr den Punktewert repräsentiert. Vermutlich haben wir hier nur eine temporäre Variable für was auch immer gefunden, die meistens (aber nicht immer) die Punktezahl enthält. Auf jeden Fall ist sie nicht das, was wir suchen.
Wie könnten die Punkte noch gespeichert sein? Wenn wir am Anfang rumspringen ist die Punktezahl ein Mehrfaches von 10, also suchen wir doch einfach mal nach einem Zehntel der Zahl! Wenn wir also 50 Punkte haben, suchen wir eine 5, haben wir 20 Punkte eine 2 und auch dieses Mal werden wir fündig. Wieder springen wir in Icy Tower herum und beobachten dabei die Adresse in TSearch und die Speicherstelle sieht gut aus.
Die gefundene Adresse schreiben wir also auf und starten Icy Tower neu, gleiches Spiel, Adresse suchen und wieder finden wir eine - doch diese ist anders als die erste. Hrm, Icy Tower arbeitet mit DMA.
Da muss wohl doch OllyDbg her.
Zwischenspiel
Wir beenden Icy Tower und TSearch und starten IcyTower.exe über OllyDbg. Beim Starten sagt uns OllyDbg, dass was nicht stimmt und vermutet, es handelt sich um eine gepackte .exe. Oshit. Wenn wir jetzt an ASProtect oder Konsorten geraten wird das ganze richtig hässlich. Also starten wir PEiD und scannen die .exe und freuen uns - PEiD findet UPX, einen Packer (kein Crypter!), der dazu Open Source ist und problemlos mit offiziellen Tools entpackt werden kann.
Mit UPX entpacken wir also die .exe (vorher Icy Tower schließen, gibt sonst "Permission denied")
Dazu öffen wir eine Konsole und geben ein (Console version von UPX saugen, in system32 packen und fortan überall verwendbar wie ping, tracert usw.):
Code:
upx -d icytower13.exe
Jetzt aber.
Nachdem wir nun eine ordentliche .exe haben, starten wir erneut Icy Tower über OllyDbg, F9 drücken und Icy Tower rennt.
Jetzt suchen wir noch ein weiteres Mal die Adresse für die Punkte indem wir TSearch wieder auf icytower13.exe attachen.
In meinem Fall ist das gerade die 0x215CF70 und wird sehr warscheinlich bei dir anders sein. Aufschreiben.
Wir wechseln in OllyDbg in das "Hex Dump"-Fenster unten links, drücken Strg+G und geben die gefundene Adresse ein. OllyDbg springt nun zu dieser Adresse im Speicher. Wir klicken den 1. Punkt im Fenster an, dann Rechtsklick und wählen
"Breakpoint" -> "Memory, on write". Sofort breakt OllyDbg an folgender Stelle:
Code:
MOV DWORD PTR DS:[EAX+28],EBX
Zwei Zeilen über dieser Zeile sehen wir eine MOV-Instruktion, die EAX füllt, und zwar
Code:
MOV EAX,DWORD PTR DS:[ECX*4+4CB920]
Code:
MOV ECX,DWORD PTR DS:[4CB908]
Der Code
Ich möchte an dieser Stelle lediglich den kommentierten Code anbieten, da hier das wohl das Beste ist.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(int argc, char *argv[])
{
HWND hwnd;
DWORD hProcessId;
HANDLE hProcess;
int *p;
unsigned int addr1;
unsigned int addr2;
unsigned int addr3;
int scoreaddr;
int score;
//Wir brauchen ein Handle zum Icy Tower-Fenster,
//das finden wir über dessen Titel
hwnd = FindWindow(NULL,"Icy Tower v1.3.1");
if(!hwnd)
{
printf("Icy Tower nicht gefunden!\n");
return -1;
}
//Nun brauchen wir die zum Fenster gehörende Prozess-ID
GetWindowThreadProcessId(hwnd,&hProcessId);
//Nun müssen wir Zugriffsrechte zum Prozess erhalten und ihn öffnen
hProcess = OpenProcess(PROCESS_ALL_ACCESS,0,hProcessId);
/*
Mit dem Handle können wir endlich arbeiten.
zur Erinnerung, wir haben diese drei Zeilen gefunden:
MOV ECX,DWORD PTR DS:[4CB908]
MOV EAX,DWORD PTR DS:[ECX*4+4CB920]
MOV DWORD PTR DS:[EAX+28],EBX
und wir möchten nichts anderes machen, als EAX+28 zu berechnen, machen
also im Prinzip das Gleiche nach!
*/
//Also lesen wir nun den Wert an der Stelle 0x4CB908 aus und haben effektiv ECX
ReadProcessMemory(hProcess,(void*)0x4CB908,(void*)&addr1,4,0);
printf("Ausgelesener Wert: 0x%x\n",addr1);
//Jetzt berechnen wir daraus die 2. Adresse (ECX*4+4CB920)
addr2 = addr1*4+0x4CB920;
//Von dieser wiederum lesen wir nun EAX aus.
ReadProcessMemory(hProcess,(void*)addr2,(void*)&addr3,4,0);
//Und der Punktestand befindet sich bei EAX+28, was addr3+0x28 entspricht:
printf("Speicheradresse fuer Puntkestand: 0x%x\n",addr3+0x28);
while(1)
{
Sleep(1000);
//Lies 4 Byte von der Speicheradresse der Punkte aus
ReadProcessMemory(hProcess,(void*)(addr3+0x28),(void*)&score,4,0);
printf("Current score: %d\n",score*10);
}
return 0;
}
Wer das Programm testet, stellt fest, dass das Programm nicht genau den Punktestand ausgibt und das ist auch richtig so. Wie mir scheint, haben wir es hier mit einem etwas komplizierteren Punktesystem zutun. Icy Tower speichert die Combo-Punkte getrennt von den reinen Höhen-Punkten und was wir hier ausgeben und herausgefunden haben ist lediglich der Speicherort für eben jene Höhen-Punkte. Aber diese funktionieren einwandfrei und Sinn des Tutorials war es, DMA zu überlisten was uns auch gelungen ist. Wer mag, kann ja an der wirklich echten Punktezahl arbeiten.
EOF.






