Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > C/C++
You last visited: Today at 06:10

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Klassenfunktion eines anderen Prozesses ausfürhen

Discussion on Klassenfunktion eines anderen Prozesses ausfürhen within the C/C++ forum part of the Coders Den category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Jan 2010
Posts: 23
Received Thanks: 2
Klassenfunktion eines anderen Prozesses ausfürhen

Hallo,

ich beschäftige mich im Moment mit Reverse Engineering und dem Schreiben eines Bots für ein RTS-Spiel und brauche dabei etwas Hilfe. Die Programme, die ich benutze sind CheatEngine und IDA Pro. Bei dem Spiel handelt es sich um Heroes of Newerth. Der Programmcode für das Spiel befindet sich in 3 Dlls:
1) k2.dll: enthält viele Klassen und einige statische Pointeradressen, die exportiert werden
2) game_shared.dll: enthält weitere Klassen, die exportiert werden
3) cgame.dll: hier werden die Funktionen importiert und allem Anschein nach verwendet

Bei einigen Klassen bzw. Objekten ist es mir bereits gelungen, statische Adressen zu finden, z. B. die Adresse, die auf ein Objekt der Klasse CHost zeigt: ["cgame.dll"+1C986C]. Die Klasse CHost stellt einige Funktionen bereit, die benötigt werden, um tiefer zu gehen. Beispielsweise die Funktion CHostServer* CHost::GetServer(void). Der asm-Code der Funktion sieht wie folgt aus:
Code:
.text:15030520 ; public: class CHostServer * __thiscall CHost::GetServer(void)
.text:15030520                 public ?GetServer@CHost@@QAEPAVCHostServer@@XZ
.text:15030520 ?GetServer@CHost@@QAEPAVCHostServer@@XZ proc near
.text:15030520                                         ; DATA XREF: .rdata:off_1582B2A8o
.text:15030520                 mov     eax, [ecx+78h]
.text:15030523                 retn
.text:15030523 ?GetServer@CHost@@QAEPAVCHostServer@@XZ endp
Nun, ich möchte gerne an das Objekt herankommen. Ich mir in CheatEngine mit der Dissect data/structure Funktion den Speicherbereich an der Stelle ["cgame.dll"+1C986C]+78 angeguckt, aber an der Stelle ist der Wert stets 0 (also kein Pointer vorhanden). Ich fürchte ich mache hier irgendwo einen Fehler.
Deswegen habe ich mir überlegt, eine Dll zu injecten, die die statische Adresse des Objektes kennt. Meine Frage ist: Wie kann ich aus meiner Dll heraus eine Memberfunktion der CHost Klasse aufrufen?

Dankbar bin ich für jeden Tipp, sowie für jeden weiteren Ratschlag. Bitte sagt mir, wie viel Erfolg ich mit meiner Überlegung haben werde! Ist vielleicht die ReadProcessMemory-Variante (ohne Dll-Injection) genauso erfolgreich?

n' schönen Abend noch
alkololl is offline  
Old 04/12/2013, 22:48   #2
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
wenn es nur ein CHost objekt gibt und in diesem an der stelle 0x78 immer NULL steht, wird es dir nichts bringen die ingamefunktion aufzurufen - die macht schließlich auch nichts anderes als *(DWORD*) (ThisPtr + 0x78) zurückzugeben - wird dementsprechend auch immer 0 zurückgeben.

generell kannst du eine funktion per typedef deklarieren und aufrufen:

Code:
typedef DWORD (__thiscall* CHost__GetServer_t)(void*);
CHost__GetServer_t = (CHost__GetServer_t) 0x15030520; // Wird vermutlich dynamisch sein, musst also mit getmodulehandle die base holen und offset raufrechnen
DWORD Server = CHost__GetServer_t(*(void**) (CGameDllBase + 0x1C986C));
Dr. Coxxy is offline  
Thanks
1 User
Old 04/13/2013, 01:22   #3
 
