C++ Pointer Problem

08/10/2013 22:46 .XXShuzZzle#1
Hallo Com,

Ich hab folgendes Problem wenn ich diesen Code compiliere und dann injecte schließt sich das Spiel.
Code:
#include <iostream>
#include <Windows.h>
#include <fstream>

using namespace std;
HANDLE hfile = NULL;
typedef int FunktionPointer(int,char*);
void SendChatPacket();


BOOL WINAPI DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved) 
{
	switch(fdwReason)
	{
		case DLL_PROCESS_ATTACH:
			CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendChatPacket, NULL, 0, NULL);
		 break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
        case DLL_PROCESS_DETACH:
            break;
	}
	return TRUE;
}

void SendChatPacket(){
ofstream myfile;
myfile.open ("pointer_result.txt");
myfile << "Initiliazed\n";
FunktionPointer* function = (FunktionPointer*)0x4AEB70;
int mode = 0;
char* message = "testtest";
function(mode, message);
myfile << "Nachricht gesendet: " << message;
myfile.close();
}
Wie man sieht versuche ich den Pointer mit 2 Argumenten Auszuführen. Mit dem Inline ASM Code würde das ungefähr so aussehen (was auch funktioniert) Der folgedene ASM Code war von einer anderen Revision deswegen sind die Offsets anders:
Code:
	DWORD CHATVAR = 0x004B5AD0;
	__asm {
		MOV		ECX,DWORD PTR DS:[0x6BEA0C]
		PUSH	modus
		PUSH	message
		CALL	CHATVAR
	}
Bitte um Hilfe. Ich hab leider nichts im Internet gefunden
08/11/2013 00:06 snow#2
Das scheint ne Memberfunktion einer Klasse zu sein, dir fehlt der this-pointer im ecx-Register.
Bau deinen typedef so auf:
int __fastcall FunktionPointer(void *thisptr, void *trashptr, int, char*);

Und den Aufruf machst du mit
void *thisptr = reinterpret_cast<void *>(*reinterpret_cast<UINT_PTR *>(0x6BEA0C));
function(thisptr, nullptr, mode, message);

Beim fastcall landen die ersten 2 Parameter im ecx- und edx-Register, demnach muss der this-Pointer als erstes Argument übergeben werden.

Sollte so klappen, kann es gerade aber nicht testen.
08/11/2013 00:55 Master674b#3
Quote:
Originally Posted by snow911 View Post
Das scheint ne Memberfunktion einer Klasse zu sein, dir fehlt der this-pointer im ecx-Register.
Bau deinen typedef so auf:
int __fastcall FunktionPointer(void *thisptr, void *trashptr, int, char*);

Und den Aufruf machst du mit
void *thisptr = reinterpret_cast<void *>(*reinterpret_cast<UINT_PTR *>(0x6BEA0C));
function(thisptr, nullptr, mode, message);

Beim fastcall landen die ersten 2 Parameter im ecx- und edx-Register, demnach muss der this-Pointer als erstes Argument übergeben werden.

Sollte so klappen, kann es gerade aber nicht testen.
Bei einem typedef kann auch __thiscall als Aufrufkonvention angegeben werden. Ungültig ist __thiscall nur im Kontext einer Funktionsdeklaration.
08/11/2013 01:19 .XXShuzZzle#4
Hallo erstmal schon vielen Dank ich hab folgendes Ausprobiert:

Nur schließt sich das Spiel leider immernoch im Error Log steht folgendes:
Code:
Time Stamp: 0x50a09766 - (null)

Exception Type: 0xc0000005

eax: 0x006b47ac	ebx: 0x00000000
ecx: 0x20ba22c0	edx: 0x00000000
esi: 0x6594fed4	edi: 0x00000000
ebp: 0x6594ff88	esp: 0x6594feb0

0x006b47ac	X:\Clients\Ephelion Client\test_34k.exe
0x755133aa	C:\Windows\syswow64\kernel32.dll
0x77a89ef2	C:\Windows\SysWOW64\ntdll.dll
0x77a89ec5	C:\Windows\SysWOW64\ntdll.dll
08/12/2013 03:38 Saedelaere*#5
Injizierst du die DLL direkt beim Spielstart? Wenn ja, werden die Game Structs noch nicht initialisiert sein zu dem Zeitpunkt und dein SendChatPacket Call geht deshalb in die Hose.
08/12/2013 15:56 Padmak#6
Quote:
Originally Posted by snow911 View Post
Das scheint ne Memberfunktion einer Klasse zu sein, dir fehlt der this-pointer im ecx-Register.
Bau deinen typedef so auf:
int __fastcall FunktionPointer(void *thisptr, void *trashptr, int, char*);

