"Größe einer Funktion"



  • Hallo,

    ich möchte gerne die Anzahl der Bytes, die eine Funktion (in der exe) verbraucht ermitteln.
    Folgendes Beispiel:

    int somefunction(int x) {
     int i;
     i = x*2;
     return i;
    }
    
    int main(int argc, char *argv[]) {
     somefunction(5);
     return 0;
    }
    

    Ich möchte die Größe der Funktion "somefunction" herausfinden.
    Hoffe mal, ich konnte mich einigermassen verständlich ausdrücken 🙂

    Danke



  • Interessant was man alles brauchen kann.
    Ich wüsste jetzt net wie sowas möglich ist, aber bin mal gespannt was kommt.



  • lol. das geht nicht.



  • Wenn man einer Kuh das Fliegen beibringen will, würde ich auch sagen "Das geht nicht". Ansonsten geht alles.

    Man nehme die Adresse der Funktion und durchsuche den Speicher bis C3 (== ret) und hat die Größe der Funktion.

    Wofür man das allerdings braucht, kann ich mir auch nicht vorstellen.



  • Danke für die Antwort Manfred S.

    Ich hab mir sowas ähnliches auch gedacht (entweder Speicher durchsuchen oder PE file).

    Könntest du mich vielleicht auf die dazu nötigen Funktionen hinweisen? Wäre echt hilfreich.

    OpenProcess() is ein guter Anfang denke ich mal 🙂
    ReadProcessMemory() schaut auch ganz nett aus...
    Doch welches Zeichen ist nun dieses ret?



  • 😮 Scheinbar meinst Du es ernst!

    Willst Du auf Routinen eines anderen Programmes zugreifen oder auf das eigene?

    Bei externen Programmen (andere EXE) ist das tatsächlich ohne OBJ- und MAP-Datei vom Linker völlig unmöglich, da die Funktionsnamen nicht in der EXE enthalten sind. Daher sind ProcessHandles völlig unbrauchbar.

    Ansonsten brauchts da keine Funktionen. char-Pointer holen, nachschauen auf welchen Wert er zeigt, Pointer weiterverschieben bis 0xC3 (=195). Differenz = Größe.



  • Und wer sagt, dass das erste ret auch das letzte der Funktion ist?

    EDIT: Außerdem kann 0xc3 auch vorkommen, ohne dass es ret bedeutet.



  • Manfred Schmidtke schrieb:

    Ansonsten brauchts da keine Funktionen. char-Pointer holen, nachschauen auf welchen Wert er zeigt, Pointer weiterverschieben bis 0xC3 (=195). Differenz = Größe.

    Ja ich meine es ernst 🙂
    Es geht um meinen eigenen Prozess aber könntest du diesen Satz von dir etwas weiter erklären?
    Ich dachte an folgendes:

    char buffer[4096];
    DWORD bread;
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrrentProcessId());
    ReadProcessMemory(hProcess, somefunction, buffer, 4096, &bread);
    

    Dann sollte ich ja den Speicherbereich im buffer haben (zur not weiter suchen)
    aber wie finde ich dieses "C3" im buffer?

    Danke



  • Wozu brauchst du das eigentlich? Reicht es dir nicht, einfach im Debugger nachzuschauen, wie groß die Funktion ist?



  • Und wie willst du den Anfang der Funktion finden? Die haben ja keinen Namen mehr.



  • Jetzt gehts es aber hier los 😉

    Für Ringding: Die Vorgehensweise ist sicherlich nicht plattform- oder compilerübergreifend. Im Code-Segment steht jedoch nur Code. Irgendwelche Daten sind auf Stack und Heap etc. verteilt. Ein vorzeitiges Return führt im ausführbaren Code nur zu einem Sprungbefehl auf das ret, da in aller Regel noch Stack aufzuräumen ist.

    Aber ist das wichtig 😕

    Für icy: Was soll ProcessMemory mit dem Parameter somefunction? C3 ist hexadezimal und steht für dezimal 195. Das kriegt Du, indem Du den Speicherbereich Byte für Byte durchgehst, bis ein Byte den Wert 195 enthält.



  • DWORD GetFunctionSize(void *address) {
    	HANDLE hProcess;
    	char buffer[4096];
    	DWORD bytesread;
    	DWORD i;
    
    	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
    
    	if (hProcess == NULL)
    		return -1;
    
    	if (ReadProcessMemory(hProcess, address, buffer, 4096, &bytesread) == 0)
    		return -1;
    
    	for (i=0;i<bytesread;i++) {
    		if (buffer[i] == 0xC3) // 195/ret
    			return i;
    	}
    
    	return -1;
    }
    

    Das sollte nur mal ne Testfunktion sein aber scheint nicht hinzuhauen



  • static void HalloBallo() {
    
    }
    
    static void NurZuBesuch() {
    
    }
    
    DWORD dwFuncSize = (DWORD)NurZuBesuch - (DWORD)HalloBallo;
    

    in seltenen fällen funktioniert das nicht, dann musst du mal bei den projektoptionen in den optimierungseinstellungen rumprobieren, aber im normalfall gibt's damit keine probleme



  • C/C++ Code:
    static void HalloBallo() {

    }

    static void NurZuBesuch() {

    }

    DWORD dwFuncSize = (DWORD)NurZuBesuch - (DWORD)HalloBallo;

    in seltenen fällen funktioniert das nicht, dann musst du mal bei den projektoptionen in den optimierungseinstellungen rumprobieren, aber im normalfall gibt's damit keine probleme

    Berechnung der Grösse der Funktion HalloBallo() nehme ich an ??
    Das ist jetz aber nicht dein Ernst oder ? 😃 😃 😃 😃



  • Manfred Schmidtke schrieb:

    Ein vorzeitiges Return führt im ausführbaren Code nur zu einem Sprungbefehl auf das ret.

    Unsinn. Vielleicht ist das bei manchen Compilern so, wenn man ohne Optimierung compiliert, aber normal ist das nicht.

    Im Code-Segment steht jedoch nur Code. Irgendwelche Daten sind auf Stack und Heap etc. verteilt.

    Das ist mir auch klar. Aber was ist dann z.B. damit:

    B0C3   mov al, c3
    

    EDIT:

    Redhead schrieb:

    Das ist jetz aber nicht dein Ernst oder ?

    Immerhin funktioniert das um einiges robuster als die andere Methode.



  • Hi Ringding,

    Redhead schrieb:
    Das ist jetz aber nicht dein Ernst oder ?

    Immerhin funktioniert das um einiges robuster als die andere Methode.

    Und du meinst wirklich das du damit einen sinnvollen und verlässlichen Wert rauskriegst. 🙂



  • Was hab ich hier bloß angerichtet!?!? 🤡

    Hätt' ich doch bloß die Finger von der Tastatur gelassen. Es ging doch nur darum, das "sowas nicht geht". Jetzt läuft dieses Thema bald auf der dritten Seite und wird, fürchte ich, dadurch noch viel mehr "Interessenten" anziehen. 😮

    Bezüglich C3 hab ich mich ein bisschen sehr undeutlich ausgedrückt. Es reicht natürlich nicht die Suche nach C3, sondern der Assembler-Code müsste entsprechend analysiert werden, also z. B. bei B0 entsprechend das nächste Byte überspringen usw.

    Wird ne ziemlich lange Liste, fürchte ich.

    Ob die Compiler-Optimierungen ggf. zusätzliche ret's einsetzen, weiß ich nicht. Vermutlich hast Du recht (ich werd's nicht überprüfen). Generell muss aber doch jede Funktion zunächst den Stack aufräumen und sich die Rücksprungadresse holen. Wahrscheinlich erzeugt eine Geschwindigkeitsoptimierung tatsächlich diesen Code mehrfach.



  • Redhead schrieb:

    Berechnung der Grösse der Funktion HalloBallo() nehme ich an ??
    Das ist jetz aber nicht dein Ernst oder ? 😃 😃 😃 😃

    Ich hab doch bereits eingeräumt, dass diese Variante nicht vollkommen deterministisch ist, aber wenn er die Größe der Funktion unbedingt haben will, dann kann er es ja so machen. In einigen Fällen ist es bei mir vorgekommen, dass die zweite Funktion vor der ersten angeordnet wurde und somit ein hoher negativer Wert rausgekommen ist. Aber wenn die kompilierte Version erstmal funktionierte, dann ging es auch auf jedem NT-System, auf dem ich diese Methode getestet habe.



  • Was ist denn der Sinn von der ganzen Sache? Nur mal so aus Langeweile was Neues ausprobieren oder steckt da noch mehr hinter?



  • Er will wohl seinen Funktionscode irgendwo injecten (Buffer-Overflows, RemoteThreads).Ansonsten wüsste ich auch keine wirkliche Verwendung dafür 😉


Anmelden zum Antworten