elite*gold: 0
Join Date: Jan 2010
Posts: 23
Received Thanks: 2
Quote:
Originally Posted by Dr. Coxxy View Post
wenn es nur ein CHost objekt gibt und in diesem an der stelle 0x78 immer NULL steht, wird es dir nichts bringen die ingamefunktion aufzurufen - die macht schließlich auch nichts anderes als *(DWORD*) (ThisPtr + 0x78) zurückzugeben - wird dementsprechend auch immer 0 zurückgeben.
Dann verstehe ich nicht, wieso da
Code:
.text:15030520                 mov     eax, [ecx+78h]
steht. Was habe ich denn falsch verstanden? Oder brauchst Du, um mir helfen zu können, noch zusätzliche Infos?
alkololl is offline  
Old 04/13/2013, 02:08   #4
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
verstehe dein problem nicht.
ecx ist der this pointer, an der hex stelle 78 von dem objekt ist offensichtlich ein pointer auf ein CHostServer Objekt, was wohl anscheinend == NULL ist, also kein valider pointer da ist.
kann sein, dass das nur unter bestimmten bedingungen gefüllt ist, z.b. wenn man auf einem server ist, musst du ausprobieren.

CHost klasse könnte bspw. so aussehen:
Code:
class CHostServer;
	
class CHost
{
public:
	BYTE Unknown1[120]; // Placeholder
	CHostServer* m_CHostServer; // 0x78 
public:
	CHostServer* GetServer() { return m_CHostServer; }
};
Dr. Coxxy is offline  
Thanks
1 User
Old 04/13/2013, 02:21   #5
 
elite*gold: 0
Join Date: Jan 2010
Posts: 23
Received Thanks: 2
Mein Problem ist das Folgende:
Es gibt einen weiteren statischen Pointer, diesmal auf ein IGame-Objekt, der diese Adresse hat: ["cgame.dll"+1C986C]. An Offset 0x188 ist ein Pointer auf ein CClientAccount-Objekt. Die Klasse CClientAccout ist in k2.dll definiert und hat eine Funktion, die so aussieht:
Code:
.text:150296E0 ; public: unsigned int __thiscall CClientAccount::GetSilverCoins(void)const
.text:150296E0                 public ?GetSilverCoins@CClientAccount@@QBEIXZ
.text:150296E0 ?GetSilverCoins@CClientAccount@@QBEIXZ proc near
.text:150296E0                                         ; DATA XREF: .rdata:off_1582B2A8o
.text:150296E0                 mov     eax, [ecx+1C8h]
.text:150296E6                 retn
.text:150296E6 ?GetSilverCoins@CClientAccount@@QBEIXZ endp
Man achte auf die 0x1C8. Das ist anscheinend der Offset zu dem unsigned int, der die Anzahl der "SilverCoins" speichert. Soviel zur Theorie. Mit Hilfe von CheatEngine habe ich aber herausgefunden, dass der Offset 0x204 ist ([["cgame.dll"+1C986C]+188]+204), also 0x3C mehr, als in der Funktionsdefinition steht.
Ich kann mich also gar nicht auf die in den Funktionen definierten Offsets verlassen und fürchte daher auch einen falschen Offset für den CHostServer-Pointer zu haben.

Weiterhin frage ich mich, ob es notwendig ist, eine Dll in das Spiel zu injecten, oder ob ich mit simplem Read- und WriteProcessMemory auskomme, um z. B. meinem Held den Befehl zu geben, an Punkt X hinzulaufen.
alkololl is offline  
Old 04/13/2013, 02:25   #6


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,104
Received Thanks: 681
Nur Read- / WriteProcessMemory wird für eine solche Aufgabe nicht ausreichen. Entweder du befindest dich im selben Prozess oder du nutzt CreateRemoteThread (in Kooperation mit WPM natürlich ), um von außen dein Ziel zu erreichen.
MfG
Jeoni
Jeoni is offline  
Thanks
1 User
Old 04/13/2013, 02:33   #7
 
