Как получить динамически сгенерированный X86_64 для возврата значения относительно RIP / RBP - PullRequest
3 голосов
/ 06 мая 2011

Я пытаюсь прочитать значения в памяти относительно %rip на X86_64. В моем первом примере я просто хочу прочитать

Если я напишу следующий код на C, я могу вызвать его и получить правильный результат (\x....C3C9):

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

Сгенерированный код выглядит следующим образом:

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 

Однако, если я теперь помещу этот код непосредственно в память и выполню его, я получу ошибку, в то время как я ожидаю прочитать \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;
}

Что я делаю не так?

редактировать Ответ в том, что я не должен был использовать malloc, но mmap для выделения области памяти, выровненной по страницам:

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

И, конечно, я должен был проверить возвращаемое значение вызова на mprotect. Он вернул -1, отметив, что это не удалось.

Ответы [ 2 ]

1 голос
/ 06 мая 2011

Скорее всего, вы получите SIGSEGV во время вызова mprotect ().Если выполнение кода в памяти, возвращаемой функцией malloc (), не разрешено операционной системой (скорее всего, если вы не используете какое-то древнее ядро), mprotect () просто вызывает ошибки.Это не ошибка, это особенность.

0 голосов
/ 06 мая 2011

инструкция ret в основном является pop value from the stack; goto value.

Когда вы goto <your_code>, ret в конечном счете выполняются, проблема в том, что у вас есть мусор в стеке (возможно, инструкция retпытается goto 9, потому что код размера - это переменная на вершине стека, кто знает ...).

В принципе, это не работает, потому что вы используете свой фрагмент asm неправильно.

Могу ли я спросить, что вы пытаетесь сделать?Я мог бы помочь:)


Тестовая программа, чтобы получить ваш рип:

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