Hilfe mit Assembler Code, this-Pointer!
-
Ich sehe da so leider immer noch keine konkrete Frage, die etwas mit Assembler zu tun haette.
Wie gesagt: Da der Compiler diese lokale Objekt-Instanz dynamisch auf dem Stack haelt, gibt es keine statische Adresse, auf die du immer zugreifen kannst. Wie du prinzipiell in Assembler an diese auf dem Stack abgelegte Referenz deines Objekts rankommst, kannst du ja im Code sehen. Wie es halt so mit lokalen Variablen ist, verschwinden diese, wenn du die Funktion verlaesst, in der sie definiert wurden, bzw. du kannst von anderen Funktionen aus nicht ohne irgendeinen Pointer oder Referenz auf sie zugreifen. Dh. du koenntest zB. von Funktionen (in einer DLL zB.) auf deine Klassen-Instanz zugreifen, wenn du diesen Funktionen die Referenz auf die Klasse als Parameter uebergibst. Wie das in Assembler prinzipiell laeuft, solltest du dir eigentlich leicht zusammenreimen koennen.
Falls du allgemein wissen moechtest, wie du nun einen Pointer/Referenz auf dein Objekt bekommst, frage bitte im C++-Forum, bzw. bei allgemeinen Fragen zu DLLs evtl. bei WinAPI.
Ich halte es aus naheliegenden Gruenden BTW fuer keine gute Idee, mit Assembler derart in den Innereien von abstrakten Hochsprachen rum zu basteln, bzw. es wird dir in diesem Fall kein Stueck weiter helfen, falls du das dachtest.
-
Ich versuch mal noch mal mein Vorhaben zu beschreiben, also:
- ich habe hier mein Programm A, das eine Klasse CTest beinhaltet
- ich will eine eigne DLL in Prozess A injizieren, aus der ich eine Methode von Klasse CTest aufrufen will
- da ich ja nun nicht einfach einen Funktionspointer auf die Memberfunktion definieren kann Bsp:typedef void (*fpShowValue)( void ); fpShowValue fpShow = (fpShowValue)(0x12345678) fpShow( ); // ~> crash
Dies wuerde ja zum crash fuehren, mit der Fehlermeldung, dass irgendwo in der Funktion auf leeren Speicher bzw. falschen Speicher zugegriffen wurde. Also dachte ich ich stricke das ganze so um:
typedef void (__thiscall *fpShowValue)( void ); fpShowValue fpShow = (fpShowValue)(0x12345678) void CallShow( ) { _asm { mov eax, ClassPointer lea ecx, eax push ecx } fpShow( ); }
ECX soll ja nach __thiscall immer die Referenz zur Klasse enthalten. Bin mir jetzt nicht sicher, ob die definition von CallShow( ) so ganz richtig ist, aber ich denke nun verstehst du wieso ich den Pointer brauch?
Gruß Tobi
-
Ich glaub ich habs, hier mien Code:
class CTest { private: int m_iValue; public: CTest( ) { m_iValue = 0; } CTest( int iVal ) : m_iValue( iVal ) { } ~CTest( ) { } void SetValue( int iNewValue ) { this->m_iValue = iNewValue; } void ShowValue( ) { printf( "Value = %d\n", this->m_iValue ); } }; #define CTest_class 0x00418148 #define func_ShowValue 0x004116A0 #define func_SetNewValue 0x00411650 CTest *test = 0; int main( ) { typedef void (__thiscall *fpShowValue)( void ); fpShowValue fpShow = (fpShowValue)func_ShowValue; typedef void (__thiscall *fpSetNewValue)( int ); fpSetNewValue fpNew = (fpSetNewValue)func_SetNewValue; test = new CTest( 0 ); test->ShowValue( ); printf( "Normal call ...\n" ); test->SetValue( 1 ); test->ShowValue( ); printf( "Not normal call ...\n" ); _asm { push 2 mov ecx, dword ptr ds:[CTest_class] call fpNew } _asm mov ecx, dword ptr ds:[CTest_class] fpShow( ); delete test; getchar( ); return 0; }
Wenn irgendwo Fehler sein sollten oder etwas nicht richtig geloest ist, bitte sagts mir.
Gruß Tobi
-
ein tipp habich noch für dich. die direkte addresse zu verwenden ist arge
gefährlich. als erstes wäre es besser das ganze mit dem offset zur programminstanz
im speicher zu machen.(unter windows)
mit z.b. GetModuleHandle(0) bekommst du ein HMODULE zu deinem programm. der wert
des handles ist die startaddresse deiner .exe im speicher. meist ist das
unter msvc 0x00400000, was deine addressen ja gut belegen. dann musst du nurnoch
den offset zur laufzeit draufaddieren. am besten wäre es noch, wenn du den ESP
wert in der funktion/an der stelle abfragst wo du die funktion aufrufst.
die differenz sollte sich nicht unterscheiden, wenn du keine weiteren funktionen
aufrufst. also ein paarmal testen und dann einbauen.
-
Hm, irgendwie will mir nach wie vor nicht ganz in den Kopf, dass es keine praktischere Art gibt, das zu bewerkstelligen. Naja, egal: 1. ist das hier nicht Thema und 2. kenne ich mich eh nicht mit c++ aus (d'oh!).
-
@ Helferlein: mit Offset meinst du dann sicher:
#define CTest_class 0x00418148 (Offset_Class = 18148h)Und nach deinem Schema sollte ich das ganze so aendern:
HMODULE hInst = GetModuleHandle( 0 );
#define CTest_class ((DWORD)hInst + Offset_Class)
So etwa?
-
jo genau so
kannst auch mit dem ESP versuchen
void __declspec(naked) func() { __asm { push ebp mov ebp, esp // funktionsprolog mov ecx, [ebp+8] // addresse von "i" auf main() pop ebp // funktionsepilog ret } } int main() { int i; func(); }
du musst halt aufpassen wieviele lokalen variablen angelegt werden.
durch __declspec(naked) kannst du verhindern, dass der kompilier selber
code für den pro und epilog erzeugt. klappt aber nur unter msvc.meist sind da auchnoch andere aufrufe dazwischen, einfach mal testen
-
Du hast da glaub nen kleinen Fehler drin
[cpp]
mov ecx, [ebp**-**8] // addresse von "i" auf main()
[/cpp]So ist es doch richtig oder?
Ich danke euch erst mal.Gruß Tobi
-
T0bi schrieb:
#define CTest_class 0x00418148 (Offset_Class = 18148h) // Und nach deinem Schema sollte ich das ganze so aendern: HMODULE hInst = GetModuleHandle( 0 ); #define CTest_class ((DWORD)hInst + Offset_Class)
Du kannst die Adresse einer Klasse nicht bestimmen. Die gibt es nicht.
Du kannst nur
-> die Adressen der Methoden (Funktionen) einer Klasse bestimmen,
und
-> die Adresse der Eigenschaften (Variablen, bzw. Instanz) einer Klasse bestimmen.
-> Das wäre aber das, was z.B. "new (Klasse)" zurückgibt.
-
Lol? Offensichtlich weiß der Threadersteller nicht wie man das Problem richtig löst und statt ihn in ein geeignetes Unterforum zu verschieben werden hier ernsthaft falsche "Lösungen" gepostet??
Du übergibst der DLL ganz einfach einen Zeiger auf das gewünschte Objekt bzw. der EXE von der DLL aus, je nachdem in welche Richtung du willst.
Und das machst du ganz klassisch über extern "C" deklarierte Funktionen, z.B.:extern "C" __declspec(export) CTest* GetCTestObject() { return das_ctest_object; }
Und laden kannst du diese Funktion wahlweise über LoadLibrary und GetProcAdress, oder durch Linken und unter Verwendung von __declspec(import).