[C#] ProcessMemory Pointers [HILFE!]

03/19/2013 21:10 Explo!t#1
Hey Leute,
hoffentlich kann mir hier jemand helfen. Ich versuche die Adresse mit der BaseAddress und dem Offset zu berechnen um auf den Inhalt der neuen Adresse zuzugreifen. Das Problem ist, irgendwie klappt es nicht.

Um euch mal näher zu erläutern was ich da eig. versuche. Ich will für GTA San Andreas GodMode schreiben (Memory Editing lernen). Die Adresse fürs Leben habe ich auch gefunden, diese kann ich dann auch manipulieren und das erfolgreich. Jedoch ist die Adresse nicht statisch also ändert die sich nach jedem neustart des Spieles. Also habe ich mit CheatEngine die Pointer gesucht und nach mehrmaligem wiederholen/neustarten des Spieles konnte ich 9 Pointer rausfiltern die immer auf die Adresse für die Lebensanzeige zeigen. Hier ein Bild:
[Only registered and activated users can see links. Click Here To Register...]

Meine Klasse fürs Memory Editing ist auch fertig. So rufe ich das ganze nun auf ohne Pointer:
Code:
            int byteswritten;
            int memoryaddress = 0x0A05E1D0; // Adresse vom Leben (Nicht statisch!)
            float life = 100f;
            byte[] memoryvalue;
            memoryvalue = BitConverter.GetBytes(wantedValue);
            byteswritten = reader.WriteProcessMemory((IntPtr)memoryaddress, memoryvalue, out byteswritten);
Das funktioniert auch perfekt wenn ich die aktuelle Adresse des Spieles nehme. Kann mir jemand helfen das umzubauen so das ich mit einem der Pointer und des Offset's die neue Adresse berechnen kann ? Entweder ich übersehe etwas oder ich Blick da noch nicht ganz durch. Hab heute erst mit Memory Editing angefangen. Versuche schon die ganze Zeit rumzuprobieren aber ich kriegs nicht hin.
03/20/2013 07:50 dready#2
Ich Empfehle dir ein Tutorial über DMA zu lesen, das vorweg :) Sollte die meisten Fragen die du hier gerade hast beantworten.

Es scheint als würd dir das Verständnis dafür fehlen was den ein Pointer ist. (soll kein Angriff sein, nur eine Feststellung :) )

Ein Pointer(Zeiger) ist nicht weiter als eine Speicherstelle in der eine Andere Speicherstelle steht.

Bsp.

Du hast einen Pointer für deine Playerbase
Du weißt das die Hitpoints ein offset von 0x02 haben
Du weißt ein Pointer hat 4 oder 8 Bytes je nachdem ob der Process als 32 Bit oder 64 Bit Process läuft.

Um zu den Hitpoints zu kommen würdest du nun folgendes Tun:

1. Du ließt 4 oder 8 Byte von der Baseadress aus -> Das ist dein Pointer
2. Du addierst dein Offset zu diesem Wert
3. du ließt/schreibst den Speicher an der Stelle des neu errechneten Wertes
03/20/2013 13:36 Explo!t#3
Ja das stimmt, ich bin ziemlich unerfahren in dem Gebiet. Das DMA Tutorial habe ich mir gestern sogar durchgelesen, werde es heute noch ein paar mal durchgehen um ein besseres Verständnis davon zu erhalten. Könntest du mir Anhand meines Beispieles am oberen Post zeigen wie ich das in C# realisiere ? Das würde mir wirklich helfen das besser zu verstehen.
03/20/2013 14:04 dready#4
Dafür fehlt uns hier deine memory read function :)
03/20/2013 14:06 Explo!t#5
Ich dummkopf :facepalm:
Hier die Methoden aus der Klasse.

Read Memory:
Code:
public byte[] ReadProcessMemory(IntPtr MemoryAddress, uint bytesToRead, out int bytesRead)
        {
            byte[] buffer = new byte[bytesToRead];

            IntPtr ptrBytesRead;
            ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, MemoryAddress, buffer, bytesToRead, out ptrBytesRead);

            bytesRead = ptrBytesRead.ToInt32();

            return buffer;
        }
Write Memory:
Code:
public int WriteProcessMemory(IntPtr MemoryAddress, byte[] bytesToWrite, out int bytesWritten)
        {
            IntPtr ptrBytesWritten;
            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, MemoryAddress, bytesToWrite, (uint)bytesToWrite.Length, out ptrBytesWritten);
            
            return bytesWritten = ptrBytesWritten.ToInt32();
        }
03/20/2013 14:55 dready#6
Code:
int baseadress = 0x000000 // hier die baseadresse des modules setzen, nehm mal an das kannst du schon da du ja den Prozesshandle bereit gesucht hast

