0

我正在尝试运行一些保存在 OS X 缓冲区中的汇编代码,但我一直遇到分段错误。代码如下所示:

int main()
{
    unsigned char buff[] = "\x66\x6a\7f\x66\xb8\x01\x00\x00\x00\x66\x83\xec\x04\xcd\x80";
    ( void (*)()buff )(); /* same as calling return 127 */
    return 0;             /* program should never reach here */
}

buff 中的代码是由 nasm 生成的,它可以工作,它会导致程序返回 127。但是,当像这样通过 ac 程序运行时,我遇到了分段错误。在 OS X 中是否有不同的方法可以做到这一点?

4

2 回答 2

3

首先,这不会编译,因为您缺少进行强制转换所需的括号void (*)()。该行应该是((void (*)())buff)();.

其次,如果不进行优化编译,buff很可能是在栈上构建的,并且执行会失败,因为 Mac OS X 将栈标记为不可执行。

第三,如果你用优化编译,buff很可能是在一些数据段中准备的,你也许可以执行它。但是您的说明不适用于 Mac OS X 平台,并且您会遇到正常的访问异常。您可以通过调试器中的说明逐步找出问题所在。

C 标准没有定义将对象指针转换为函数指针并调用函数的行为。你不应该依赖它来工作。

汇编代码中的错误包括:

  • 它将一个移到%ax寄存器,这是寄存器的低两个字节%rax。这使得高六字节不受控制。然后它尝试%rax用作地址。这失败了,因为%rax寄存器中的值没有指向可访问的内存。
  • 它尝试执行指令int $0x80。这是一些 Microsoft Windows、DOS 或 Linux 服务调用。在 Mac OS X 上,这是一条非法指令。
于 2013-08-22T19:42:21.517 回答
2

默认情况下,堆栈是不可执行的——您需要将页面标记为可执行mprotect(2)以使其可执行。强烈不建议使堆栈可执行,因此如果要运行在运行时生成的代码,则应改为在堆上分配内存。

例如:

#include <sys/mman.h>
#include <unistd.h>

...

// Error checking omitted for expository purposes

// Allocate 1 page of read-write memory
size_t page_size = getpagesize();
void *mem = mmap(NULL, page_size,
                 PROT_READ | PROT_WRITE,
                 MAP_ANON | MAP_PRIVATE,
                 -1, 0);
// Copy the shell code into the memory
char shellcode[] = "...";
memcpy(mem, shellcode, sizeof(shellcode));

// Change memory to executable and non-writable
mprotect(mem, page_size, PROT_READ | PROT_EXEC);

// Run the code
((void (*)())mem)();

// Free the memory
munmap(mem, page_size);
于 2013-08-22T19:50:40.717 回答