我已经下载并编译了苹果源代码,并将其添加到Xcode.app/Contents/Developer/usr/bin/include/c++/v1.中现在我该如何开始用C实现呢?我正在使用的代码来自this关于Hackadays外壳代码执行器的帖子。我的代码目前是这样的:
#include <stdio.h>
#include <stdlib.h>
unsigned char shellcode[] = "\x31\xFA......";
int main()
{
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
printf("2\n");
}我用这两个都编译过:
gcc -fno-stack-protector shell.c
clang -fno-stack-protector shell.c我想我的最后一个问题是,我如何告诉编译器实现"__enable_execute_stack"?
发布于 2015-06-24 15:57:10
堆栈保护器不同于可执行堆栈。这引入了金丝雀来检测堆栈何时被损坏。
要获得可执行堆栈,您必须链接使用可执行堆栈。不用说,这是一个坏主意,因为它使攻击变得更容易。
链接器的选项是-allow_stack_execute,它变成了gcc/clang命令行:
clang -Wl,-allow_stack_execute -fno-stack-protector shell.c但是,您的代码不会尝试在堆栈上执行代码,但会尝试更改堆栈的少量内容,尝试返回外壳代码,这是最常见的ROP攻击之一。
在典型的编译OSX 32bit environment上,这将尝试覆盖所谓的链接区(这是函数返回时将调用的下一条指令的地址)。这假设代码不是用-fomit-frame-pointer编译的。如果它是用这个选项编译的,那么你实际上是在向上移动一个额外的地址。
在OSX64位it uses the 64bit ABI上,寄存器是64位的,所有的值都需要由long引用,而不是由int引用,但是方式是相似的。
然而,您获得的外壳代码实际上位于代码的数据段中(因为它是一个char [],这意味着它是可读/可写的,而不是可读/可执行的。您需要将其mmap (就像nneonneo的答案),或者将其复制到现在可执行的堆栈中,获取它的地址并以这种方式调用它。
然而,如果你只是想让代码运行,那么nneonneo的答案会让它变得非常简单,但是如果你想尝试利用-y代码,那么你需要做更多的工作。由于非可执行堆栈,新的孩子们使用返回库机制,试图让返回调用,比方说,使用堆栈中的数据调用exec/system调用之一。
发布于 2015-06-24 16:20:05
有了现代的执行保护,让外壳代码像这样运行就有点棘手了。请注意,您的代码并不是试图在堆栈上执行代码;相反,它将外壳代码的地址存储在堆栈上,而实际代码位于程序的数据段中。
你有几个选项可以让它工作:
__attribute__((section("name"))),通过GCC和Clang来做到这一点。在OS X上:const char code[] __attribute__((section("__TEXT,__text“)= "...";
后跟一个
((void (*)(void))code)();
效果很好。
mmap创建一个读写的内存部分,复制你的外壳代码,然后mprotect它使它具有读-执行权限,然后执行它。这就是现代JIT执行动态生成代码的方式。举个例子:#include size_t execute_code(const void * size_t,codesize) {size_t pagesize =( PAGE_SIZE +PAGE_SIZE- 1) & ~(PAGE_SIZE - 1);void *chunk = mmap(NULL,pagesize,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0);if(chunk == MAP_FAILED) return;memcpy(chunk,代码,codesize);mprotect(chunk,pagesize,PROT_READ|PROT_EXEC);((void (*)(Void)分块)();munmap(分块,页面大小);}
这两种方法都不需要指定任何特殊的编译器标志才能正常工作,也不需要摆弄堆栈上保存的EIP。
https://stackoverflow.com/questions/31017817
复制相似问题