int hpoffset = 0x0540;

int firstpointer = baseadress + 0x0076F3B8; // Wir bekommen deinen Ersten pointer indem wir den Start des Codes dieses Modules zu dem Offset rechnen an dem der Erste Pointer war. Das machen wir da Windows das Programm nicht immer zwangsläuf an der selben stelle läd.

int bread; // eine int variable um die Rückgabe der gelesenen Bytes von ReadProcessmemory aufzunehmen 

Int32 pointereins = Bitconvert.toInt32(ReadProcessMemory(IntPtr(firstpointer), 4, out bread),0) // ReadProcessMemory liefert uns hier was 4 Bytes weit an der von uns erechneten Speicherstelle steht, gibt in bread aus wieviele bytes gelesen wurden(etwa für Sanity checks), Bitconvert wandelt uns das Bytearray das wir ausgelesen haben in einen Int32 um, werd dazu am schluss noch was sagen ;)

Int32 Speicherstellediewirsuchten = pointereins + hpoffset; // offset der Hps draufrechnen, ab hier ist es wie in deinem Beispiel oben
Hab hier leider keine Ide und muss ganz ehrlich sagen das ich ewig nichts damit gemacht hab, wenn als Fehler drin sind dürft ihr mich mit Watte bewerfen ^^, sollte dich aber auf jedenfall auf den Richtigen weg bringen.

Wichtig Sachen die noch anzumerken wären, wir benutzen hier Int als wären sie Pointer, das ist simpel und einfach falsch :P sobald man das ganze auf 64 bit porten will wird man ordentlich Fluchen und es ist ganz allgemein verpöhnt ;P das klappt da ein Pointer auf 32bit genauso aussieht wie ein Int. Wollte dich nun nicht direkt damit zuknallen aber solltest dir auf jedenfall mal ansehen wie man den Sachen in Intptr umwandelt.
03/20/2013 15:22 Explo!t#7
was ist hier mit dem "ersten pointer" gemeint ?
Code:
int firstpointer = baseadress + 0x0076F3B8; // Wir bekommen deinen Ersten pointer indem wir den Start des Codes dieses Modules zu dem Offset rechnen an dem der Erste Pointer war. Das machen wir da Windows das Programm nicht immer zwangsläuf an der selben stelle läd.
Ich versteh nicht ganz was du meinst. Aber schonmal vielen vielen dank dafür. Ich werde das ausprobieren und aufjedenfall versuchen zu verstehen. Neuland, aber sehr interessant !
03/20/2013 15:29 dready#8
Die erste Adresse die in inda mit "name.exe"+offset angegeben ist

Ich nehm an da du c# benutzt das du die Process klasse benutzt um dein Handle zu bekommen.

mit z.b. Process tmp = Process.GetProcessbyname("binaryname").First(); holst

Dort könntest dann mit tmp.Mainmodule.baseadress oder etwas in der art die Adresse holen an der der Anfang des Codes deiner Binary im Speicher geladen wurde
03/20/2013 15:42 Explo!t#9
Ich habe die BaseAdresse schon rausgenommen, meinen Pointer oben drauf gerechnet wie in deinem Beispiel und darauf das HPoffset.

Ich habe es gerade eben getestet und DANKE. Es funktioniert ! Und endlich verstehe ich es. Im grunde genommen startet das Spiel ja immer an einer neuen baseadresse. so entstehen dann auch die neuen adressen für die inhalte, aber die Entfernung bleibt immer die selbe solange der Pointer statisch ist, nicht wahr ?
03/20/2013 15:47 dready#10
Das ist der Sinn der Sache also ja :)

Was du dir noch ansehen solltest ist warum es den solche statischen Pointer gibt und warum du oft genug festellen wirst das intressante Werte wie Hitpointsmax und Hitpoints so nah zusammenliegen
Das ganze hat nämlich mit der Art zu tun wie ein Programmierer diese Daten logisch zusammenfast und welche wege er dabei wählt

Was für dich noch intressant ist wäre zu schauen was man unter Patternsearch versteht, so das du deine Pointer nach einem Patch schnell wiederfindest

Ansonsten wünsch ich dir natürlich viel Glück weiterhin mit deinem kleinen Projekt
03/20/2013 15:57 Explo!t#11
Vielen Dank. Fänd es super wenn wir irgendwie in Kontakt bleiben könnten in Skype oder ähnliches. Ich würde mich bei Fragen sehr gerne an dich wenden. Will noch ne Menge lernen was dieses Thema angeht und ich kenne sonst niemanden der Ahnung mit dieser Materie hat. :)