Pointer und Offsets
-
Tippsundso schrieb:
Du würdest doch auch nicht
void* hOwnProcess = GetCurrentProcess();
schreiben, oder?!
Dochdoch, immer. Wenn es native Typen sind...
Aber ich arbeite ja auch nur für mich.:p
-
Tippsundso schrieb:
Du würdest doch auch nicht
void* hOwnProcess = GetCurrentProcess();
schreiben, oder?!
Gut, dieses Beispiel ist schon extremer, aber dennoch darf man niemals nachlässig sein!! Wenn ich WinAPI bezogen programmiere, dann verwende ich auch nur die abstrakten Datentypen, welche dafür vorgesehen sind.
Klar. Wenn bald irgendwann Windows 128Bit rauskommt, kannste einfach den Sourcecode nehmen und auf 128Bit compilieren und fertig ist der Lack. Schon kann das Programm mit mehr als 16Mio Terabyte Ram umgehen. Einfach so.
Also bei der Umstellung von 32 auf 64 war das schon sehr praktisch, daß ich mich vorher schon an die Typen gehalten hatte.Nee, eigentlich ist es für mich nur viel einfacher, mich an die MS-Typen und Konstanten zu halten. Dann muss ich weniger nachdenken, sondern kann einfach machen, was in der Doku steht.
-
Pointer und Offsets mit WinApi?
Bereits Windows 3.1 (16 bit) hatte da eigene Vorgehensweisen mit Handles und WinApi-Funktionen.
Es ist zweckmässig, sich daran zu halten. Offsets waren unter DOS-16 ein Graus zur Überwindung der 64-kB-Grenze, woran man sich nur ungern erinnern möchte!
-
Ähh, was?
Lies den ersten Post des Threads...
-
Vielen vielen Dank
hab aber immer noch eine frage
wie finde ich jetz eig die offsets raus? Und wie die dll adresse?
-
Das weißt du jetzt nach 2 Seiten Erklärung immer noch nicht?
Nenn dich doch trollilolipoplol
-
lolipoplol schrieb:
Vielen vielen Dank
hab aber immer noch eine frage
wie finde ich jetz eig die offsets raus? Und wie die dll adresse?
-.-
DllBaseAddr + Offset = MessageBox addr;
Da ich hab schnell was zusammengeschustert:
(Ja Ja Funktionen nicht auf Rückgabewerte geprüft bla bla bla mir doch Jacke wie Hose, ich hab jetzt Feierabend(1h früher als sonst :D) )
#include <iostream> #include <windows> #include <TlHelp32> using namespace std; unsigned GetDllBaseAddress( unsigned ProcessId, string DllName ) { HANDLE snap; MODULEENTRY32 lppe; ZeroMemory(&lppe,sizeof(MODULEENTRY32)); lppe.dwSize = sizeof(MODULEENTRY32); snap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, ProcessId ); if ( snap == INVALID_HANDLE_VALUE ) { cout<< "CreateToolhelp32Snapshot error: " << GetLastError() << "\n"; return 0; } Module32First( snap, &lppe ); do { if ( !strcmp( lppe.szModule,DllName.c_str()) ) { cout<<lppe.szModule<< " "<<hex<<lppe.hModule<<"\n"; break; } } while ( Module32Next ( snap , &lppe ) == 1 ) ; return unsigned(lppe.hModule); } unsigned GetOffsetAddress ( unsigned FunctionAddr, unsigned DllBaseAddr ) { return FunctionAddr - DllBaseAddr; } int main() { HWND hwnd = FindWindow ( 0,"Rechner"); if ( hwnd == 0 ) { cout<<"Windows Taschenrechenr wurde nicht gestartet.\n"; return 0; } DWORD pid=0; GetWindowThreadProcessId(hwnd, &pid); unsigned DllBaseAddr = GetDllBaseAddress ( pid, "user32.dll" ); cout<< hex << DllBaseAddr << "\n"; HANDLE handle = LoadLibrary ( "user32.dll" ); FARPROC MessageBoxA_Addr = GetProcAddress ( handle, "MessageBoxA" ); cout<<"MessageBoxA addr: " << MessageBoxA_Addr <<endl; unsigned offset = GetOffsetAddress ( reinterpret_cast<unsigned>(MessageBoxA_Addr), DllBaseAddr ); cout<<offset<<"\n"; system("PAUSE"); }
-
Vielen Danke
jetz hab ich auch verstanden
-
Ich weiß der Thread is schon alt
aber ich hab nochmal versucht mich damit zu beschäftigen
hab diesmal versucht ein Programm zu schreiben was in Windows Solitär den spielstand ändert. Hab mit cheat engine schon die Offsets und die (nicht statische ) base adress (Base Adress: solitaire.exe+BAFA8, Offset1: 50, Offset2: 14)
unsigned findbaseadress(DWORD ProcessId, string name ) { HANDLE snap; MODULEENTRY32 modul; ZeroMemory(&modul,sizeof(MODULEENTRY32)); modul.dwSize = sizeof(MODULEENTRY32); snap = CreateToolhelp32Snapshot(TH32CS_INHERIT, ProcessId ); /* musste TH32CS_SNAPMODULE zu TH32CS_INHERIT ändern weil sonst immer ein fehler kam (299)*/ if ( snap == INVALID_HANDLE_VALUE ) { cout<< "CreateToolhelp32Snapshot error: " << GetLastError() << "\n"; return 0; } Module32First( snap, &modul ); do { if ( !strcmp( modul.szModule,name.c_str()) ) { cout<<modul.szModule << hex<<modul.hModule<<"\n"; break; } } while ( Module32Next ( snap , &modul ) == TRUE) ; return unsigned(modul.hModule); }
Aber die Funktion funktioniert nicht. Ich habe mir danach zum testen den Rückgabewert der Funktion ausgeben lassen, aber der ist immer 0...
Kann mir vielleicht jemand helfen?
-
Da ist der Fehler:
snap = CreateToolhelp32Snapshot(TH32CS_INHERIT, ProcessId );
Kopier einfach von mir die Funktion die funktioniert.
Oder ändere es so um:
snap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, ProcessId );
-
Bassmaster schrieb:
Kopier einfach von mir die Funktion die funktioniert
-
berniebutt schrieb:
Pointer und Offsets mit WinApi?
Bereits Windows 3.1 (16 bit) hatte da eigene Vorgehensweisen mit Handles und WinApi-Funktionen.
Es ist zweckmässig, sich daran zu halten. Offsets waren unter DOS-16 ein Graus zur Überwindung der 64-kB-Grenze, woran man sich nur ungern erinnern möchte!Hi. Was auch mal gesagt werde muss... Deine Seite ist zum heulen. Und deine unnötigen halb wissenden Antworten gehen mir auf den Sack. Also bitte such dir ein anderes Hobby, den du hast gar nichts verstanden...
-
Ich frage mich schon ewig woran genau es liegt dass sich bei CheatEngine z.B die Adresse der Munition in einem Spiel immer wieder ändert.
Liegt das an ASLR ?
-
Das ist doch einleuchtend.
unsigned int* muni = new unsigned int;
Jetzt kann muni bei jedem Programmstart ne andere Adresse haben (heap alloc. halt).
-
man muss ja bei cheatengine solche pointer finden, die dann auf den wert zeigen, dessen adresse sich immer verändert. was wären solche pointer im code?
-
Generell hat man es leichter, wenn es globale (also quasi statische) Variablen sind.
Es kann sich aber auch um komplett dynamische Werte handeln. Dann kann man zB einen statischen Zeiger darauf suchen (einfach nach der Adresse des gewü. Wertes als Wert suchen).
Bei komplexeren Strukturen muss man halt versuchen, sich ein Bild darüber zu machen.
Oder man manipuliert die code section, zB macht man ein JMP in eine __declspec(naked) Funktion, holt sich dort ne Adresse oder macht was auch immer und JMP'd wieder zurück. So kann man natürlich sämtliches Verhalten ändern.
-
unsigned int* muni = new unsigned int;
Jetzt kann muni bei jedem Programmstart ne andere Adresse haben (heap alloc. halt).
Das liegt also daran, dass der Heap wegen ASLR eine neue Adresse bekommt?
Aber wenn ein Spiel kein ASLR hat dann müssten die Adressen eigentlich statisch sein und man braucht keine Pointer.
-
Vergiss ASLR, das ist irrelevant, da es nur die Basisadresse des Prozesses und der Module ändert. Die offsets bleiben gleich.
Trotzdem kann das Betriebssystem bei jedem new/malloc Speicher an einer beliebigen Adresse reservieren, das ist absolut nicht festgelegt, also muss man davon ausgehen, dass es immer unterschiedlich ist.
-
Wenn das Spiel keine feste Base-Adresse hat, musst du dir mit z.B. 'GetModuleHandlle' die Base Adresse von deinen Module wo deine Adresse ist benutzen. Es kann auch sein, das es sich bei deiner Adresse um eine Adresse handelt, die ein Pointer auf eine Klasse ist und somit bei z.B. jeden Neustart ändert. Dann musst du den Pointer + Offset suchen & wenn dann der Pointer nicht in einer festen Base Adresse ist, musst du auch noch die Base Adresse dazu rechnen.
Beispiel:
DWORD CALLBACK HackThread( LPVOID lpReserved ) { DWORD dwGame = ( 0 ); do { dwGame = (DWORD)GetModuleHandle( "Game.exe" ); } while ( dwGame == 0 ); while ( TRUE ) { DWORD dwScorePointer = *(DWORD*)( dwGame + 0x1F50C ); if ( dwScorePointer ) { *(INT*)( dwScorePointer + 0x84 ) = ( 99999999 ); } Sleep( 100 ); } return ( 0 ); }
-
Witzig sollte es werden wenn ...
- Der Main-Loop des Games nicht im "Main"-Thread (=ersten Thread des Prozesses) läuft
- Der Main-Loop-Thread erst erzeugt wird nachdem das Programm schon viele lustige andere Dinge gemacht hat (Libraries initialisieren etc.)
und - Das Hauptobjekt des Spiels (bzw. der primäre Zeiger darauf) nur lokal im Stack des Main-Loop-Thread lebt, und von dort aus immer nur als Parameter an andere Funktionen übergeben wird.
Dann dürfte es *ziemlich schwierig* werden den Zeiger zu finden.
Wäre vielleicht eine ganz gute zusätzliche Cheat-Hürde für Spiele.
Natürlich könnte man dann immer noch alle Threads des Prozesses durchgehen, den Main-Loop-Threads suchen indem man im Stack nach der "main" Rücksprungadresse sucht, und dann im Stack des Main-Loop-Threads nach einem bekannten Muster suchen um das Stack-Frame zu finden welches das Game-Objekt enthält. Oder, vermutlich einfacher, gleich den ganzen Speicher nach einem bestimmten Muster durchsuchen mit dem man das Game-Objekt "zuverlässg" finden kann.
Mit "normalen" Cheat-Engines geht das aber zumindest nicht mehr