从C – Bus错误10测试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!' 

我遇到的问题是当我尝试将此代码作为来自ac程序的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  #include  #include  #include  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。

您的程序尝试从标记为“ 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  #include  #include  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!