2010-12-28 3 views
3

Ich würde gerne wissen, wie in C in den Inhalt einer Funktion in MEMROY kopieren und ausführen kann?Eine Funktion in den Speicher kopieren und ausführen

Ich versuche, so etwas zu tun:

typedef void(*FUN)(int *); 
char * myNewFunc; 

char *allocExecutablePages (int pages) 
{ 
    template = (char *) valloc (getpagesize() * pages); 
    if (mprotect (template, getpagesize(), 
      PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { 
     perror ("mprotect"); 
    } 
} 

void f1 (int *v) { 
    *v = 10; 
} 

// allocate enough spcae but how much ?? 
myNewFunc = allocExecutablePages(...) 

/* Copy f1 somewere else 
* (how? assume that i know the size of f1 having done a (nm -S foo.o)) 
*/ 

((FUN)template)(&val); 
printf("%i",val); 

Vielen Dank für Ihre Antworten

+2

Sie haben diese Frage schon einmal hier gestellt, http://stackoverflow.com/questions/4541419/dynamic-obfuscation-by -self-modifying-code/4541911 # 4541911 - warum fragst du nochmal? –

+0

Durchsuchen Sie das Web nach "embedded copy C function RAM" für weitere Informationen. –

+0

Was ist das Besondere, das sowieso verschleiern muss? –

Antwort

5

Sie scheinen den Teil über den Schutz Fahnen heraus haben. Wenn Sie die Größe der Funktion kennen, können Sie jetzt einfach memcpy() ausführen und die Adresse von f1 als Quelladresse übergeben.

Ein großer Vorbehalt ist, dass Sie auf vielen Plattformen keine anderen Funktionen aufrufen können als die, die Sie kopieren (f1), weil relative Adressen in den Binärcode der Funktion festgeschrieben und verschoben werden Es an einem anderen Ort kann der Speicher diese relativen Adressen schlecht werden lassen.

+2

Konnte immer die Umlagerungen von der '.o' Akte durchführen. Viel Spaß beim Schreiben Ihres eigenen Linkers. :-) –

+2

Die Startadresse einer Funktion kann leicht mit dem Namen der Funktion ermittelt werden. Die * Länge * einer Funktion ist eine andere Sache. –

0

Ich habe dieses Problem viele Male in C versucht und kam zu dem Schluss, dass es nicht nur mit der C-Sprache erreicht werden kann. Mein Hauptdorn war die Länge der zu kopierenden Funktion.

Die Sprache Standard C bietet keine Methoden, um die Länge einer Funktion zu erhalten. Man kann jedoch Assembler und "Abschnitte" verwenden, um die Länge zu finden. Sobald die Länge gefunden ist, ist das Kopieren und Ausführen einfach.

Die einfachste Lösung ist das Erstellen oder Definieren eines Linkersegments, das die Funktion enthält. Schreiben Sie ein Assemblersprachmodul, um die Länge dieses Segments zu berechnen und öffentlich zu deklarieren. Verwenden Sie diese Konstante für die Größe der Funktion.

Es gibt andere Methoden zum Einrichten des Linkers, z. B. vordefinierte Bereiche oder feste Positionen und Kopieren dieser Positionen.

In eingebetteten Systemen Land, wird der meiste Code, der ausführbare Sachen in RAM kopiert, in Assembly geschrieben.

+0

Sie brauchen * Assembly * nicht, um die Länge einer Funktion zu bestimmen - Sie können diesen Teil mit einem Linker-Skript ausführen. – Ponkadoodle

0

Dies könnte eine Hack-Lösung hier sein. Könnten Sie eine Dummy-Variable oder -Funktion direkt nach der Funktion erstellen (zu kopieren), die Adresse dieser Dummy-Variablen/Funktion erhalten und dann die Funktionen address nehmen, um eine arithmetische Addition mit Adressen durchzuführen, um die Funktionsgröße zu erhalten? Dies könnte möglich sein, da der Speicher linear und geordnet (und nicht zufällig) zugewiesen wird. Dies würde auch das Kopieren von Funktionen innerhalb einer ANSI C-Portabilität beibehalten, anstatt sich in systemspezifischen Assemblercode zu vertiefen. Ich finde, dass C ziemlich flexibel ist, man muss nur nachdenken.

0

Hacky Lösung und einfachen Nachweis von Konzept, das funktioniert für mich (und kompiliert auf Mac OS X/GCC 4.2.1 ohne Warnung):

#include "stdio.h" 
#include "stdlib.h" 
#include "string.h" 
#include <sys/mman.h> 

int function1(int x){ 
    return x-5; 
} 

int function2(int x){ 
    return x+5; 
} 


int main(){ 
    int diff = (&function2 - &function1); 
    printf("pagesize: %d, diff: %d\n",getpagesize(),diff); 

    int (*fptr)(int); 

    void *memfun = malloc(4096); 

    if (mprotect(memfun, 4096, PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { 
     perror ("mprotect"); 
    } 

    memcpy(memfun, (const void*)&function2, diff); 

    fptr = &function1; 
    printf("native: %d\n",(*fptr)(6)); 
    fptr = memfun; 
    printf("memory: %d\n",(*fptr)(6)); 
    fptr = &function1; 
    printf("native: %d\n",(*fptr)(6)); 

    free(memfun); 
    return 0; 
} 
2

Diese Arbeit geschieht, weil function1 und function2 sind genau die gleichen Größe im Speicher. Wir brauchen die Länge von Funktion2 für unsere Memcopy, was getan werden sollte: int diff = (& Haupt - & Funktion2);

Sie werden bemerken, dass Sie die Funktion 2 nach Ihren Wünschen bearbeiten können und es funktioniert immer gut!

Btw ordentlich Trick. Unglaublich, der g ++ Compiler spuckt ungültige Konvertierung von void * nach int aus ...Aber in der Tat mit gcc kompiliert es perfekt;)

Modified Quellen:

//Hacky solution and simple proof of concept that works for me (and compiles without warning on Mac OS X/GCC 4.2.1): 
//fixed the diff address to also work when function2 is variable size  
#include "stdio.h" 
#include "stdlib.h" 
#include "string.h" 
#include <sys/mman.h> 

int function1(int x){ 
    return x-5; 
} 

int function2(int x){ 
    //printf("hello world"); 
    int k=32; 
    int l=40; 
    return x+5+k+l; 
} 


int main(){ 
    int diff = (&main - &function2); 
    printf("pagesize: %d, diff: %d\n",getpagesize(),diff); 

    int (*fptr)(int); 

    void *memfun = malloc(4096); 

    if (mprotect(memfun, 4096, PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { 
     perror ("mprotect"); 
    } 

    memcpy(memfun, (const void*)&function2, diff); 

    fptr = &function1; 
    printf("native: %d\n",(*fptr)(6)); 
    fptr = memfun; 
    printf("memory: %d\n",(*fptr)(6)); 
    fptr = &function1; 
    printf("native: %d\n",(*fptr)(6)); 

    free(memfun); 
    return 0; 
} 

Ausgang:

Walter-Schrepperss-MacBook-Pro: cppWork wschrep $ gcc memoryFun.c Walter-Schrepperss-MacBook -Pro: cppWork wschrep $ ./a.out Seitengröße: 4096, diff: 35 nativer: 1 Speicher: 83 nativer: 1

Eine andere nicht e ruft printf wird segfault, weil printf höchstwahrscheinlich nicht gefunden wird, weil die relative Adresse falsch läuft ...

Verwandte Themen