Linux AMD64从复制程序集调用C库函数

如何从memcpy的汇编函数调用C库的函数?

我正在做一个示例testing代码,如何在Linux上分配和更改内存保护,AMD64从C运行任意生成的代码。我所做的是我编译一个小的GAS组装函数,沿着我的主程序(用C编写)然后在运行时将程序集二进制blob复制到程序块可执行的内存中并跳转到它。 这部分工作正常。

但是,如果调用C库放置()从复制大会blob它导致段错误由于function不良地址?! 我如何解决它?

汇编代码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 

然后在C主()我做(伪代码):

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

后来,如果这甚至可能甚至不会编译asm blob,但只是将示例程序编码为unsigned char execblob [] = {0xCC,0xCC,0xC3,..}并将其复制到可执行区域中。 这位代码探索如何从C开始生成asm

也许你可以做

 push %rbp mov %rsp, %rbp # puts("Hello World\n") mov $_message, %rdi mov $puts, %eax call %eax pop %rbp ret 

从而迫使call成为绝对的。 问题是汇编程序是否不会为了自己的目的而优化它。

它不可能调用memcpy-ed代码块中的任何C标准库函数(或任何链接的),就好像链接器决定puts函数的入口点是原来那里的任何地方,复制的代码块只是格式错误。 第一个答案停止工作,第二个二进制blob与程序的其余部分不同步。

唯一的解决办法是在运行时修改二进制blob,并将当前的实际函数地址(从C程序)分配给像C链接器那样的blob。