从C - Bus错误10测试Shellcode

时间:2013-07-23 23:35:19

标签: c macos assembly shellcode

下面,我编写了打印'Hello,World!'的x64程序集。来自Mac OS X 10.8上的系统调用。它独立执行时汇编并运行完美。

; Assemble and link with:
; nasm -f macho64 -o HelloWorld.o HelloWorld.s
; ld -arch x86_64 -o HelloWorld HelloWorld.o

global start

section .text

start:

    push rbp
    mov rbp, rsp

    jmp short String

    xor rdi, rdi
    mov di, 0x01

StringRet:
    pop rsi

    xor rdx, rdx
    mov dl, 0xE

    mov r8b, 0x02
    shl r8, 24
    or r8, 0x04
    mov rax, r8

    syscall            ; System call for write(4)

    xor edi, edi

    mov r8b, 0x02
    shl r8, 24
    or r8, 0x01
    mov rax, r8

    syscall            ; System call for exit(1)

    mov rsp, rbp
    pop rbp

String:

    call StringRet
    db 'Hello, World!'

我遇到的问题是当我尝试将此代码作为来自c程序的shell代码运行时。我使用otool获取以下机器操作码。

otool -t HelloWorld.o

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c"
              "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2"
              "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89"
              "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65"
              "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21";

以下是我用来执行此操作的程序。但我一直收到一个总线错误:10。

; Compile:
; gcc -o HelloWorldTest HelloWorldTest.c

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c"
              "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2"
              "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89"
              "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65"
              "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21";

int main()
{
    int (*ret)();

    ret = (int(*)())code;

    (int)(*ret)();

    return 0;
}

当我逐步使用gdb时,我会在执行传递给shellcode时获得KERN_PROTECTION_FAILURE。

更新了问题:

以上由Carl Norum解决,这是由于记忆保护。我有一个不同的问题,但与上面类似。我没有将shell代码放在同一个文件中,而是想从.txt文件中读取shell代码并执行它。下面我尝试将一段内存标记为PROT_EXEC,并将.txt文件的内容读入其中并执行。但是它不起作用,我得到了同样的错误,KERN_PROTECTION_FAILURE,我尝试使用mprotect和mmap将一段内存标记为PROT_EXEC。

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

int (*ret)();

unsigned char* buf;

int main()
{
    FILE* file;
    file = fopen("text.txt", "rb");

    unsigned int len = ftell(file);

    buf = (char*)malloc(len);
    fread(buf, 1, len, file);

    fclose(file);

    mprotect(&buf, len, PROT_EXEC);

   // I also tried mmap, but same error.
   /*void *ptr = mmap(0, 1024, PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);

    if (ptr == MAP_FAILED)
    {
        perror("mmap");
        exit(-1);
    }

    memcpy(ptr, buf, 1024);*/

    ret = buf;

    ret();

    return 0;
}

这是我正在阅读的text.txt文件,它的hello世界代码相同:

\x55\x48\x89\xe5\xeb\x33\x48\x31\xff\x66\xbf\x01\x00\x5e\x48\x31\xd2\xb2\x0e\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c\x89\xc0\x0f\x05\x31\xff\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89\xc0\x0f\x05\x48\x89\xec\x5d\xe8\xc8\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0a

因为我正在将txt文件的内容复制到PROC_EXEC内存中,所以我不明白为什么我会得到KERN_PROTECTION_FAILURE。

1 个答案:

答案 0 :(得分:9)

您的程序尝试从标记为“execute disable”的内存页面执行shellcode,这是数据部分中内存的默认值。这就是你看到KERN_PROTECTION_FAILURE的原因。您需要将shellcode放在文本部分中:

__attribute__((section("__TEXT,__text")))
char code[] = ...

这样做之后,你的程序运行正常:

$ clang -Wall -Wextra -pedantic -O2 example.c -o example
$ ./example
Hello, World!

编辑说明:您不需要在函数指针调用上进行类型转换。只需ret();即可。你需要至少摆脱(int)部分进行编译而不发出警告。

编辑:

这是一个有效的程序,无需你进行分段覆盖体操:

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

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c"
              "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2"
              "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89"
              "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65"
              "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0a";

int main()
{
    int (*ret)() = (int (*)())code;
    void *page = (void *)((uintptr_t)code & ~(getpagesize() - 1));

    mprotect(page, sizeof code, PROT_EXEC);

    ret();

    return 0;
}

示例运行:

$ clang -O2 -Wall -Wextra example.c -o example
$ ./example
Hello, World!
$ gcc -O2 -Wall -Wextra example.c -o example
$ ./example
Hello, World!