我正在尝试修改rip寄存器(只是为了好玩).buffer应该是一个内存地址,所以我不知道为什么会得到Error: operand type mismatch for '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);
}
Run Code Online (Sandbox Code Playgroud)
在x86中,您不能rip直接用作a的源或目标mov.要改变rip你必须jmp或call,或ret.
尝试移动您的地址rax然后jmp rax.确保标记rax为"破坏".
然而,更简单的方法就是简单地创建一个函数指针,将其指向您分配的内存并调用它.
另请注意,您的malloced内存不会被标记为可执行文件,因此您的测试将立即崩溃.要解决此问题,您可以使用mprotect(2)更改页面权限.但是,这会为整个页面更改它们.更好的解决方案是用于mmap(2)映射匿名的可执行页面.
首先,我们编写一个小的汇编函数:
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
Run Code Online (Sandbox Code Playgroud)
然后组装它,看看操作码:
$ nasm -o binary prog.s
$ ndisasm -b64 prog
00000000 4889F8 mov rax,rdi
00000003 4801F0 add rax,rsi
00000006 C3 ret
Run Code Online (Sandbox Code Playgroud)
现在将代码编入我们的示例程序:
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;
}
Run Code Online (Sandbox Code Playgroud)
给它一个旋转:
$ gcc -Wall -Werror -o mmap mmap.c
$ ./mmap
Result: 10
Run Code Online (Sandbox Code Playgroud)