WriteProcessMemory()
-
Moin, Moin...
Ich möchte in den Speicherbereich eines Prozesses hineinschreiben bzw. auslesen. Nun benötigt die Funktion WriteProcessMemory() die Base Address des Prozesses. Woher bekomme ich diese Basisadresse?
Danke im voraus...
-
Das mußt du doch wissen. Wenn du die Adresse garnicht weißt, dann brauchst du die Funktion auch nicht.
-
@MyTurn:
Wenn ich mit einem Programm den Speicherbereich eines ANDEREN Prozesses bearbeiten möchte(so ähnliche wie Spieletrainer), kenne ich die Adresse nicht automatisch sondern muss sie erst ermitteln, oder etwa nicht?
-
Versuch mal www.codecreator.net, da steht in kleines Tutorial zu dem Thema
-
Danke für den Link. Das dortige Beispiel arbeitet aber mit einer Adresse, die vom Benutzer eingegeben werden muss.
Ich möchte jedoch die Basisadresse des Programms automatisch ermitteln lassen. Es muss doch eine API-Funktion geben, die mir die Basisadresse eines laufenden Prozesses(auch eines fremden) ermittelt.
Ciao...
-
Wenn du die Prozess-ID kennst, kannst du mit CreateToolhelp32Snapshot einiges herausfinden.
-
Hm ok, hier ist eines meiner noch unveröffnetlichen Tutorials:
Speichertutorial Teil 2 by Thomas Nitschke
www.codecreator.net
master@codecreator.net
Copyright Thomas NitschkeDies ist eine Fortsetzung des ersten "Wie lese ich
Speicher von fremden Programmen"-Tutorial.
Viele Leute haben mich gefragt wie man denn den
Speicherbereich eines Programmes heraus finden
oder zumindest eingrenzen kann.
Ich werde hier eine (und mir einzig bekannte)
Methode vorstellen.
Als Basis dient dieser etwas abgeänderte
Code aus dem letzten Tutorial:#include <windows.h> #include <iostream.h> typedef unsigned int uint; HANDLE hproc; DWORD procid; int main(void) { HWND hWnd; hWnd = FindWindow(0,"Opfer"); if(!hWnd) return 0; GetWindowThreadProcessId(hWnd, &procid); hproc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procid); CloseHandle(hproc);//<-- Wichtig! return 0; }
Außerdem benötigen wir wieder unser Opfer-Prog.
Da ich das Ermitteln des Speicherbereiches nicht auch
noch in die main() reinquetschen will, schreiben wir
die Funktion GetMemMinMax():#include <windows.h> #include <iostream.h> typedef unsigned int uint; HANDLE hproc; DWORD procid; void GetMemMinMax(void); int main(void) { HWND hWnd; hWnd = FindWindow(0,"Opfer"); if(!hWnd) return 0; GetWindowThreadProcessId(hWnd, &procid); hproc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procid); GetMemMinMax(); CloseHandle(hproc);//<-- Wichtig! return 0; } void GetMemMinMax(void) { //hier speicherbereich bestimmen }
Infos über den Speicherbereich erhalten wir mit der
Funktion VirtualQueryEx(). Sie braucht als Parameter
das Processhandle, die Adresse,
einen Pointer auf die MEMORY_BASIC_INFORMATION-Struktur,
und die Größe dieser Struktur.
Die MEMORY_BASIC_INFORMATION-Struktur sieht so aus:struct _MEMORY_BASIC_INFORMATION { PVOID BaseAddress; PVOID AllocationBase; DWORD AllocationProtect; DWORD RegionSize; DWORD State; DWORD Protect; DWORD Type; } MEMORY_BASIC_INFORMATION;
BaseAdress speichert die Anfangsadresse der
Speicherregion während RegionSize die Größe dieser
Speicherregion speichert. Der Bereich geht also
von BaseAdress bis BaseAdress+RegionSize.
Alles was wir jetzt machen ist in einer
Schleife immer mit VirtualQueryEx() uns
a) die Größe des Speicherbereichs zuholen
b) Prüfen ob er zu dem Programm gehört
c) Beim nächtsten Bereich weitermachen
Als Code sähe das ungefährt so aus:MEMORY_BASIC_INFORMATION mbi; unsigned int adress = 0x400000; do { VirtualQueryEx(hproc,(void*)adress, &mbi,sizeof(MEMORY_BASIC_INFORMATION)); adress += mbi.RegionSize; } while(adress < 0x80000000);
Jetzt müssen wir nur noch überprüfen ob der
Speicherbereich zu unserem Programm gehört und ob er
mit Dingen "gefüllt" ist die wir brauchen.
Es kann nämlich auch sein, das wir auf den
Speicher stoßen in dem der Programmcode unseres
Zielprogs liegt! Für Virencoder sicherlich
interessant, aber wir begnügen uns jetzt mal
mit dem Verändern der Werte.
Um zu überprüfen ob das "unser" Speicher ist,
müssen wir uns die State-Variable der
MEMORY_BASIC_INFORMATION-Struktur anschauen.
Ist sie == MEM_COMMIT, gehört der Speicher uns.
Danach müssen wir noch darauf achten das
wir nicht Programmcode oder andere Sachen
gefunden haben. Das kann man mit der
Protect-Variable überprüfen. Normale Variablen
kann man ja sowohl auslesen als auch schreiben,
also ist der gesuchte Wert: PAGE_READWRITE
Als zusätzliche Sicherheit überprüfe ich
noch die Type-Variable, die sollte immer == MEM_PRIVATE
sein. Hier ist der erweiterte Code:void GetMemMinMax(void) { MEMORY_BASIC_INFORMATION mbi; unsigned int adress = 0x400000; do { VirtualQueryEx(hproc,(void*)adress, &mbi,sizeof(MEMORY_BASIC_INFORMATION)); if((mbi.State == MEM_COMMIT)&& (mbi.Protect == PAGE_READWRITE)&& (mbi.Type == MEM_PRIVATE)) { uint start = (uint)mbi.BaseAddress; uint end = (uint)mbi.BaseAddress+mbi.RegionSize; cout << "Bereich: " << hex << start << " - " << hex << end; } adress += mbi.RegionSize; } while(adress < 0x80000000); }
In der start und end Variable wird jeweils die
Anfangs und Endadresse des Bereich gespeichert.
So, jetzt können wir also nach unseren
Speicherbereichen suchen! Ob der gesuchte Wert
darin enthalten ist, müssen wir noch prüfen.
Dazu schreibe ich wieder eine neue Funktion mit
Namen ScanMem():void ScanMem(DWORD start, DWORD end) { cout << "Bereich wird gescannt...\n"; DWORD read = 0; uint buffer = 0; for(start;start<end;start++) { ReadProcessMemory(hproc,(void*)start,&buffer, sizeof(uint),&read); if(buffer == 15) { cout << "Wert an " << hex << start << " gefunden!"; char choice; cout << "Abbrechen? [j,n]"; cin >> choice; if(choice == 'j') return; } } return;//nichts gefunden }
Wenn das Programm den Wert gefunden hat,
wird der User gefragt ob weiter gesucht werden
soll. Man kann nämlich immernoch nicht sicher
sein ob dieser Wert DIE gesuchte Variable ist.
Hier ist ScanMem() bereits in die Schleife eingebaut:do { VirtualQueryEx(hproc,(void*)adress, &mbi,sizeof(MEMORY_BASIC_INFORMATION)); if((mbi.State == MEM_COMMIT)&& (mbi.Protect == PAGE_READWRITE)&& (mbi.Type == MEM_PRIVATE)) { uint start = (uint)mbi.BaseAddress; uint end = (uint)mbi.BaseAddress+mbi.RegionSize; cout << "Bereich: " << hex << start << " - " << hex << end; ScanMem(start,end); } adress += mbi.RegionSize; } while(adress < 0x80000000);
Hier vollständigkeitshalber
nochmal der gesamte Programmcode:#include <windows.h> #include <iostream.h> typedef unsigned int uint; void GetMemMinMax(void); void ScanMem(DWORD start, DWORD end); HANDLE hproc; DWORD procid; int main(void) { HWND hWnd; hWnd = FindWindow(0,"Opfer"); if(!hWnd) return 0; GetWindowThreadProcessId(hWnd, &procid); hproc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procid); GetMemMinMax(); CloseHandle(hproc);//<-- Wichtig! return 0; } void GetMemMinMax(void) { MEMORY_BASIC_INFORMATION mbi; unsigned int adress = 0x400000; do { VirtualQueryEx(hproc,(void*)adress, &mbi,sizeof(MEMORY_BASIC_INFORMATION)); if((mbi.State == MEM_COMMIT)&& (mbi.Protect == PAGE_READWRITE)&& (mbi.Type == MEM_PRIVATE)) { uint start = (uint)mbi.BaseAddress; uint end = (uint)mbi.BaseAddress+mbi.RegionSize; cout << "Bereich: " << hex << start << " - " << hex << end; ScanMem(start,end); } adress += mbi.RegionSize; } while(adress < 0x80000000); } void ScanMem(DWORD start, DWORD end) { cout << " Bereich wird gescannt...\n"; DWORD read = 0; int buffer = 0; for(start;start<end;start++) { ReadProcessMemory(hproc,(void*)start,&buffer, sizeof(int),&read); if(buffer == 15) { cout << "Wert an " << hex << start << " gefunden!"; char choice; cout << "Abbrechen? [j,n]"; cin >> choice; if(choice == 'j') return; } } return;//nichts gefunden }
Machen wir einen Testlauf! Wenn alles klappt, steht in
der Konsole:
Bereich: 408000 - 40d000 Bereich wird gescannt...
Wert an 409040 gefunden! Abbrechen? [j,n]Und *täterätä* die Adresse stimmt!!!
Ich hoffe, das damit die meisten Fragen was
Speicherbereiche angeht beantwortet sind.
Falls ihr Kritik, Anregungen oder Fragen habt,
schickt eine Mail an master@codecreator.net!
Viel Spaß!Es ist deshalb noch nicht online weil ich
a) zu faul bin die Site zu aktualisieren und
b) weil ich es noch nicht auf Korrektheit hin überprüft habeIst also mit Vorsicht zu genießen
[ Dieser Beitrag wurde am 04.01.2003 um 11:14 Uhr von cd9000 editiert. ]
-
-
Argh.. ich hab' die Codetags vergessen
Naja, ich hoffe man kann es trotzdem lesen.
-
Da du registriert bist, kannst du deine Beiträgt editieren, um z.B. Codetags hinzuzufügen.
-
Hey cool, thx cd!
Ich denk mal wieder viel zu kompliziert...