c - Linux AMD64 从复制的程序集中调用 C 库函数

标签 c linux assembly x86-64

如何从经过 memcpy 处理的汇编函数调用 C 库函数?

我正在制作一个示例测试代码,说明如何在 Linux、AMD64 上分配和更改内存保护以运行从 C 任意生成的代码。 我所做的是,在主程序(用 C 编写)旁边编译一个小型 GAS 汇编函数,然后在运行时将汇编二进制 blob 复制到 block 可执行内存中并跳转到其中。 这部分工作正常。

但是如果我从复制的程序集 blob 中调用 C 库 put() ,则会因错误的函数地址而导致段错误?!我该如何修复它?

汇编代码块:

       .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 main() 中我执行(伪代码):

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

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

关于c - Linux AMD64 从复制的程序集中调用 C 库函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30549375/

相关文章:

c++ - 为什么此代码片段会在 C 和 C++ 中生成截然不同的汇编代码?

[Array of Struct in [Array of Struct in [Array of Struct ]]] 中的结构体动态数组

检查输入的内容然后使用 scanf (C)

c - 为什么 readline 库中的 readline() 不接受 UNICODE? ANSI C语言

linux - 如何防止从静态链接库中导出符号?

用于在不同时间运行的作业的 Linux Crontab 表达式

c - 提取coap查询

c - gtk_main 更新 GUI

assembly - "rep; nop;"在 x86 汇编中意味着什么?和 "pause"指令一样吗?

assembly - 获取操作码的简单方法