Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux: executing code that is loaded to memory manually

Tags:

c

linux

I'm expermenting with function pointers on Linux and trying to execute this C program:

#include <stdio.h>
#include <string.h>

int myfun() 
{
    return 42;
}

int main()
{
    char data[500];
    memcpy(data, myfun, sizeof(data));
    int (*fun_pointer)() = (void*)data;
    printf("%d\n", fun_pointer());

    return 0;
}

Unfortunately it segfaults on fun_pointer() call. I suspect that it is connected with some memory flags, but I don't found information about it.

Could you explain why this code segfaults? Don't see to the fixed data array size, it is ok and copying without calling the function is successfull.

UPD: Finally I've found that the memory segment should be marked as executable using mprotect system call called with PROT_EXEC flag. Moreover the memory segment should be returned by mmap function as stated in the POSIX specification. There is the same code that uses allocated by mmap memory with PROT_EXEC flag (and works):

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

int myfun() 
{
    return 42;
}

int main()
{
    size_t size = (char*)main - (char*)myfun;
    char *data = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE,
        MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
    memcpy(data, myfun, size);

    int (*fun_pointer)() = (void*)data;
    printf("%d\n", fun_pointer());

    munmap(data, size);
    return 0;
}

This example should be complied with -fPIC gcc option to ensure that the code in functions is position-independent.

like image 278
Alexander Rodin Avatar asked Dec 28 '15 08:12

Alexander Rodin


People also ask

How a program is loaded into memory and then executed?

For a program to execute as a process, it has to be loaded into memory via a program loader. The executable file that contains the program consists of several sections that identify different regions of the program and where they should be loaded into memory.

When it is executed the program is then loaded into?

Program is a passive entity as it resides in the secondary memory. Process is a active entity as it is created during execution and loaded into the main memory. 3.

How do I run an EXE file to the main memory?

Load an executable file into memory. This is done through the exec (now execve ) system call. During this call, 3 main memory areas, called regions are filled: The text region, which consists of a set of instructions your process is to follow : basically, your program.


2 Answers

Several problems there:

  • Your data array stays in data segment, not in code segment.
  • The address relocation is not handled.
  • The code size is not known, just guessed.
like image 141
dlask Avatar answered Oct 15 '22 16:10

dlask


In addition to Diask's answer you probably want to use some JIT compilation techniques (to generate executable code in memory), and you should be sure that the memory zone containing the code is executable (see mprotect(2) and the NX bit; often the call stack is not executable for security reasons). You could use GNU lightning (quickly emitting slow machine code), asmjit, libjit, LLVM, GCCJIT (able to slowly emit fast optimized machine code). You could also emit some C code in some temporary file /tmp/emittedcode.c, fork a compilation command gcc -Wall -O -fPIC -shared /tmp/emittedcode.c -o /tmp/emittedcode.so then dlopen(3) that shared object /tmp/emittedcode.so and use dlsym(3) to find function pointers by their name there.

See also this, this, this, this and that answers. Read about trampoline code, closures, and continuations & CPS.

Of course, copying code from one zone to another usually don't work (it has to be position independent code to make that work, or you need your own relocation machinery, a bit like a linker does).

like image 32
Basile Starynkevitch Avatar answered Oct 15 '22 17:10

Basile Starynkevitch