Und den Aufruf machst du mit
void *thisptr = reinterpret_cast<void *>(*reinterpret_cast<UINT_PTR *>(0x6BEA0C));
function(thisptr, nullptr, mode, message);

Beim fastcall landen die ersten 2 Parameter im ecx- und edx-Register, demnach muss der this-Pointer als erstes Argument übergeben werden.

Sollte so klappen, kann es gerade aber nicht testen.
Das hier ist VÖLLIG falsch, falls der TE nicht den Borland C++-Compiler (Embarcadero) benutzt sondern den Visual C++-Compiler

Mit Visual C++ sieht der typedef so aus:
typedef int (__thiscall* TSendChatPacket)(int _this, int mode, const char* message);

Und auch sonst ist dein Code völliger Schwachsinn:
Die Funktion und this können nicht beide die gleiche Adresse haben.
0x6B47AC ist zwar tatsächlich die CPythonNetworkStream-Instanz, die Funktion hat aber 'ne völlig andere Adresse.

Tu uns allen einen Gefallen: es gibt schon genügend Crap-Code in Metin2, bitte gesell dich nich auch noch dazu^^

Padmak
08/12/2013 16:10 snow#7
Quote:
Originally Posted by Padmak View Post
Das hier ist VÖLLIG falsch, falls der TE nicht den Borland C++-Compiler (Embarcadero) benutzt sondern den Visual C++-Compiler

Mit Visual C++ sieht der typedef so aus:
typedef int (__thiscall* TSendChatPacket)(int _this, int mode, const char* message);
Das mit dem thiscall wusste ich bisher tatsächlich noch nicht, dennoch sollte die Convention mit ecx & edx eingehalten werden, oder nicht? Letztendlich ist es dann eine hässliche Lösung, aber sie hat das Potential um um zu funktionieren.
Habe seit einiger Zeit keine thiscalls mehr benötigt. :o

War der Rest des Textes noch mir gewidmet? :D ich hab nur das mit dem this-Pointer aufgegriffen, mit Metin2 kenne ich mich nicht aus..
08/12/2013 18:18 MrSm!th#8
Quote:
Originally Posted by Padmak View Post
Das hier ist VÖLLIG falsch, falls der TE nicht den Borland C++-Compiler (Embarcadero) benutzt sondern den Visual C++-Compiler

Mit Visual C++ sieht der typedef so aus:
typedef int (__thiscall* TSendChatPacket)(int _this, int mode, const char* message);

Und auch sonst ist dein Code völliger Schwachsinn:
Die Funktion und this können nicht beide die gleiche Adresse haben.
0x6B47AC ist zwar tatsächlich die CPythonNetworkStream-Instanz, die Funktion hat aber 'ne völlig andere Adresse.

Tu uns allen einen Gefallen: es gibt schon genügend Crap-Code in Metin2, bitte gesell dich nich auch noch dazu^^

Padmak
Und wo siehst du, dass this und Function ptr gleich sind?
Spätestens beim Hooken wird er ohnehin fastcall benötigen, da thiscall nicht für normale Funktionen angegeben werden kann.
08/12/2013 20:06 Padmak#9
Schau in den Spoiler in Beitrag 4, da is das drin:
Code:
FunktionPointer* function = (FunktionPointer*)0x6B47AC;
void *thisptr = reinterpret_cast<void *>(*reinterpret_cast<UINT_PTR *>(0x6B47AC));
@snow:
Nur der Anfang war an dich, bei Microsoft is bei __thiscall this im ECX-Register, der Rest auf'm Stack

