Länge einer Compilierten Funktion ermitteln



  • Gib es eine einfache Möglichkeit die Länge einer fertig compilierten Funktion zu ermitteln?

    Mit einem Pointer auf diese Funktion ist mir nicht geholfen. Ich muss den kompletten compilierten "Code" während der Laufzeit kopieren und an eine andere Stelle einfügen.



  • Nein, gibt es nicht (jedenfalls nichts portables). Wozu benötigst du diese Angabe überhaupt?



  • Ich muss den fertig compilierten Code der Funktion kopieren und dafür brauche ich zumindest die Länge. Die Startadresse hab ich ja über den Funktionspointer aber ich kenn das Ende nicht 😞



  • Sowas kann es überhaupt nie geben... der Compiler kann alles mögliche Optimieren und die Implementierung mag von Version zu Version unterschiedlich sein (auch ohne Optimierung).



  • Hier meine jetzige Lösung (etwas frickelig, aber es scheint ja nicht anders zu funktionieren) :

    Die Startadresse der Funktion ist bekannt über den Funktionspointer.
    Fehlt somit noch das Ende welches unbekannt ist. Da ich die Funktion selber kenne und diese keinen Rückgabeparameter hat, wird diese folglich am Ende mit einem Assembler 'RET' (Return, Maschinencode 0xC3) ausgeführt.
    Ich suche ab der Startposition der Funktion danach und habe somit das Ende und kann die Länge kalkulieren.

    FERTIG. Hoffe das Funktioniert. Bisher ist es nur Theorie.



  • Hi, habe das bisher immer so gemacht und hat immer funktioniert. (was nicht heißen soll, dass es immer funktionieren muss 😉 )

    #pragma check_stack(off)
    
    static DWORD WINAPI ThreadFunc( LPVOID ) 
    {
    ...
    }
    
    static void AfterThreadFunc (void) {}
    
    #pragma check_stack 
    
    const int cbCodeSize = ((LPBYTE) AfterThreadFunc - (LPBYTE) ThreadFunc);
    


  • MarcelL schrieb:

    Hoffe das Funktioniert.

    Nein, wird es nicht.



  • Jochen Kalmbach schrieb:

    MarcelL schrieb:

    Hoffe das Funktioniert.

    Nein, wird es nicht.

    Warum würde mich mal interessieren?

    Dafür sollte meine "Lösung" funktionieren 😉



  • MarcelL schrieb:

    Fehlt somit noch das Ende welches unbekannt ist. Da ich die Funktion selber kenne und diese keinen Rückgabeparameter hat, wird diese folglich am Ende mit einem Assembler 'RET' (Return, Maschinencode 0xC3) ausgeführt.

    Und wie kannst du dir sicher sein, das 0xc3 nicht noch in irgendeiner anderen Befehlssequenz vorkommt?

    Und auch der Vorschlag von yogle ist zweifelhaft, da es keine Garantie gibt, dass die Funktionen in der entsprechenden Reihenfolge im Code abgelegt werden.
    Imo ist sowas nur auf Assemblerebene zuverlässig machbar.



  • Sobald ein Sprungbefehl in der Funktion drin ist (z.B. durch "if" verursacht), kann der Compiler die beiden Code-Fragmente an vollkommen unterschiedlichen Stellen (nicht mal aufeinanderfolgend) anbringen! Ganz zu schweigen was der Compiler macht, wenn man die Optimierungen aktiviert.



  • musst dir halt einen kleinen disassembler schreiben oder eine fertige disassembler lib nehmen.
    moeglich is das damit durchaus blos einfach nach dem opcode suchen 0xC3 kann nicht zuverlaessig funktionieren da, wie schon gesagt wurde, der wert 0xc3 auch als parameter zu einem opcode vorkommen kann.
    In der theorie muss zwar eine funktion nicht mit einem 'ret' beendet werden is aber sicher zu 99% der fall



  • achja um einen disassembler wirst du wahrscheinlich auch mit der methode yogle nicht herumkommen da wenn du eine funktion wo anders hinkopierst relative adressen (zb von 'call's) nicht mehr stimmen! Die muesstest du finden und anpassen wenn die funktion lauffaehig bleiben soll...



  • groovemaster schrieb:

    MarcelL schrieb:

    Fehlt somit noch das Ende welches unbekannt ist. Da ich die Funktion selber kenne und diese keinen Rückgabeparameter hat, wird diese folglich am Ende mit einem Assembler 'RET' (Return, Maschinencode 0xC3) ausgeführt.

    Und wie kannst du dir sicher sein, das 0xc3 nicht noch in irgendeiner anderen Befehlssequenz vorkommt?

    Weil diese "spezielle" Funktion minimal gehalten ist und maximal 70 Byte Lang ist.

    Weil ich den compilierten Code in Assembler angeschaut habe und keine weiteren 0xC3`s vorkommen.

    Weil es soeben funktioniert hat.

    Das es keine 100% kompatible Lösung gibt ist mir klar. Ich muss halt jetzt bei jedem compilieren schauen wie der passende Assembler Code ausschaut.


  • Mod

    MarcelL schrieb:

    [quote="groovemasterWeil diese "spezielle" Funktion minimal gehalten ist und maximal 70 Byte Lang ist.

    Und wer garantiert Dir, dass eine unterschiedliche Ladeposition (Relokation) nicht zu einer Änderung in Deinem Code führt?



  • Naja, das sagte ich doch. Ich kenne den Assembler Code der hinter dieser "minimal" Funktion steckt.



  • MarcelL schrieb:

    Naja, das sagte ich doch. Ich kenne den Assembler Code der hinter dieser "minimal" Funktion steckt.

    Wenn Du denn Assembler-Code eh kennst, dann brauchst Du hier noch so unnötige und unzuverlässige Methoden anwenden. Dann mach sowas wie:

    unsigned char myFunction[] = {0x03, 0x22, 0x54, 0x02, 0xc3 };
    


  • MarcelL schrieb:

    Weil diese "spezielle" Funktion minimal gehalten ist und maximal 70 Byte Lang ist.

    Dann schreib sie doch komplett mit Inline Assembler, dann bekommst du auch problemlos die Länge raus.



  • Wozu willst du das überhaupt?



  • hustbaer schrieb:

    Wozu willst du das überhaupt?

    brauche das für für eine DLL Injektion ohne dabei über die Windows Hook Funktionen zu gehen.

    Ich öffne einen Prozess, allokiere mir ein wenig virtuellen Speicher. Injiziere dann meine Dll, eine Struktur mit eine paar Funktionspointer und die "Funktion" über die wir reden um einen Thread in der Dll zu starten :-).



  • das hört sich illegal an


Anmelden zum Antworten