Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从内联程序集中修改RIP寄存器_C_Assembly_X86 64 - Fatal编程技术网

C 从内联程序集中修改RIP寄存器

C 从内联程序集中修改RIP寄存器,c,assembly,x86-64,C,Assembly,X86 64,我正在尝试修改rip寄存器(只是为了好玩)buffer应该是内存地址,所以我不知道为什么会出现错误:“movq”的操作数类型不匹配 #include <stdio.h> #include <stdlib.h> int main(){ char* buffer; buffer = (char*) malloc(8*sizeof(char)); asm volatile("movq %0, %%rip \n" : : "r"

我正在尝试修改
rip
寄存器(只是为了好玩)
buffer
应该是内存地址,所以我不知道为什么会出现
错误:“movq”的操作数类型不匹配

#include <stdio.h>
#include <stdlib.h> 

int main(){
        char* buffer;
        buffer = (char*) malloc(8*sizeof(char));
        asm volatile("movq %0, %%rip \n" : : "r" (buffer));
        free(buffer);
}
#包括
#包括
int main(){
字符*缓冲区;
缓冲区=(char*)malloc(8*sizeof(char));
asm volatile(“movq%0,%%rip\n”::“r”(缓冲区));
自由(缓冲);
}

在x86中,不能将
rip
直接用作
mov的源或目标。要更改
rip
,必须
jmp
调用
,或
ret

尝试将您的地址移动到
rax
,然后移动到
jmp-rax
。确保将
rax
标记为“Clobbred”

不过,做您正在尝试的事情更简单的方法是创建一个函数指针,将它指向您分配的内存,然后调用它

还要注意的是,您的
malloc
ed内存将不会被标记为可执行,因此您的测试将立即崩溃。要解决此问题,可以使用更改页面权限。但是,这会在整个页面中更改它们。更好的解决方案是用于映射匿名的可执行页面


首先,我们编写一个小汇编函数:

prog.s

[BITS 64]
global addints

;; unsigned long addints(unsigned long x, unsigned int y);
addints:
    mov     rax, rdi    ;; x
    add     rax, rsi    ;; y
    ret
然后组装,并查看操作码:

$ nasm -o binary prog.s
$ ndisasm -b64 prog
00000000  4889F8            mov rax,rdi
00000003  4801F0            add rax,rsi
00000006  C3                ret
现在将其编码到我们的示例程序中:

mmap.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>

#define PAGE_SIZE   0x1000  /* always 4 KiB (min.) on x86 */

static const uint8_t mycode[] = {
    0x48, 0x89, 0xF8,   /* mov rax, rdi */
    0x48, 0x01, 0xF0,   /* add rax, rsi */
    0xC3,               /* ret */
};

int main(void)
{
    void *m;

    /* Use mmap to allocate a page of executable memory */
    m = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
             MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

    if (m == MAP_FAILED) {
        fprintf(stderr, "mmap() failed: %m\n");
        exit(2);
    }

    /* Copy our code into the executable memory */
    memcpy(m, mycode, sizeof(mycode));

    /* For safety, remove the 'writable' flag */
    mprotect(m, PAGE_SIZE, PROT_READ | PROT_EXEC);

    /* Create a function pointer, and point it at the executable memory */
    unsigned long (*func)(unsigned long x, unsigned long y) = m;

    /* Call our code */
    unsigned long result = func(7, 3);

    printf("Result: %lu\n", result);

    return 0;
}

可能重复:。。你也可以看到这个:@Paulo:那些不是复制品。它们试图做完全不同的事情,却恰好给出相同的错误消息。jmp、call或push/ret。“创建一个函数指针,将它指向您分配的内存…”您的确切意思是什么?将指向数据的指针转换为指向函数的指针不是ISO C。@black我很好奇,那么,在ISO C中如何实现JITer。这正是Linux内核在JIT BPF代码时使用的构造。它也是由
ld
函数完成的(如
dlopen
)。ISO C没有定义这一点,尽管POSIX兼容的实现是必需的。@black我不知道你为什么问我当时的意思,如果你已经知道:-)