Suche Hilfe bei Trainer programierung!!!!!!!!!!!!



  • Hallo!

    Wie schon der Tietel sagt brauche ich Hilfe bei der programierung eines Trainers. Ich habe bis jetzt noch keine Erfarungen mit derartieger programierung, aber ich möchte dass lehrnen.

    Also ich suche jehmanden, der damit Erfahrung hat und mir das Ganze etwas erkleren kann.

    Ich hofe es meldet sich jehmand, der mir helfen kann.

    Ihr könnt mir auch eine E-mail schreiben an die Andresse: be_on_edge@email.si



  • Das ist bei den meisten Spielen garnicht schwer, wenn Du nur den Speicherstand cheaten möchtest. Dazu musst Du aber herausfinden wo was gespeichert wird und dann einen Trainer schreiben der den Inhalt an diesen Positionen verändert.

    Um z.B. herauszufinden wo die Lebenspunkte gespeichert werden, musst du zunächst während eines Angriffs das Spiel speichern und die Lebenspunkte merken. Als nächstes spielst Du weiter bis dir wieder ein paar Punkte abgezogen wurden, speicherst es wieder, aber unter einem anderen Namen. Dann gehst Du aus dem Spiel raus. Öffnest die Speicherstände z.B. mit einem Hex-Editor und suchst einfach die Stellen wo die Zahlen vorkommen, dann vergleichst Du die Stellen. Wenn beide gleich sind, dann werden hier eventuell die Punkte gespeichert. Falls es mehrere Stellen gibt, die in Frage kommen können. Dann wiederhollst einfach alles wieder, bis es eine eindeutige Stelle gibt.

    Falls Du aber die Exe des Spiels cheaten willst dann musst Du Assembler lernen, oder zumindest wie eine Exe aufgebaut ist.



  • Also unter einem Trainer versteh ich keinen Save cheater.
    Da wird dir wirklich nichts anderes übrig bleiben als ASM zu lernen, und mit sowas wie Softice rumzuwursteln, und zu checken, ob sich etwas im RAM getan hat. Die Exe müßtest du normal eigentlich nicht anfassen. Ein kleines Tool, daß im Hintergrund checked, was passiert reicht 😃 ( leicht gesagt *g )

    P.s. Sowas macht mit den riesen Teilen aber auch nicht mehr wirklich Spaß. Am C64er, Amiga oder 368er war das noch lustig.



  • Erstmals Danke für die Antwrt, Es ist für mich kein Problem die Adresse zu finden, die den Vert enthält, aber da sich aber die Adresse verendert, wenn man das Spiel verläst und es wieder startet, muss man nach meiner Meinung ein offset von der Basisadresse der Anwendung Verendern, die Frage ist jetzt

    Wie mache ich dass? (wie finde ich dass)

    Ich habe auch schon einige sachen mit dem W32dasm gemacht, aber noch keine Trainer



  • Nimm ReadProcessMemory und WriteProcessMemory falls du mit Win arbeitest, ASM ist da komplett unnötig. Benutzung siehe MSDN.



  • Morgen,

    http://www.codecreator.net/
    unter WinAPI Tutorial -> Speicherzugriff

    ist genau das was du brauchst 😃



  • Und hier der 2. nie veröffnetlichte Teil:

    Speichertutorial Teil 2 by Thomas Nitschke
    www.codecreator.net
    master@codecreator.net
    Copyright Thomas Nitschke
    
    Dies 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ß!
    

    PS:
    Bitte glaubt nicht das das Tut. meinen jetzigen Wissenstand wiederspiegelt.
    Das habe ich anno dazumal geschrieben 🙄

    [EDIT]Codetags vergessen


Anmelden zum Antworten