Modifiziere Code mit injected dll

04/19/2013 23:20 Zapeth#1
Hallo, ich versuche momentan mithilfe einer injected dll Codesegmente im Speicher des Programms das die dll lädt zu manipulieren.

Allerdings habe ich gewisse Schierigkeiten dies zu realisieren, speziell das modifizieren an sich.

Die dll habe ich bereits injected, die Basisaddressen der Codesegmente die ich manipulieren will habe ich herausgesucht mithilfe von ollydbg und einem hex editor und ich weiß schon ziemlich genau was ich wie ändern muss.

Nur wie soll ich nun innerhalb der dll auf den Speicherbereich den ich modifizieren will zugreifen? Ich habe bereits versucht nach einer Antwort zu suchen, nur bin ich aus den gefundenen Themen nicht wirklich schlau geworden.


In einigen Antworten wird von der Funktion WriteProcessMemory() geredet und nachdem ich mir die Dokumentation angeschaut habe, scheint das auch die gewünschte Funktion zu sein.

Allerdings habe ich auch gelesen, dass diese Funktion gar nicht notwendig ist wenn man sich bereits im Speicher des Prozesses befindet (also nicht auf einen externen Prozess zugreifen muss).

Das ergibt ja auch Sinn (auch wenn ich immer gedacht habe, dass die Speicherbereiche von dll und exe auch irgendwie voneinander getrennt sind), nur bin ich beim besten Willen nicht in der Lage auf die gewünschte Addresse zuzugreifen.

Angenommen ich will den Speicher bei der Addresse 0x0418FC01 lesen/modifizieren, wie kann ich das mit pointern realisieren?


Außerdem bin ich mir nach wie vor nicht ganz sicher, wie ich mit dem Offset umgehen soll. In all den Tutorials und Threads die ich diesbezüglich gefunden habe war nur die Rede davon, dass man zb mit CheatEngine sich den Offset anzeigen lassen kann und dann damit auf die Addresse im Speicher kommt.
Soweit ich weiß ändert sich der Offset aber von Zeit zu Zeit und bleibt nicht konstant für jeden Prozess oder?

Wenn dem so ist, wie kann ich mir dann innerhalb der dll den Offset holen/berechnen (damit ich nicht jedes Mal mit CheatEngine nachschauen muss oder gar den kompletten Speicher des Prozesses durchsuchen muss).

Ich hoffe ihr könnt mir helfen ;)
04/20/2013 00:05 Dr. Coxxy#2
nehmen wir an, an Offset1 ist code, den du ändern möchtest und an Offset2 ein float, den du lesen und ändern möchtest:
Code:
const DWORD Offset1 = 0x18FC01;
const DWORD Offset2 = 0x12345;
const BYTE CodeArrayToWrite = {0x90, 0x90, 0x90, 0x90, 0x90}; // Array mit 5 nops (NOP == 0x90)

//...

DWORD BaseAdd = GetModuleHandle(NULL); // Wird vermutlich 0x400000 sein
memcpy((void*)(BaseAdd + Offset1), CodeArrayToWrite, 5); // An BaseAdd + Offset1 5 byte code mit nops überschreiben
float* SomeFloat = (float*) (BaseAdd + Offset2); // Einen pointer auf einen float definieren...
printf("Der float ist derzeit: %f\n", *SomeFloat); // Float auslesen und ausgeben
*SomeFloat = 13.37f; // Den float im speicher überschreiben
printf("Der float ist jetzt: %f\n", *SomeFloat); // wird 13.37 ausgeben
grad nur hier im antwortenfeld gemacht, für tippfehler wird nicht gehaftet ;)

lesenswert dazu:
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
04/20/2013 00:30 Zapeth#3
Cool vielen Dank, scheint zu funktionieren :) (werde ich morgen (bzw heute) noch eingehender testen).

Also gibt mir GetModuleHandle() den Base Offset? Wenn ich das nur schon früher gewusst hätte, irgendwie habe ich nirgends was davon finden können :p
(btw man muss den return Wert auf DWORD casten damit dein Code funktioniert)
04/20/2013 02:27 Dr. Coxxy#4
jö, hab ich vergessen, habs wie gesagt direkt ins antwortfeld geschrieben.
GetModuleHandle(NULL) holt baseaddress vom prozess idr., GetModuleHandle("NameMeinerDll"); z.b. von deiner dll.
04/20/2013 11:00 Zapeth#5
Hmm sollte das mit memcpy in den Speicher so funktionieren wie du das geschrieben hast?

Folgender Code funktioniert bei mir nämlich nicht (crash bei memcpy):
Code:
const DWORD Offset1 = 0x18FC01;
const BYTE CodeArrayToWrite[6] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
DWORD BaseAdd = GetModuleHandle(NULL);
memcpy((void*)(BaseAdd + Offset1), (void*)CodeArrayToWrite, 5);
BaseAdd + Offset1 enthält die richtigen Werte, die konnte ich erfolgreich mit memcpy auslesen nur wenns ums schreiben in den Speicher geht gibts Probleme.

Ich habe auch probeweise in einen von mir erstellten Speicherbereich geschrieben und da gab es keine Probleme (mit dem quasi gleichen Code).
Code:
unsigned char* buffer = new unsigned char[10];
const BYTE CodeArrayToWrite[6] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
memcpy(buf, (void*)CodeArrayToWrite, 5);
//buffer enthält nun CodeArrayToWrite
delete[] buffer;
Ich habe auch probeweise eine Testapplication erstellt und versucht irgendwo in den Speicher mit memcpy zu schreiben (wie oben beschrieben), jedoch auch ohne Erfolg.

