Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

28.01.2013, 23:01

Speicheroffset eines laufenden Prozesses

Hallo alle zusammen,

Ich habe folgendes Problem: Ich habe mich nun etwas intensiver mit der Speicherverwaltung auseinander gesetzt und mir die WinAPI-Funktionen dazugehörend angeeignet und schaffe es nach Hilfe des Tutorials von TcH (HowTo: Erstellen eines Trainers II) Programme zu schreiben die bestimmte Werte auslesen und auch umschreiben kann. Als gutes Beispiel habe ich es versucht ein Programm zu schreiben, dass nacheinander den momentanen Gang bei Live for Speed ausliest und mir die Adresse wiedergibt. (Nach dem Prinzip leg den ersten Gang ein, drück Enter, leg den zweiten Gang ein, drück Enter usw. bis nur noch eine Adresse und ein Wert übrig war.)
Jetzt würde ich gerne den genauen Umkehrschluss ziehen. Ich weiß, dass die Adresse des Wertes sich immer wieder bei Neustart des Programms ändert, das Offset bleibt jedoch gleich. Demnach möchte ich nun das Offset von der Startadresse zur Zieladresse herausfinden. Klingt erst einmal recht trivial und simpel aber leider habe ich das Problem anscheinend etwas unterschätzt. Um nicht schon Fehler in den Basics reinzubauen benutze ich den Code von TcH als Grundlage und habe versucht die Main-Routine umzuschreiben.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int _tmain (int argc, ::TCHAR* argv[]){     FILE *fHandle;  int offset = 0; bool richter = true;        ::DWORD eingegeben = 0x0FE34D79, down =0x0FE34D79;  //Gear
    fHandle = fopen("ergebnisse.txt","w");    ::_tprintf (_T ("MemScan v1.3 by TcH\n\n"));
    ::HWND hwnd = select_window ();
    ::DWORD process_ID;    ::DWORD thread_ID       = ::GetWindowThreadProcessId (hwnd, &process_ID);
    ::HANDLE process        = ::OpenProcess (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF, FALSE, process_ID);    ::MEMORY_BASIC_INFORMATION mbi;
    ::SYSTEM_INFO sys_info;    ::GetSystemInfo (&sys_info);
    std::vector<::DWORD> adresses;    unsigned int value = 0;
    ::_tprintf (_T ("starte Scanvorgang nach %d\n"), value);
    ::DWORD adress = (::DWORD) sys_info.lpMinimumApplicationAddress;    do {
        ::VirtualQueryEx (process,                           reinterpret_cast<void*>(adress),                           &mbi,                           sizeof (::MEMORY_BASIC_INFORMATION));
        ::DWORD start = (::DWORD) mbi.BaseAddress;        ::DWORD end   = (::DWORD) mbi.BaseAddress + mbi.RegionSize;
        adress = start;
        if(richter) {           down -= start;          richter = false;        }
        printf("%x %x %i\nOffset: %i Adress: %x\n\n",start,end,mbi.RegionSize,offset,adress);       fprintf(fHandle,"%x %x %i Offset: %x Adress: %x\n",start,end,mbi.RegionSize,offset,adress);
        if(adress + mbi.RegionSize > eingegeben) {
            offset += down;         adress += down;
        } else {

            offset += mbi.RegionSize;           adress += mbi.RegionSize;           down-= mbi.RegionSize;      }
    } while (adress < (::DWORD) eingegeben);
    printf("%x %x",offset,adress);  getch();
    ::CloseHandle (process);
    ::TCHAR a;    ::_tscanf (_T ("%c"), &a);
    return 0;}


In der Funktion select_window() wird nichts gemacht, als das das Fenster ausgewählt wird. Ansonsten zähle ich einfach immer die Regions mit. Diese starten allerdings immer bei mir bei 10000 was natürlich nicht sein kann. Außerdem sieht die Auflistung wenn ich das Programm ausführ so aus:


10000 20000 65536 Offset: 0 Adress: 10000
20000 21000 4096 Offset: 10000 Adress: 20000
21000 30000 61440 Offset: 11000 Adress: 21000
30000 31000 4096 Offset: 20000 Adress: 30000
31000 40000 61440 Offset: 21000 Adress: 31000
40000 41000 4096 Offset: 30000 Adress: 40000
41000 50000 61440 Offset: 31000 Adress: 41000
50000 88000 229376 Offset: 40000 Adress: 50000
88000 8a000 8192 Offset: 78000 Adress: 88000


Und eigentlich ist es doch so, dass die nächste Region doch nicht sofort an der letzten angrenzt oder? Ich steh einfach auf dem Schlauch und weiß nicht wo ich ansetzen soll.

Danke für die Hilfe.

Grüße
Tim

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

29.01.2013, 06:08

Warum nicht? Die Offsets und Längen passen doch perfekt zueinander. Warum sollten die also nicht linear im Speicher liegen? (liegen sie dank Paging vermutlich dennoch nicht)
Alles andere wäre doch sehr unsinnig.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

29.01.2013, 08:28

Offset falsch

Das Problem dass ich habe ist einfach, dass sich das Offset von einem Wert, den ich nachweislich herausgefunden hab sich immer wieder verändert. Ich habe also öfters mithilfe des Programms aus dem Tutorial von TcH und auch der Cheat Engine z.B. den momentanen Gang des Wagens herausgefunden und die zugehörige Adresse. Wenn ich jetzt mit meinem Programm das Offset berechne bekomme ich erst einmal einen Wert. Wenn ich nun das Spiel schließe und neu öffne, wieder den ganzen Vorgang durchziehe sollte ich doch das gleiche Offset bekommen oder sehe ich das falsch?

