我正在尝试读取内存中相对于X86_64上的%rip
的值。在我的第一个例子中,我只想阅读
如果我在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表示它已失败。
答案 0 :(得分:1)
你最有可能在mprotect()调用期间获得SIGSEGV。如果操作系统不允许执行malloc()返回的内存的代码执行(很可能是你没有使用某些古老内核),mprotect()只是段错误。这不是一个错误,它是一个功能。
答案 1 :(得分:0)
ret
指令基本上是pop value from the stack; goto value
。
当goto <your_code>
,ret
最终被执行时,问题是堆栈上有垃圾(可能ret
指令尝试goto 9
因为codesize是变量在堆栈的顶部,谁知道......)。
基本上,它不起作用,因为您错误地使用了您的asm代码段。
请问您要做什么?我可以帮忙:))
获取你的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;
}