elite*gold: 0
Join Date: Jan 2010
Posts: 23
Received Thanks: 2
Quote:
Originally Posted by Jeoni View Post
Nur Read- / WriteProcessMemory wird für eine solche Aufgabe nicht ausreichen. Entweder du befindest dich im selben Prozess oder du nutzt CreateRemoteThread (in Kooperation mit WPM natürlich ), um von außen dein Ziel zu erreichen.
MfG
Jeoni
Okay. Werde wohl dann den Weg mit der Dll wählen. Dann bleibt mir nur noch die Frage: Wenn ich die Adresse eines Objekts habe und einer Funktion, die über das Objekt aufrufbar ist (z. B. CClientAccount::GetSilverCoins()), wie rufe ich dann die Funktion für das Objekt auf?
alkololl is offline  
Old 04/13/2013, 11:36   #8
 
Schlüsselbein's Avatar
 
elite*gold: 0
Join Date: Feb 2013
Posts: 1,137
Received Thanks: 869
Da ein pointer auf das Objekt in c++ immer das erste Argument einer Methode ist, übergibst du - wer hätte das gedacht - einen Zeiger auf das Objekt als in dem Fall einzigen Parameter.
Schlüsselbein is offline  
Old 04/13/2013, 12:25   #9
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
Quote:
Originally Posted by alkololl View Post
Okay. Werde wohl dann den Weg mit der Dll wählen. Dann bleibt mir nur noch die Frage: Wenn ich die Adresse eines Objekts habe und einer Funktion, die über das Objekt aufrufbar ist (z. B. CClientAccount::GetSilverCoins()), wie rufe ich dann die Funktion für das Objekt auf?
wie ich bereits sagte, im register ecx wird der this pointer übergeben, wie ich das hier auch gemacht habe:

Code:
DWORD Server = CHost__GetServer_t(*(void**) (CGameDllBase + 0x1C986C));
es wird dir aber nichts bringen, weil die funktion auch nix anderes macht als an dem übergebenen objekt an einem bestimmten offset auszulesen.
Woher hast du denn überhaupt diese disassembly?
Code:
.text:150296E0 ; public: unsigned int __thiscall CClientAccount::GetSilverCoins(void)const
.text:150296E0                 public ?GetSilverCoins@CClientAccount@@QBEIXZ
.text:150296E0 ?GetSilverCoins@CClientAccount@@QBEIXZ proc near
.text:150296E0                                         ; DATA XREF: .rdata:off_1582B2A8o
.text:150296E0                 mov     eax, [ecx+1C8h]
.text:150296E6                 retn
.text:150296E6 ?GetSilverCoins@CClientAccount@@QBEIXZ endp
sicher, dass die noch aktuell ist?
das hier:

Quote:
Man achte auf die 0x1C8. Das ist anscheinend der Offset zu dem unsigned int, der die Anzahl der "SilverCoins" speichert. Soviel zur Theorie. Mit Hilfe von CheatEngine habe ich aber herausgefunden, dass der Offset 0x204 ist ([["cgame.dll"+1C986C]+188]+204), also 0x3C mehr, als in der Funktionsdefinition steht.
darf eigentlich nicht sein!
Dr. Coxxy is offline  
Old 04/13/2013, 12:57   #10
 
elite*gold: 0
Join Date: Jan 2010
Posts: 23
Received Thanks: 2
Quote:
Originally Posted by Schlüsselbein View Post
Da ein pointer auf das Objekt in c++ immer das erste Argument einer Methode ist, übergibst du - wer hätte das gedacht - einen Zeiger auf das Objekt als in dem Fall einzigen Parameter.
Okay. Soetwas habe ich noch nie gemacht. Das fertige Programm von euch zu verlangen wäre unverschämt, aber vielleicht kann mir jemand sagen, was ich googlen muss, um herauszufinden, wie ich das im Programm umsetze.

Quote:
Originally Posted by Dr. Coxxy View Post
wie ich bereits sagte, im register ecx wird der this pointer übergeben, wie ich das hier auch gemacht habe:

Code:
DWORD Server = CHost__GetServer_t(*(void**) (CGameDllBase + 0x1C986C));
es wird dir aber nichts bringen, weil die funktion auch nix anderes macht als an dem übergebenen objekt an einem bestimmten offset auszulesen.
Ja ich weiß, aber ich muss erst anfangen ein paar einfache Methoden aufzurufen, damit ich mich später an schwierigere wagen kann. Wie gesagt, ich habe mich mit so etwas noch nie beschäftigt (dem Aufrufen von Funktionen eines anderen Prozesses) und wenn ich schaffe, einfache Funktionen auszuführen, schaffe ich auch schwierigere

