11

I would like to know how in C in can copy the content of a function into memory and the execute it?

I'm trying to do something like this:

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);

Thanks for your answers

2
  • 2
    You already asked this question once here, stackoverflow.com/questions/4541419/… - why are you asking again? Commented Dec 28, 2010 at 13:15
  • Search the web for "embedded copy C function RAM" for more information. Commented Dec 28, 2010 at 18:07

5 Answers 5

8

You seem to have figured out the part about protection flags. If you know the size of the function, now you can just do memcpy() and pass the address of f1 as the source address.

One big caveat is that, on many platforms, you will not be able to call any other functions from the one you're copying (f1), because relative addresses are hardcoded into the binary code of the function, and moving it into a different location it the memory can make those relative addresses turn bad.

Sign up to request clarification or add additional context in comments.

2 Comments

Could always perform the relocations from the .o file.. Have fun writing your own linker though. :-)
The starting address of a function is easily obtained, by using the name of the function. The length of a function is a different matter.
4

This happens to work because function1 and function2 are exactly the same size in memory. We need the length of function2 for our memcopy so what should be done is: int diff = (&main - &function2);

You'll notice you can edit function 2 to your liking and it keeps working just fine!

Btw neat trick. Unfurtunate the g++ compiler does spit out invalid conversion from void* to int... But indeed with gcc it compiles perfectly ;)

Modified sources:

//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;
}   

Output:

Walter-Schrepperss-MacBook-Pro:cppWork wschrep$ gcc memoryFun.c 
Walter-Schrepperss-MacBook-Pro:cppWork wschrep$ ./a.out 
pagesize: 4096, diff: 35
native: 1
memory: 83
native: 1

Another to note is calling printf will segfault because printf is most likely not found due to relative address going wrong...

1 Comment

Nice answer! Minor problem: malloc(4096) is not guaranteed to return memory aligned to 4096-byte pages (although I think it usually will with most allocators), but mprotect() usually requires its first argument to be aligned to a page. To be sure, you may want to use aligned_alloc() (available since C11) and use getpagesize() instead of the constant 4096. en.cppreference.com/w/c/memory/aligned_alloc
1

Hacky solution and simple proof of concept that works for me (and compiles without warning on Mac OS X/GCC 4.2.1):

#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;
}

1 Comment

Nice answer! Minor problem: malloc(4096) is not guaranteed to return memory aligned to 4096-byte pages (although I think it usually will with most allocators), but mprotect() usually requires its first argument to be aligned to a page. To be sure, you may want to use aligned_alloc() (available since C11) and use getpagesize() instead of the constant 4096. en.cppreference.com/w/c/memory/aligned_alloc
0

I have tried this issue many times in C and came to the conclusion that it cannot be accomplished using only the C language. My main thorn was finding the length of the function to copy.

The Standard C language does not provide any methods to obtain the length of a function. However, one can use assembly language and "sections" to find the length. Once the length is found, copying and executing is easy.

The easiest solution is to create or define a linker segment that contains the function. Write an assembly language module to calculate and publicly declare the length of this segment. Use this constant for the size of the function.

There are other methods that involve setting up the linker, such as predefined areas or fixed locations and copying those locations.

In embedded systems land, most of the code that copies executable stuff into RAM is written in assembly.

1 Comment

You don't need assembly to figure out the length of a function - you can do that part with a linker script.
0

This might be a hack solution here. Could you make a dummy variable or function directly after the function (to be copied), obtain that dummy variable's/function's address and then take the functions address to do sum sort of arithmetic using addresses to obtain the function size? This might be possible since memory is allocated linearly and orderly (rather than randomly). This would also keep function copying within a ANSI C portable nature rather than delving into system specific assembly code. I find C to be rather flexible, one just needs to think things out.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.