edit: Ich vermute mal der Crash passiert weil der Speicherbereich den ich modifizieren will, schreibgeschützt ist.
Falls dies der Fall ist, wie kann ich dann den Bereich modifizierbar machen?
Und warum ist der Speicher in manchen Fällen direkt beschreibbar (bzw in den meisten Fällen die ich finden konnte)?
04/20/2013 11:52 snow#6
Das dürfte helfen: [Only registered and activated users can see links. Click Here To Register...]
04/20/2013 12:28 Zapeth#7
Danke, jetzt gehts :)
04/20/2013 12:31 Dr. Coxxy#8
Quote:
Originally Posted by Zapeth View Post
Hmm sollte das mit memcpy in den Speicher so funktionieren wie du das geschrieben hast?

Folgender Code funktioniert bei mir nämlich nicht (crash bei memcpy):
Code:
const DWORD Offset1 = 0x18FC01;
const BYTE CodeArrayToWrite[6] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
DWORD BaseAdd = GetModuleHandle(NULL);
memcpy((void*)(BaseAdd + Offset1), (void*)CodeArrayToWrite, 5);
BaseAdd + Offset1 enthält die richtigen Werte, die konnte ich erfolgreich mit memcpy auslesen nur wenns ums schreiben in den Speicher geht gibts Probleme.

Ich habe auch probeweise in einen von mir erstellten Speicherbereich geschrieben und da gab es keine Probleme (mit dem quasi gleichen Code).
Code:
unsigned char* buffer = new unsigned char[10];
const BYTE CodeArrayToWrite[6] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
memcpy(buf, (void*)CodeArrayToWrite, 5);
//buffer enthält nun CodeArrayToWrite
delete[] buffer;
Ich habe auch probeweise eine Testapplication erstellt und versucht irgendwo in den Speicher mit memcpy zu schreiben (wie oben beschrieben), jedoch auch ohne Erfolg.

edit: Ich vermute mal der Crash passiert weil der Speicherbereich den ich modifizieren will, schreibgeschützt ist.
Falls dies der Fall ist, wie kann ich dann den Bereich modifizierbar machen?
Und warum ist in manchen/den meisten Fällen nicht der Fall (also warum kann man manchmal direkt darauf zugreifen)?
das was snow911 gesagt hat, hab ich vergessen, weil ich für sowas ne eigene funktion habe...
musst auf EXECUTE_READWRITE rechte den speicherbereich setzen (den zurückgegebenen vorherigen wert speichern), dann mit memcpy drüberschreiben und dann wieder den vorherigen wert wiederherstellen.
am besten du packst dir das ganze in eine funktion MemCpySecure(void* Dst, void* Src, size_t Len);

EDIT:
und da war te schneller :P

na, immerhin darf ich noch schreiben, welche speicherbereiche schreibgeschützt sind.
ein programm ist in mehrere segmente unterteilt, der .text (da ist der programmcode normalerweise drin) und .rdata (konstante daten, wie z.b. const int Blubb = 100; und strings) sind per default schreibgeschützt.
04/20/2013 12:38 Nightblizard#9
Quote:
Originally Posted by Zapeth View Post
Hmm sollte das mit memcpy in den Speicher so funktionieren wie du das geschrieben hast?

Folgender Code funktioniert bei mir nämlich nicht (crash bei memcpy):
Code:
const DWORD Offset1 = 0x18FC01;
const BYTE CodeArrayToWrite[6] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
DWORD BaseAdd = GetModuleHandle(NULL);
memcpy((void*)(BaseAdd + Offset1), (void*)CodeArrayToWrite, 5);
BaseAdd + Offset1 enthält die richtigen Werte, die konnte ich erfolgreich mit memcpy auslesen nur wenns ums schreiben in den Speicher geht gibts Probleme.

Ich habe auch probeweise in einen von mir erstellten Speicherbereich geschrieben und da gab es keine Probleme (mit dem quasi gleichen Code).
Code:
unsigned char* buffer = new unsigned char[10];
const BYTE CodeArrayToWrite[6] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
memcpy(buf, (void*)CodeArrayToWrite, 5);
//buffer enthält nun CodeArrayToWrite
delete[] buffer;
Ich habe auch probeweise eine Testapplication erstellt und versucht irgendwo in den Speicher mit memcpy zu schreiben (wie oben beschrieben), jedoch auch ohne Erfolg.

edit: Ich vermute mal der Crash passiert weil der Speicherbereich den ich modifizieren will, schreibgeschützt ist.
Falls dies der Fall ist, wie kann ich dann den Bereich modifizierbar machen?
Und warum ist in manchen/den meisten Fällen nicht der Fall (also warum kann man manchmal direkt darauf zugreifen)?
Die .exe Datei ist in verschiedene Sektionen aufgeteilt. I.d.R. sind das die folgenden:
.text -> Hier steht der Programmcode. Ist mit PAGE_EXECUTE geschützt.
.rdata -> Read Only Daten. Ist mit PAGE_READONLY geschützt.
.data -> Z.B. globale Variablen. Ist mit PAGE_READWRITE geschützt.

Wenn du jetzt Daten in der .data Section änderst, dann geht das in Ordnung, da du dort lesen und schreiben darfst. Wenn du nun aber den Programmcode ändern willst, dann musst du vorher die Zugriffsrechte ändern, da das sonst in der ACCESS_VIOLATION Exception endet.

Ein paar interessante Beiträge zum Aufbau der PE Dateien:
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]