Dies ist eine etwas knifflige und sogar komplexe Frage, in dem Sinne, dass Sie damit ziemlich tief gehen können. Aber um die Dinge ein bisschen zu vereinfachen:
Betrachten Sie Ihr Beispiel für " Lesen des Timers in einem Minenspiel ":
Der erste Schritt besteht darin , die Speicheradresse zu finden . Dies erfolgt normalerweise mit einem Tool namens Speichereditor (in einigen Fällen auch mit einem Debugger), das mithilfe verschiedener Methoden den Speicherort einer Variablen im Prozessspeicher ermitteln kann . Es ist üblich, im Speicher des Zielprozesses nach einem bestimmten Wert (z. B. dem Wert des Timers) zu suchen, dann den Zielwert zu ändern (z. B. den Timer vorzuschieben) und erneut nach Übereinstimmungen zu suchen. Dieser Prozess fixiert die Kandidaten bei jeder Iteration, bis nur noch die genaue Variable übrig ist. Das Abrufen der Adresse dieser Variablen im Speicher des Prozesses ist nur ein Mausklick mit einem Speichereditor.
Der zweite Schritt besteht darin, die Daten in dieser bestimmten Adresse zu ändern . Wie dies geschieht, hängt vom Betriebssystem ab. Unter Windows gibt es einen WinAPI-Aufruf mit dem Namen, mit WriteProcessMemory
dem vordefinierte Daten an eine bestimmte Adresse im Speicher des Zielprozesses geschrieben werden können. In unserem Beispiel würden Sie diese Funktion verwenden, um die Timer-Variable im Zielprozess mit Ihrem eigenen gewünschten Wert zu überschreiben und den Timer im Spiel effektiv zu ändern.
In der Praxis müssten Sie die Prozess- ID des Zielprozesses ermitteln und dann Ihren Rogue-Prozess an den Zielprozess anhängen , um dessen Speicherplatz ändern zu können. Dies ist eine ziemlich triviale Aufgabe, trägt aber nicht zur Beantwortung der Frage bei, so dass ich sie dem Leser als Übung ausgelassen habe. ;)
Es ist völlig anders von OS. Einige erlauben es Ihnen überhaupt nicht, und Sie müssen wissen, wo sich die gewünschten Daten im Speicher des Ziels befinden.
So geht's unter Linux: /unix/6301/how-do-i-read-from-proc-pid-mem-under-linux
quelle
Eine Anwendung erhält vom Betriebssystem einen Speicherbereich. Im Allgemeinen muss die Anwendung den Speicher anfordern, aber diese Funktionalität kann für den Programmierer aufgrund der Sprache verdeckt sein.
Sprachen wie C ermöglichen Blockanforderungen für bestimmte Größen, während andere Sprachen wie C ++, C # und Java Anforderungen mithilfe von Schlüsselwörtern wie ermöglichen
new
. Jede Sprache verfügt über verschiedene Möglichkeiten, Speicher zuzuweisen. Dies ist also nur eine kurze Übersicht. Die Freigabe des Speichers an das Betriebssystem kann entweder explizit oder über einen Garbage Collector erfolgen.Der Zugriff auf den Speicher in der Anwendung hängt davon ab, wie er zugewiesen wurde. C und C ++ sind am bekanntesten für die Verwendung des Konzepts von Zeigern, um anzuzeigen / zu verfolgen, wo sich der Speicher befindet. Andernfalls wird der Speicherzugriff über die erstellte Klasse oder Variable abgewickelt.
Meistens müssen Sie sich nicht um einen bestimmten Speicherzugriff in Ihrem Programm kümmern. Die Sprachkonstrukte und das Betriebssystem verschleiern diese Bedenken für Sie effektiv.
Ihr Beispiel für einen Timer in einem Spiel ist ein großartiges Beispiel dafür, wo Sie sich keine Gedanken über die zugrunde liegende Speicherzuordnung machen müssen. Sie haben eine Variable, die den Timer darstellt, und Sie lesen nur aus der Variablen.
Meine Antwort ist relevant für das Schreiben der Anwendung, während die Antwort von zxcdw für den Zugriff auf Speicher relevant ist, der zu einer anderen Anwendung gehört. Ihre LMGTFY-Begriffe wären "Debugging" und "Reverse Engineering", um sich weiter mit diesem Thema zu befassen.
Einige zusätzliche Lektüre:
quelle