Problem mit DMA

05/22/2011 14:15 Riches#1
Hey Leute,

ich hoffe, ihr könnt mir bei meinem kleinen (Verständnis-)Problem weiterhelfen.

Worum gehts?
Ich versuche DMA durch Code Injection auszutricksen. Leider hab ich ein kleines Problem mit der wechselnden Position des Gamecodes im Speicher.

Nehmen wir als Beispiel das Flash-Game Multitask 2. Dort will ich die abgelaufene Zeit freezen (Ich weiß, es macht keinen Sinn, ist jetzt nur ein Beispiel). Da diese Variable wohl dynamisch allociert (DMA) wird, versuche ich den entsprechenden Inkrementierungscode zu NOPpen. Dabei gehe ich wie folgt vor:
  1. Finden der Adresse mit CE (Die Zeit ist hier eine Doublevariable)
  2. Breakpoint-on-write auf die Variable
  3. Disassemblieren der gefunden Codestelle
  4. AusNoppen der betreffenden Zeile

So, das klappt soweit so gut.
Mein Problem hier ist jedoch (wie angekündigt), dass die Speicheradresse des Codes bei jedem Neustart (des Games) sich verändert und ich die oben erwähnten Schritte erneut ausführen muss.

Ich hab mehrere DMA-Tutorials durchgelesen. In jedem davon war die Rede, dass die Variablen dynamisch allociert werden, der Gamecode hingegen jedoch statisch ist.

Das ist jedoch ein Widerspruch zu dem, was ich jetzt vorliegen habe.

Wie muss man diese Aussage "der Gamecode ist statisch" verstehen?
  • Heisst es, dass er eine feste Position im Ram oder im Virtual Memory des PCs hat? (Das macht für mich keinen Sinn, da Windows das Programm doch da reinlädt, wo gerade Platz ist, oder?)
  • Oder heisst es, dass er ein festes Offset zur Startadresse des Games hat? Also beispielsweise Game.exe+0x00000034.
  • oder lieg ich mit beidem total daneben?

Wie kann ich im zweiten Fall die Startadresse herausfinden? Das finden des Offsets dürfte dann ja kein Problem sein.

Ich hoffe ihr könnt mir weiterhelfen.

Grüße,
Riches
05/22/2011 18:08 5769854332#2
Quote:
da Windows das Programm doch da reinlädt, wo gerade Platz ist, oder?
Das Programm wird an die ImageBase Addresse geladen (die steht im PE Header des Programms und ist bei .exe Dateien meistens 0x400000).

Nur bestimmte Dlls werden an zufällige Addressen geladen (ab vista, [Only registered and activated users can see links. Click Here To Register...]).

Evtl. hast du Code einer Dll verändert?
In welcher Sprache ist das Programm geschrieben, VB?
05/22/2011 23:08 Riches#3
Hey,
ich glaube, mein Text ist doch zu ungenau :)

Ich habe selbst noch kein Trainer/Hack etc. erstellen können, da die dazu nötigen Adressen des Programmcodes des Spiels, das ich hacken möchte, sich bei jedem Start verändert.
05/23/2011 10:27 5769854332#4
Jaa, sehr ungenau.
1. Schau mal in der Memory Map (in Ollydbg "Alt + M"), in welchem Modul sich die Addresse befindet (main.exe, .dlls, stack usw.).