Quote:
Originally Posted by Dr. Coxxy View Post
Woher hast du denn überhaupt diese disassembly?
Code:
...
sicher, dass die noch aktuell ist?
Die Assembly habe ich mit IDA pro aus der aktuellen Version von dem Spiel. Die Offsets müssten also richtig sein. Es gibt insgesamt 6 Pointer, die auf den Wert der "SilverCoins" zeigen.
[["cgame.dll"+001C986C]+188]+204
[["game_shared.dll"+004AD29C]+188]+204
[[["cgame.dll"+001C986C]+188]+5C]+204
[[["game_shared.dll"+001C986C]+188]+5C]+204
[[["cgame.dll"+001C986C]+188]+254]+204
[[["game_shared.dll"+001C986C]+188]+254]+204
Der letzte Offset ist jedes Mal 0x204. Kann es sein, dass die Klasse CClientAccount eine Überklasse hat?
alkololl is offline  
Old 04/13/2013, 13:04   #11
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
wie du eine funktion aufrufst habe ich hier schon erklärt:

Code:
typedef DWORD (__thiscall* CHost__GetServer_t)(void*);
CHost__GetServer_t = (CHost__GetServer_t) 0x15030520; // Wird vermutlich dynamisch sein, musst also mit getmodulehandle die base holen und offset raufrechnen
DWORD Server = CHost__GetServer_t(*(void**) (CGameDllBase + 0x1C986C));
kannst dir auch mal das hier anschauen:
Dr. Coxxy is offline  
Old 04/13/2013, 13:17   #12
 
Schlüsselbein's Avatar
 
elite*gold: 0
Join Date: Feb 2013
Posts: 1,137
Received Thanks: 869
Um besser zu verstehen könntest du dir ein kleines Beispiel programmieren, dann kompilieren und durch den Assembly-Code mit nem Debugger steppen. Dadurch bleibt anderes Zeug weg, dass dich vielleicht nur noch mehr verwirren könnte.

Mit Visual Studio geht das alles ohne Probleme und extra Tools: Einfaches Beispiel erstellen (ne Klasse, die irgendwas mit ner Zahl anstellt). Dann von der Klasse 2, 3 Objekte erzeugen und die Methoden aufrufen. Breakpoint setzen, zum disassembly tab wechseln, durchsteppen und bestenfalls verstehen.
Pass nur auf, dass Optimierungen ausgeschaltet sind (einfach den Debug-build benutzen), denn unter C++ dürfen auch komplette Klassen rausoptimiert werden.

Die Funktion callen kannst du dann zum Beispiel auf die gleiche Art via inline assembler (in deiner dll!).
Schlüsselbein is offline  
Old 04/13/2013, 19:59   #13
 
elite*gold: 0
Join Date: Jan 2010
Posts: 23
Received Thanks: 2
Quote:
Originally Posted by Dr. Coxxy View Post
wie du eine funktion aufrufst habe ich hier schon erklärt:

Code:
typedef DWORD (__thiscall* CHost__GetServer_t)(void*);
CHost__GetServer_t = (CHost__GetServer_t) 0x15030520; // Wird vermutlich dynamisch sein, musst also mit getmodulehandle die base holen und offset raufrechnen
DWORD Server = CHost__GetServer_t(*(void**) (CGameDllBase + 0x1C986C));
kannst dir auch mal das hier anschauen:
Dein Tutorial finde ich super. Das hilft mir wirklich ungemein. Gibt es eine gute Methode, die IGame-Struct mit einem Programm automatisch generieren zu lassen? Ich möchte die Abstände (BYTE unkown[...]) nicht selbst berechnen müssen. ReClass ist gut, aber erstens sehr alt und zweitens muss ich die Adressen ständig neu eingeben. Außerdem kann ich an Offset 0x188 nicht auswählen, dass er meine vordefinierte Klasse CClientAccount nehmen soll. Stattdessen, soll ich die Klasse nochmal an dem Offset definieren. Das gefällt mir nicht.
Die Dissect data/structures Funktion von CheatEngine gefällt mir nicht, denn wenn man einen Offset löscht, werden die nachfolgenden Offsets nicht neu berechnet, i. e. die Daten fallen weg. Außerdem habe ich noch keine Funktion gefunden, die Structure als C++ struct zu exportieren.

