|
You last visited: Today at 19:37
Advertisement
MSVC -__thiscall Implementation
Discussion on MSVC -__thiscall Implementation within the C/C++ forum part of the Coders Den category.
08/12/2013, 18:18
|
#1
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,902
Received Thanks: 25,407
|
Jo, hier einmal die ausgelagerte Version der Diskussion über __thiscall.
Kann jemand was zu der Implementation sagen? Wie schreibt es eigentlich der Standard vor (oder ist __thiscall MS spezifisch)?
Mich wundert vor allem der sinnvolle Hinweis von IntelliSense, dass thiscall bei statischen Methoden nicht zulässig ist, während es der Compiler dennoch annimmt.
Was wäre die eleganteste Methode, echte Klassenmethoden (keinen DX-like C-Nachbau) zu definieren, um sie nutzen zu können, sprich hooken und aufrufen.
Eine Möglichkeit, die Methoden von reversed Klassen auch direkt in deren Deklarationen angeben zu können, um komfortables OOP zu nutzen, wäre schon schön. Mit den trivialen Lösungen ist mir das bisher nicht gelungen und Padmaks Lösung kann ich nicht nachvollziehen (zumal eine statische Methode schonmal für polymorphe Klassen ungünstig ist). Gerade eine elegante Möglichkeit, mit Methodenzeigern zu hantieren, wäre mir willkommen.
Hier mal der Inhalt des ersten relevanten Posts:
Quote:
Originally Posted by Padmak
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
|
#2
|
elite*gold: 58
Join Date: Jun 2008
Posts: 2,311
Received Thanks: 8,420
|
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
|
#3
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,902
Received Thanks: 25,407
|
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
|
#4
|
elite*gold: 58
Join Date: Jun 2008
Posts: 2,311
Received Thanks: 8,420
|
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
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
|
#5
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,902
Received Thanks: 25,407
|
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
|
#6
|
elite*gold: 58
Join Date: Jun 2008
Posts: 2,311
Received Thanks: 8,420
|
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
|
#7
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,902
Received Thanks: 25,407
|
Quote:
Originally Posted by Padmak
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
|
#8
|
elite*gold: 58
Join Date: Jun 2008
Posts: 2,311
Received Thanks: 8,420
|
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
|
|
|
08/13/2013, 08:32
|
#9
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
__thiscall ist afaik im standard nirgendwo definiert, der gcc macht soweit ich weiß das gleiche wie nen cdecl, nur, dass der thisptr als letzter parameter gepusht wird (macht der ms compiler glaub ich auch so bei klassenmethoden mit variablen parametern [?]).
das mit über ECX übergeben ist ms spezifisch.
Mit der static methode als __thiscall zu definieren war mir neu, dass das geht, ich hab bisher immer __thiscall für den typedef benutzt und für eine hookdefinition immer __fastcall dann mit nem DWORD UselessEDX als 2. parameter.
EDIT:
Grad nochn bissle rumgetestet, eine zufällige compileroptimierung halte ich für unwahrscheinlich, das wäre zuviel des guten.
Außerdem benutzt der msvc dafür normalerweise EDI (macht er bei mir auch ohne __thiscall).
Um auf Smiths ersten post zurückzukommen, man kann sich die adresse einer memberfunktion relativ simpel ercheaten:
Code:
class Foo
{
public:
void Bar();
};
template<typename T> DWORD GetMemberAddress( T Func )
{
return *((DWORD*) &Func);
}
printf("Address of Foo::Bar: %08X\n", GetMemberAddress(&Foo::Bar));
|
|
|
08/13/2013, 13:37
|
#10
|
elite*gold: 58
Join Date: Jun 2008
Posts: 2,311
Received Thanks: 8,420
|
Ich frage mich gerade (nur ein Gedanke, keine Ahnung ob das funktionieren kann) ob man nicht statt der eigenen Funktion auch ein boost::bind-Objekt übergeben kann, vor allem wenn man den this-Pointer schon vorher kennt
Ich glaube dass this in ECX schon fast als Standard angesehen werden kann (bei MSVC), das habe ich jetzt schon in mehreren Artikeln zu Calling Conventions gesehen, nicht zuletzt sogar auf Wikipedia.
Warum meine static-Methode funktioniert kann ich ehrlich gesagt auch nicht sagen, dass IntelliSense das unterkringelt wusste ich gar nicht, da ich VisualAssistX installiert habe hab ichs darauf geschoben^^
Aber ehrlich gesagt: ich hab mir bisher echt null Gedanken darüber gemacht, wieso es geht. Bisher habe ich alles mit MSVC compiled und nur in Programmen gehooked, die damit geschrieben wurden.. Ich glaube ich wäre auf ernsthafte Probleme gestoßen, bin mal gespannt was jetzt hier rauskommt^^
Padmak
|
|
|
08/13/2013, 15:12
|
#11
|
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
|
Boost wird gar nicht benötigt, die Standardbibliothek ist genug. Ein kleines Beispielprojekt mit std::mem_fn:
Code:
#include <iostream>
#include <functional>
using namespace std;
class C {
private:
int a;
int func (int b) {
return a += b;
}
public:
C (int a = 0) : a (a) {}
typedef decltype (& C::func) func_type;
//oder:
using func_type2 = decltype (& C::func);
//oder:
typedef int (C::* func_type3) (int);
//oder:
using func_type4 = int (C::*) (int);
//es wird daraus:
typedef int (__thiscall C::* ms_func_type) (int);
static_assert (is_same <func_type3, ms_func_type>::value, "falscher Compiler");
static func_type get_func ();
};
auto C::get_func () -> decltype (& C::func) {
return & C::func;
}
int main () {
C c (1);
cout << "1 + 2 = " << mem_fn (C::get_func ()) (c, 2) << endl;
cin.get ();
}
|
|
|
 |
