Linux AMD64从复制的程序集调用C库函数 [英] Linux AMD64 call C library functions from copied assembly

查看:74
本文介绍了Linux AMD64从复制的程序集调用C库函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How do I call from an memcpy'ed assembly function a C library functions?

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

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.

但是如果我从复制的程序集blob调用C库puts(),则会由于错误的函数地址而导致segfault?我该如何解决?

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?

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

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

即使有可能,甚至以后甚至都不会编译asm blob,而只是将示例程序编码为 unsigned char execblob [] = {0xCC,0xCC,0xC3,..} 并复制到可执行区域.此位代码探索如何从C开始生成asm.

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.

推荐答案

也许你可以

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

,因此强制call成为绝对值.问题是汇编程序是否不会出于自身目的对其进行优化.

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.

这篇关于Linux AMD64从复制的程序集调用C库函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