call + ?
-
Hi,
ich bin leider in der Situation, dass ich zur Laufzeit kleine asm-Funktionen in C++ erstellen muss. Klappt soweit auch ganz gut (HeapAlloc + einfach die Funktion da reinschreiben), wobei ich ein Problem habe. Ich möchte aus dieser zur Laufzeit erstellten Funktion eine andere, statische Funktion aufrufen. Leider klappt dies nicht (Exception vom Debugger).static __stdcall int Function(int a,int b) { return 0; } void MacheFunktion1(unsigned char* pcFunction) { //Basiscodes erstellen, argumente pushen etc. pcFunction[10]=0xe8;//call *reinterpret_cast<void**>(&pcFunction[11])=Function; //... }
Was ist falsch?
Danke
-
muss natürlich static int __stdcall Function(int a,int b) heißen
-
Aus reiner Neugier, wofür ist das gut, eine Funktion zur Laufzeit des Programms zu erstellen?
Wäre es nicht besser, ein Paar Funktionen zu schreiben und mit einem Funktionen-Zeiger zwischen den Funktionen umschalten?
-
Ich habe irgendwo einen Array (unbestimmte Anzahl) von Funktionszeiger, und ich muss ein Programm erstellen, was mir diese Aufrufe aus diesen Funktionszeigern ausgibt. Leider brauche ich auch die genaue Position (in diesem Array) der Funktion, und daher reicht es nicht aus, einfach einen Funktionszegeiger auf eine eigene Funktion reinzuschreiben. Statdessen erstelle ich einfach eine Funktion zur Laufzeit, welche genau eine andere Statische Funktion mit den gleichen Argumente aufruft, wobei diese statische Funktion noch ein int Argument mit der Position annimmt.
Also so:
int __stdcall DieFunktion(int Pos, int, int, int...) { //... return 0; } void MacheFunktion1(unsigned char* pcFunction) { //Basiscode //Push Argument 4 //Push Argument 3 //Push Argument 2 //Push Position 1 //call DieFunktion; //... }
Es liegt definitiv an dem Zeiger nach dem Call. Wenn ich eine andere, vorkomplimierte Funktion, zur Laufzeit per memcpy in meinen unsigned char-Funktionsarray reintue, dann klappt es. Der einzige unterschied zwischen diser vom Compiler generierten und meiner Funktion ist der Zeiger auf die Funktion, welcher im Fall der vom Compilergenerierten Funktion definitiv nicht der richtige Zeiger auf meine "DieFunktion" ist (Relativ?!)
Hilfe!!!
-
Kannst du das was du machen willst nochmal besser ausdrücken? Dafür gibt es mit Sicherheit auch eine Lösung in C++
-
bluecode schrieb:
Kannst du das was du machen willst nochmal besser ausdrücken? Dafür gibt es mit Sicherheit auch eine Lösung in C++
Nein
Egal. Es geht sowieso einfach nur um den Zeiger, der nach einem __asm call befehl kommen muss. Wie sieht der aus???
-
Hier nochmal ein wenig Code, welcher mein Problem verdeutlichen soll...
#include <iostream> using namespace std; #pragma optimize("g", off) static int __stdcall EineTolleFunktion() { return 0; } /* Nach dem VS asm output sieht die Funktion so aus 55 push ebp 8b ec mov ebp, esp e8 00 00 00 00 call ?EineTolleFunktion@@YGHXZ 5d pop ebp c3 ret 0 */ static int __stdcall FunktionCallTest() { return EineTolleFunktion(); } int main() { FunktionCallTest(); // Zeiger auf die Funktion!!! void* p=EineTolleFunktion; cout << static_cast<int>(reinterpret_cast<unsigned char*>(&p)[0]) << " "; cout << static_cast<int>(reinterpret_cast<unsigned char*>(&p)[1]) << " "; cout << static_cast<int>(reinterpret_cast<unsigned char*>(&p)[2]) << " "; cout << static_cast<int>(reinterpret_cast<unsigned char*>(&p)[3]); cout << endl; // Zeiger auf die Funktion wie er nach dem call kommt!!! cout << static_cast<int>(reinterpret_cast<unsigned char*>(FunktionCallTest)[4]) << " "; cout << static_cast<int>(reinterpret_cast<unsigned char*>(FunktionCallTest)[5]) << " "; cout << static_cast<int>(reinterpret_cast<unsigned char*>(FunktionCallTest)[6]) << " "; cout << static_cast<int>(reinterpret_cast<unsigned char*>(FunktionCallTest)[7]); //Ich bin verwirrt! return 0; } #pragma optimize("g", on)
-
Hallo dicker
nach call kommt bei x86-Prozessoren eigentlich der Offset zwischen der Adresse der Funktion und der Adresse des Calls + 4
-
n00b_n00b schrieb:
Hi,
ich bin leider in der Situation, dass ich zur Laufzeit kleine asm-Funktionen in C++ erstellen muss. Klappt soweit auch ganz gut (HeapAlloc + einfach die Funktion da reinschreiben) ...
Dass kannste jemandem erzählen, der die Hosen mit der Kneifzange anzieht.Kann sein dass Du kleine
Funktionen ins Datensegment schreibst - zum Laufen bringste die da nie- und wenn Du versuchst
während der Laufzeit ins Codesegment zu schreiben gibts dieb rote Karte vom OS.Der Trick in ne
DLL zu schreiben und die dann zu Laden, ist ne andere Technik.
-
balduin schrieb:
n00b_n00b schrieb:
Hi,
ich bin leider in der Situation, dass ich zur Laufzeit kleine asm-Funktionen in C++ erstellen muss. Klappt soweit auch ganz gut (HeapAlloc + einfach die Funktion da reinschreiben) ...
Dass kannste jemandem erzählen, der die Hosen mit der Kneifzange anzieht.Kann sein dass Du kleine
Funktionen ins Datensegment schreibst - zum Laufen bringste die da nie- und wenn Du versuchst
während der Laufzeit ins Codesegment zu schreiben gibts dieb rote Karte vom OS.Der Trick in ne
DLL zu schreiben und die dann zu Laden, ist ne andere Technik.
Warum sollte es denn nicht funktionieren? Wo liegt denn der Unterschied zwischen den .data-Sektionen der PE-Datei (exe, dll, whatever) und einem einfach Buffer, welcher mit HeapAlloc erzeugt würde?!
Anyway, diese zur Laufzeit erstellte Funktion wird auf jeden Fall klappen, da viele weitverbreitete Bibliotheken (z.b. die Microsoft Detour Library) diese gleiche Technik ohne Probleme nutzen...
-
n00b_n00b schrieb:
Egal. Es geht sowieso einfach nur um den Zeiger, der nach einem __asm call befehl kommen muss. Wie sieht der aus???
Das ist bei einem normalen near call (opcode 0xE8) eine relative Adresse zum nächsten Befehl oder bei einem indirekten near call (opcode 0xFF) steht die relative Adresse in einem Register (welches steht in dem Mod/RM byte).
btw. du gibts mit dem code ja nur was aus dem codesegment aus. Aber was willst du jetzt dynamisch verändern?
btw. Codesegment sind normalerweise read-only & exeutable, datensegment (& heap/stack) sind read/write aber falls es geht nicht executable.