EDIT: Die Adresse muss man nicht jedes mal neu eingeben, da es die Operatoren & und * gibt. [["cgame.dll"+188]+b4]+0 wäre demnach &cgame.dll+*188+*b4.
alkololl is offline  
Old 04/13/2013, 21:18   #14
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
Quote:
Originally Posted by alkololl View Post
Dein Tutorial finde ich super. Das hilft mir wirklich ungemein. Gibt es eine gute Methode, die IGame-Struct mit einem Programm automatisch generieren zu lassen? Ich möchte die Abstände (BYTE unkown[...]) nicht selbst berechnen müssen. ReClass ist gut, aber erstens sehr alt und zweitens muss ich die Adressen ständig neu eingeben. Außerdem kann ich an Offset 0x188 nicht auswählen, dass er meine vordefinierte Klasse CClientAccount nehmen soll. Stattdessen, soll ich die Klasse nochmal an dem Offset definieren. Das gefällt mir nicht.
Die Dissect data/structures Funktion von CheatEngine gefällt mir nicht, denn wenn man einen Offset löscht, werden die nachfolgenden Offsets nicht neu berechnet, i. e. die Daten fallen weg. Außerdem habe ich noch keine Funktion gefunden, die Structure als C++ struct zu exportieren.
Programmier dir selber eins, hab ich damals auch gemacht.
Ansonsten musste halt mit ReClass vorlieb nehmen.
Dr. Coxxy is offline  
Old 04/13/2013, 22:57   #15
 
elite*gold: 0
Join Date: Jan 2010
Posts: 23
Received Thanks: 2
Dann nehme ich mit ReClass vorlieb. Gibt es eine saubere und einfache Möglichkeit die injizierte Dll mit dem Loader kommunizieren zu lassen? NamedPipes sind dafür nicht geeignet, denke ich.
alkololl is offline  
Reply

Tags
dll, heroes of newerth, readprocessmemory, reverse engineering


Similar Threads Similar Threads
Anzeigen eines Wertes (inkl. Änderungen) aus dem Speicher eines anderen Programmes
01/09/2012 - General Coding - 2 Replies
Hi Leute, ich habe mir ein kleines Programm mit Hilfe folgenden Tutorials gemacht: http://www.elitepvpers.com/forum/coding-tutorials /225242-tutorial-gamehacking-howto-i-ger.html Habe allerdings mit Visual Studio Express eine CLI-Anwendung erstellt (anstelle wie im Tutorial beschrieben eine MFC-Anwendung). Das Lesen und Schreiben des Wertes funktioniert soweit auch gut. Nun habe ich mich allerdings gefragt, ob man die Wertänderung der Punkte von Solitär (die ja durch hochlaufen der...
Wie erlange ich die PID eines Prozesses für z.B. WriteProcessMemory
11/06/2008 - Coding Tutorials - 4 Replies
An die, die noch nicht wissen, wie sie ein Handle eines Prozesses erlangen, folgt hier ein kleiner Beispielquelltext . Beispielprogramm: .386 .model flat, stdcall option casemap :none include windows.inc include kernel32.inc include user32.inc
Sound eines anderen hören.
03/08/2008 - Technical Support - 4 Replies
Hi, freund hat vor kurzem PC neu aufgesetz und seitdem hat er probleme mit seinem sound. Bis vor 2 Tagen ging das Micro gar ned und jetz wo es geht haben wir das problem das ich alles höre was er tut also wenn er music hört hör ich sie ganz normal als würd ich sie auf meinem PC hören. Es liegt nicht daran das er micro zu nah an sound ist da es nicht leiser wird, bzw wenn er seinen ton ausmacht ich mich noch immer hör wenn ich laber... Hoffe es kann mir wer helfen bzw meinem Freund :D



All times are GMT +2. The time now is 06:10.


Powered by vBulletin®
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2024 elitepvpers All Rights Reserved.