简体   繁体   English

如何动态生成X86_64以返回相对于RIP / RBP的值

[英]How to get dynamically generated X86_64 to return a value relative to the RIP / RBP

I'm trying to read values in memory relative to the %rip on X86_64. 我试图读取内存中相对于X86_64上的%rip值。 In my first example I just want to read 在我的第一个例子中,我只想阅读

If I write the following code in C, I can call it and get the correct result ( \\x....C3C9 ): 如果我在C中编写以下代码,我可以调用它并获得正确的结果( \\x....C3C9 ):

void * test() {
    __asm("mov 0(%rip), %rax");
}

The generated code looks as follows: 生成的代码如下所示:

0000000000400624 <test>:
  400624:   55                      push   %rbp
  400625:   48 89 e5                mov    %rsp,%rbp
  400628:   48 8b 05 00 00 00 00    mov    0x0(%rip),%rax        # 40062f <test+0xb>
  40062f:   c9                      leaveq 
  400630:   c3                      retq 

If I now however put this code directly in memory and execute it I get a segfault, while I would expect to read \\x0000C3C9 : 但是,如果我现在将此代码直接放在内存中并执行它,我会得到一个段错误,而我希望读取\\x0000C3C9

int main()
{
    int codesize = 9;
    unsigned char * code = (unsigned char*)malloc(1024);
    memcpy(code, "\x48\x8B\x5\x0\x0\x0\x0\xC9\xC3\x00\x00", codesize + 2);
    mprotect(code, codesize, PROT_EXEC | PROT_READ);
    goto *code;
}

What am I doing wrong? 我究竟做错了什么?

edit The answer is that I shouldn't have used malloc but mmap to allocate a page-aligned memory region: 编辑答案是我不应该使用malloc而是使用mmap来分配页面对齐的内存区域:

(unsigned char*)mmap(NULL, 1024, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_SHARED, -1, 0);

And of course I should have checked the return value of the call to mprotect . 当然我应该检查调用mprotect的返回值。 It returned -1 flagging that it had failed. 它返回-1标记它失败了。

You most likely get the SIGSEGV during the mprotect() call. 您最有可能在mprotect()调用期间获得SIGSEGV。 If the code execution of the memory returned by malloc() is disallowed by the OS (it most likely is if you aren't using some ancient kernel), mprotect() just segfaults. 如果操作系统不允许执行malloc()返回的内存的代码执行(很可能是你没有使用某些古老内核),mprotect()只是段错误。 That's not a bug, it's a feature. 这不是一个错误,它是一个功能。

the ret instruction is basically a pop value from the stack; goto value ret指令基本上是pop value from the stack; goto valuepop value from the stack; goto value pop value from the stack; goto value . pop value from the stack; goto value

When you goto <your_code> , ret eventually gets executed the problem is that you have garbage on the stack (maybe the ret instruction tries to goto 9 because codesize is the variable on the top of the stack, who knows...). 当你goto <your_code>ret最终会被执行,问题是你的堆栈上有垃圾(也许ret指令试图goto 9因为codesize是堆栈顶部的变量,谁知道......)。

Basically, it doesn't work because you are using your asm snippet incorrectly. 基本上,它不起作用,因为你错误地使用你的asm片段。

May I ask what you are trying to do ? 请问您要做什么? I could help :) 我可以帮忙:)


A test program to get your rip: 获取你的rip的测试程序:

static inline unsigned long get_rip(void)
{
    unsigned long val;
    asm volatile(
        "call 1f\n"
        "1: popq %0\n"
        : "=r"(val));
    return val;
}

int main()
{
    printf("rip = %p\n", (void *)get_rip());
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM