Reputation: 852
How do I call from an memcpy'ed assembly function a C library functions?
I'm making an example test code how one can allocate and change memory protection on Linux, AMD64 to run arbitrarily generated code from C. What I done is that I compile an small GAS assembly function along side my main program (written in C) and then copy the assembly binary blob onto piece executable memory in run-time and jump into it. This part works OK.
But I if call C library puts() from the copied assembly blob it results in segfault due to bad function address?! How do I fix it?
The assembly code blob:
.text
.global _print_hello_size
.global _print_hello
.type _print_hello,@function
_print_hello:
push %rbp
mov %rsp, %rbp
# puts("Hello World\n")
mov $_message, %rdi
call puts # <-- SEGFAULT
pop %rbp
ret
procend: # mark end address of the _print_hello code
.section .rodata
_message:
.asciz "Hello, world\n"
_print_hello_size:
.long procend - _print_hello
Then in C main() I do (pseudo code):
// Import assembler function and its size
extern "C" void _print_hello(void);
extern "C" const long _print_hello_size;
int main() {
// Use special function that allocates Read-Write-Executable memory
void * memexec = MallocExecutableMemory(1024);
// Copy the binary asm blob, memexec is aligned to at least 16-bytes
memcpy(memexec, (void*)_print_hello, _print_hello_size);
void (*jmpfunc)(void) = (void (*)(void))memexec;
jmpfunc(); // Works, jumps into copied assembly func
return 0;
}
Later if this is even possible would not even compile the asm blob, but just encode the example program in in unsigned char execblob[] = { 0xCC,0xCC,0xC3,..} and copy that into the executable region. This bit code exploration how to start generating asm from C.
Upvotes: 2
Views: 449
Reputation: 6403
Maybe you could do
push %rbp
mov %rsp, %rbp
# puts("Hello World\n")
mov $_message, %rdi
mov $puts, %eax
call %eax
pop %rbp
ret
and thus forcing the call
to become an absolute one. The question is whether the assembler won't optimize this out for its own purposes.
Upvotes: 2
Reputation: 852
It it impossible call any C standard library function (or any linked) from memcpy-ed block of code, as if linker decides the puts function entry point is any where else than it originally was the copied code block is simply malformed. The first answer stops working the second binary blob is out-of-sync with the rest of the program.
Only way around is to modify the binary blob at run-time and assign the current real function addresses (from the C program) to the blob like C linker does.
Upvotes: 0