2. Und/oder poste die "Linker Info", aus PEiD ([Only registered and activated users can see links. Click Here To Register...]).
05/23/2011 15:06 Riches#5
Ich versuchs jetzt nochmal genauer zu erläutern :)
(Entschuldigt die Wasserzeichen bei den Screenshots :()

Hier habe ich links das Flashgame Multitask 2 im Firefox 4 Browser gestartet.
Rechts habe ich mit Hilfe von Cheat Engine den Prozess "Plugin-container" geöffnet, in dem das Spiel bei Firefox "ausgelagert" wird.
Wie man unten in der Liste von CE sehen kann, habe ich bereits die Zeit als Doublevariable gefunden und gefrezzt.
[Only registered and activated users can see links. Click Here To Register...]


Da mir das jedoch nicht ausreicht, setze ich nun einen Breakpoint auf diese Variable und finde folgende Codestelle(orange gekennzeichnet):
[Only registered and activated users can see links. Click Here To Register...]

Mein Problem ist jetzt, dass diese Codestelle beim erneuten Starten des Spiels eine andere Adresse hat, d.h. nicht statisch ist. So muss ich jedes mal diese Stelle erneut aufsuchen und kann gar keinen Trainer schreiben, der einfach diese Stelle beispielsweise ausnoppt, da die Adresse jedesmal wechselt.

[Only registered and activated users can see links. Click Here To Register...] Leider weiß ich nichts damit anzufangen.

Eine kurze Frage am Ende noch:
Die Adressen, die bei CE oder Ollydbg angezeigt werden (also z.B. die Adresse der Codestelle oben), geben diese die absoulte Position im Arbeitsspeicher an oder sind das Virtual Adresses (d.h. 00 00 00 00 ist hier Anfang des Programms)?

Danke :handsdown:
05/23/2011 19:14 5769854332#6
Natürlich sind das Virtuelle Addressen (Windows unterstützt "Paging").

Sieht so aus, als ob die plugin-container.exe das Flashgame jedesmal an eine andere Addresse lädt.
05/23/2011 20:34 Riches#7
Quote:
Originally Posted by Kiakar View Post
Sieht so aus, als ob die plugin-container.exe das Flashgame jedesmal an eine andere Addresse lädt.
Daraus entnehme ich jetzt, dass es nicht möglich ist, einen Trainer einfach mit festen Adressen zu füttern und diese Codestellen verändern zu lassen :/

Was hälst du denn von der Idee, die Suche der Codestelle zu automatisieren? Das wäre jetzt meine Idee das Problem zu umgehen.
05/23/2011 21:07 InvaderZim#8
Hey, ich hab noch nie einen flash-trainer geschrieben daher kp wie man das elegant löst.
Der Code liegt immer an anderer Stelle, also vermutet dass das Game im Heap liegt wo gerade genug Platz war. Olly -> Memory Map -> Sektion gesucht in der der Code liegt -> fail.
Der Code liegt immer in zwischen nem Bereich markiert als "stack of thread xy". Dann versucht rauszufinden welche DLL den Code im Stack gecallt hat; also ab Stelle mit Zugriff auf die Zähler-Adresse: Olly->Debug->SetCondition-> "command is one of:" RET, dann solange "Trace Over" bis caller gefunden: 01468383 call edx in npswf32.dll
Wenn "call edx" zum gewünschten Codepath mit Zugriff auf Zähler führt endet EDX bei mir immer auf 7A6 (z.B. 02F9B7A6). Unter der Adresse liegt dann immer der Einstieg in den Code:
02F9B7A6 55 PUSH EBP
02F9B7A7 8BEC MOV EBP,ESP
02F9B7A9 83EC 08 SUB ESP,8
02F9B7AC 895D FC MOV DWORD PTR SS:[EBP-4],EBX
02F9B7AF 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8]
02F9B7B2 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+C]
02F9B7B5 8B55 10 MOV EDX,DWORD PTR SS:[EBP+10]
02F9B7B8 85DB TEST EBX,EBX
02F9B7BA 75 1E JNZ SHORT 02F9B7DA
02F9B7BC 8BC1 MOV EAX,ECX
02F9B7BE 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
02F9B7C1 8B1A MOV EBX,DWORD PTR DS:[EDX]
02F9B7C3 83E3 F8 AND EBX,FFFFFFF8
02F9B7C6 891A MOV DWORD PTR DS:[EDX],EBX
02F9B7C8 8B5D FC MOV EBX,DWORD PTR SS:[EBP-4]
02F9B7CB 52 PUSH EDX
02F9B7CC 51 PUSH ECX
02F9B7CD 50 PUSH EAX
02F9B7CE E8 DD0378FF CALL 0271BBB0
02F9B7D3 83C4 0C ADD ESP,0C
02F9B7D6 8BE5 MOV ESP,EBP
02F9B7D8 5D POP EBP
02F9B7D9 C3 RETN

Paar mal die Adresse angeguckt von der Stelle wo auf den Zähler zugegriffen wird ob der Abstand gleichbleibt zum Stack-Anfang, oder Programmeinstieg -> fail.
ABER: Der Abstand zwischen der Adresse in CALL 0271BBB0 und dem Zähler Zugriff ist immer derselbe! Einfach 0x6F abziehen = immer die letzten beiden Bytes auf 41 setzen und man landet an der gesuchten stelle (hier 0271BB41).

Jetzt musst du nur noch prüfen ob bei dir auch EDX immer mit 0x7A6 endet wenn an den Code gesprungen wird, dann Wert aus dem Call ... lesen, letzten 2 Byte auf 41 ändern -> Stelle gefunden.

Scheint mir von Hinten durchs Knie in den Kopf, aber funktioniert.. wenn jemand ne elegante Lösung kennt wär ich auch dankbar ^^ (btw. Zeitaufwand 2h~).

Zim
05/23/2011 22:51 Riches#9
Quote:
Originally Posted by InvaderZim View Post
Der Code liegt immer an anderer Stelle, also vermutet dass das Game im Heap liegt wo gerade genug Platz war. Olly -> Memory Map -> Sektion gesucht in der der Code liegt -> fail.

Zim
Ich hab zwar nicht so viel Ahnung, aber ich hab rausgefunden, dass der Code, der die Zeit hochzählt, erst im Speicher ist, sobald man im Menu das Spiel einmal richtig gestartet hat. Damit meine ich, dass solange man sich im Menu befindet, ohne ein Spiel gespielt zu haben, sind die Funktionen auch unauffindbar. Das würde doch die Vermutung mit dem Heap stützen.
05/23/2011 22:52 5769854332#10
Um Bytecodes in der Memory zu finden, kannst du z.B. [Only registered and activated users can see links. Click Here To Register...] benutzen. C++ Beispiele kann man googeln, das hier ist in asm.
05/24/2011 00:31 Akorn#11
Quote:
Originally Posted by Kiakar View Post
Um Bytecodes in der Memory zu finden, kannst du z.B. [Only registered and activated users can see links. Click Here To Register...] benutzen. C++ Beispiele kann man googeln, das hier ist in asm.
Wie kann jemmand der in Assembler Programmieren will nur so einen schlechten programmierstil haben.
05/24/2011 12:40 Riches#12
Weiß denn jemand, wodurch der Code immer an einer anderen Stelle zu finden ist?
Kann man das als Codeshifting oder so bezeichnen? :/
05/24/2011 15:33 besimbicer#13
:) i dont know convert english
05/25/2011 12:57 Riches#14
Quote:
Originally Posted by besimbicer View Post
:) i dont know convert english
So i have a problem with the flash game multitask 2. Its gamecode is always shifiting and i can't really calculate the position of certain codelines after restarting the game :(