@MrSm!th:
Man kann sehr wohl Funktionen mit __thiscall angeben (zumindest in VC++2010):
Code:
class foo
{
public:
    static void __thiscall bar(void* _this);
};
Padmak
08/12/2013 21:35 MrSm!th#10
Das ist ja auch innerhalb einer Klasse. Außerhalb einer Klasse ist das nicht möglich.
Aber interessante Kombination. Obwohl VS mir die Zeile unterstreicht und sagt, dass __thiscall nur bei nicht-statischen Methoden zulässig ist (was auch Sinn macht, da statische Methoden keinen thisptr bekommen), kompiliert es fehlerfrei.
Und was noch viel interessanter ist: Ein Funktionspointer auf so eine Funktion lässt sich einfach in einen normalen Ganzzahltypen casten. Versuch das mal mit einem Pointer auf eine normale Methode, da biste ewig am rumcasten und rumprobieren, bis das fehlerfrei kompiliert und dann auch noch das gewünschte Ergebnis bringt.
Ein durchaus netter und praktischer Workaround.

Allerdings stelle ich es mir schwierig vor, den thisptr bei dieser Methodik abzurufen. Als ersten Parameter könnte man ihn ja nicht angeben, der müsste ja wie gewohnt auf dem Stack liegen.

Btw. laut MSDN wird __thiscall auf x64 ignoriert.
08/12/2013 21:40 Padmak#11
Ich weiß, ist durchaus ganz praktisch. Dass es nur innerhalb einer Klasse geht wusste ich, gibt aber auch Kapselungstechnisch durchaus Sinn

Quote:
Originally Posted by MrSm!th View Post
Allerdings stelle ich es mir schwierig vor, den thisptr bei dieser Methodik abzurufen. Als ersten Parameter könnte man ihn ja nicht angeben, der müsste ja wie gewohnt auf dem Stack liegen.
Was genau meinst du damit?
Wenn du eine __thiscall-Funktion gehookt hast, ist der in meiner Funktion als void* _this angegebene Parameter tatsächlich der this-Pointer, also ECX
Oder meintest du etwas anderes?

Padmak
08/12/2013 21:45 MrSm!th#12
Das ergibt keinen Sinn, wieso sollte der Compiler den ersten Parameter im ECX Register erwarten. Eigentlich müsste er für deinen _this Parameter auf den Stack zugreifen. Und eigentlich hat IntelliSense auch Recht damit, dass __thiscall nur für nicht-statische Methoden erlaubt sein sollte, immerhin unterscheidet sich eine statische Methode nicht von einer Funktion und hat nichts mit einem Thisptr am Hut. Ich denke, das wird dann nur eine Optimierung sein, dass er dafür bei dir das ECX-Register nimmt. Das tut MSVC auch gerne ohne __thiscall.

Btw. Auf x64 wird __thiscall laut MSDN ignoriert.
08/12/2013 22:25 Padmak#13
Bei Microsoft ist this immer in ECX, das ist so festgelegt.
Wenn ich als __thiscall compile, erwarte und bekomme ich auch immer den this-Pointer da, wo ich ihn haben will
Ich hab natürlich auch nur in VC++-Exen getestet, bei Metin2 ist es aber definitiv so und funktioniert auch super

Padmak
08/13/2013 00:13 MrSm!th#14
Quote:
Originally Posted by Padmak View Post
Bei Microsoft ist this immer in ECX, das ist so festgelegt.
Nur gibt es in der Funktion kein This, weil sie statisch ist.
Dein _this ist schlichtweg der erste Parameter. Du könntest auch einfach das static und den Parameter weglassen und innerhalb der Funktion sogar über das Schlüsselwort this auf den thisptr zugreifen. Lediglich das Übergeben von Zeigern auf normale Methoden gestaltet sich etwas kompliziert.
Quote:
Wenn ich als __thiscall compile, erwarte und bekomme ich auch immer den this-Pointer da, wo ich ihn haben will
Ich hab natürlich auch nur in VC++-Exen getestet, bei Metin2 ist es aber definitiv so und funktioniert auch super

Padmak
Das ist schon in sich widersprüchlich, denn bei einer thiscall Funktion wäre der thisptr logischerweise über das this Schlüsselwort verfügbar und müsste nicht als erster Parameter notiert werden.
08/13/2013 03:13 Padmak#15
Um das hier nochmal klarzustellen: ich rede bei dieser Verwendung des __thiscalls wirklich nur von Hooks in Programmen, die wie meine in Visual C++ geschrieben wurden
Ich rufe die Funktionen aber teils auch selbst auf, halt mit meinem gewünschten this-Wert als ersten Parameter.
Dass die Funktionen an sich keine wirklichen thiscall-Funktionen sind, ist ja logisch. Für Hooks funktioniert es aber wunderbar, in anderen Fällen sollte man das in C++ eigentlich eh nicht mehr brauchen

Padmak