我正在测试我正在编写的汇编程序,它生成X86指令。我想做这样的事情来测试指令是否有效。
#include<stdio.h>
unsigned char code[2] = {0xc9, 0xc3};
int main() {
void (*foo)();
foo = &code;
foo();
return 0;
}
然而,由于DEP,OS X似乎正在阻止这种情况。有没有办法(a)禁用此程序的DEP或(b)以另一种格式输入字节,以便我可以跳转到它们。
答案 0 :(得分:6)
如果您只是需要测试,请尝试相反,它是魔法 ......
const unsigned char code[2] = {0xc9, 0xc3};
^^^^^
const
关键字使编译器将其放在const
部分(警告!这是一个实现细节!),它与text
部分位于同一段。整个段应该是可执行的。这样做可能更容易:
__attribute__((section("text"))
const unsigned char code[2] = {0xc9, 0xc3};
您可以随时在程序集文件中执行此操作,
.text
.globl code
code:
.byte 0xc9
.byte 0xc3
但是:如果要在运行时更改代码,则需要使用mprotect
。默认情况下,内存中没有写入和执行权限的映射。
以下是一个例子:
#include <stdlib.h>
#include <sys/mman.h>
#include <err.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
unsigned char *p = malloc(4);
int r;
// This is x86_64 code
p[0] = 0x8d;
p[1] = 0x47;
p[2] = 0x01;
p[3] = 0xc3;
// This is hackish, and in production you should do better.
// Casting 4095 to uintptr_t is actually necessary on 64-bit.
r = mprotect((void *) ((uintptr_t) p & ~(uintptr_t) 4095), 4096,
PROT_READ | PROT_WRITE | PROT_EXEC);
if (r)
err(1, "mprotect");
// f(x) = x + 1
int (*f)(int) = (int (*)(int)) p;
return f(1);
}
mprotect
规范声明如果内存最初未与mmap
映射,则其行为未定义,但您正在测试,而不是发货,所以只知道它在OS X上运行正常因为OS X malloc
在幕后使用mmap
(我认为是专门的)。
答案 1 :(得分:0)
不知道您在OSX上的DEP,但您可以做的另一件事是malloc()您编写代码的内存,然后跳转到这个malloc区域。至少在Linux上,这个内存不会受到exec保护(事实上,这就是JIT通常如何操作)。