Denn genau das passiert nicht. Ich bekomme bei jedem Durchlauf ein anderes Offset raus. Die Idee dahinter ist es die Daten herauszubekommen um sie auf einem LCD gekoppelt an einem µC auszugeben. Ich weiß, dass diverse Spiele auch eine eingebaute Engine haben, die per Sockets immer wieder Pakete schickt, die genau die Daten ausgibt. Allerdings suche ich eher eine allgemeine Lösung weil manche Spiele solch eine Engine wie bei LFS das sogenannte "Outgauge" nicht besitzen.

Danke jetzt schonmal für die Antwort :)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

29.01.2013, 10:38

Wieso sollte die Adresse gleich bleiben? Es handelt sich offenbar um Heap-Variablen und deren Offsets ändern sich eben. Es wird aber einen Pointer geben, der auf einen Pointer zeigt, der auf einen Pointer zeigt, der auf eine Liste von Pointern zeigt.... der auf Deine Variable zeigt.
Zu erwarten, dass einmal gefundene Variablen immer am selben Offset liegen, ist ein Trugschluss. Dazu dann noch ASLR und du darfst danach suchen lassen. Wäre vermutlich einfacher, wenn Du die Inhalte der umgebenden Speicher auf immer gleiche Muster (String-Pointer, Fixwerte, etc) analysierst und basierend darauf den Offset dynamisch ermitteln lässt.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

6

30.01.2013, 23:57

Danke schonmal, ihr habt mir echt schon sehr weiter geholfen. Ich verfolge nun die Idee den statischen Base-Pointer des jeweiligen Wertes zu finden. Mit der Cheat-Engine hat das auch funktioniert. Das Offset kann ich immer wieder verwenden um in der "Pointerkette" zu meinem jeweiligen Wert zu kommen auch nach Neustarten des Programmes.

Nun müsste ich ja einfachdie Pointer-Hierarchie in mein Programm übernehmen. Sprich ich nehme den Base-Pointer , nehme den Level 1 Pointer , Level 2 Pointer.... Bis ich irgendwann an meinem Wert angekommen bin. Allerdings habe ich nun wieder das Problem dass mir in dem Trainerprogramm immer wieder die Adressbereiche von 10k-20k 20k-30k usw angezeigt werden, in der Cheat Engine finde ich aber völlig andere Adressen. Nun meine Frage: Wie kann ich die tatsächlich erste Adresse des Programmes auslesen?

Liebe Grüße

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

31.01.2013, 06:45

sys_info.lpMinimumApplicationAddress ?
Die wird doch oben schon in dem Segment-Code verwendet, hast du den denn nicht gelesen und angepasst?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

8

31.01.2013, 11:55

"LFS.exe"

Also, meine Cheat Engine sagt mir, dass mein Base Pointer an der Adresse "LFS.exe"+588D54 mit dem Offset 2F06 liegt.


"LFS.exe" ist angeblich 905A4D.

"LFS.exe" + 588D54 würde angeblich auf = 0C4CFB90 zeigen.

Sprich wenn ich folgendes mache müsste ich doch eigentlich C4CFB90 ausgegeben bekommen oder nicht?



int main(void) {
HWND hWnd;
int ein;
int komm = NULL;
hWnd = FindWindow(0,"Live For Speed");
if(!hWnd) return 0;
GetWindowThreadProcessId(hWnd, &procid);
hproc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procid);

int adresseneu = 0xE8E7A1; //=0x905A4D + 0x588D54
ReadProcessMemory(hproc,(short**)adresseneu,&komm,sizeof(int),NULL);


//komm += 0x2F06; //Offset draufrechnen

printf("%x",komm);
cin >> ein;

CloseHandle(hproc);//<-- Wichtig!
return 0;
}

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

31.01.2013, 12:07

"LFS.exe" ist angeblich 905A4D.

"LFS.exe" + 588D54 würde angeblich auf = 0C4CFB90 zeigen.

Sprich wenn ich folgendes mache müsste ich doch eigentlich C4CFB90 ausgegeben bekommen oder nicht?

905A4D+588D54 ergibt bei mir E8E7A1, so wie es in Deinem Source steht. Woher Du die 0C4CFB90 nimmst, das ist mir nicht ganz klar.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

10

31.01.2013, 12:13

Vielleicht habe ich mich ein bisschen krumm ausgedrückt :)


Wenn man bei der Cheat Engine manuell eine Adresse eingibt gibt es die Chance die Auswahl "Pointer" zu treffen. Demnach zeigt der Pointer mit der Adresse "LFS.exe"+0x00588D54, also 0xE8E7A1, auf die Adresse 0C4CFB90. Demnach lese ich den Speicher mit der Adresse 0xE8E7A1 aus und sollte doch eigentlich den Wert 0C4CFB90 erhalten oder nicht?


Zugerechnet mit dem Offset von 2F06 bekomme ich die Adresse 0C4D2A96. Und in der steht mein Gang, nachweislich. Allerdings hapert es an dem Schritt aus der Adresse 0xE8E7A1 den Wert 0C4CFB90 auszulesen.

Werbeanzeige