Similar Threads
|
Chi system implementation
07/28/2013 - CO2 Private Server - 6 Replies
Chi system implementation ,
i found this from the egy site.
anyone could pin point where to put this codes?
using Conquer_Online_Server.Client;
using System;
namespace Conquer_Online_Server.Network.GamePackets
{
|
XTrap free implementation?
05/11/2013 - Cabal Online - 1 Replies
Hi everyone. About an year ago I remember reading a thread somewhere in the Cabal section. It was a guide that explained how to implement cracked versions of XTrap to your own Cabal pserver client FOR FREE.
I've used the search function, with no success. Does someone remember the thread or I just imagined it? May I get a link?
Thanks in advance.
|
sms billing implementation
01/22/2013 - SRO Private Server - 1 Replies
Hey guys im working with a new sro server and we have a moneybookers and paypal set up but i wanted to set up a Fortumo or something like tht for our pinoy players and the others who dnt use playpal.
I have never set up sms b4 to work with my server so i would really appreciate help figuring this out. A link to a guide or something thatll get me thru this pain in the ass siutation.
You can reply here or add me to Skype if you able to help....thanks
|
[HELP] Problems with new map implementation
09/09/2012 - Metin2 Private Server - 0 Replies
Hy,
I'm having some problems in implementing new maps. Everything is done right but i can only warp to the new map with one character. Each time I try to warp with a different character I am warped to map1/village. And I get the following error in syserr:
SYSERR: Sep 9 18:21:04 :: Entergame: !GetMovablePosition (name TestWarp 1243200x1243300 map 195 changed to 1273200x1274000)
I don't think that it is an implementation error because there is 1 character i can warp there. But I made 10...
|
msvc++ kann kein projekt erstellen
09/03/2011 - C/C++ - 0 Replies
Hey,
Immer wenn ich msvc++ starte und dann auf neues projekt gehe name eingebe steht unten das projekt xx wird erstellt.....fehler beim erstellen des projekts egal was ich mache es geht nicht weg pls help !
|
All times are GMT +1. The time now is 19:37.
|
|