![在 Ubuntu 上禁用堆栈保护以防止没有 C 编译器标志的缓冲区溢出](https://linux22.com/image/29365/%E5%9C%A8%20Ubuntu%20%E4%B8%8A%E7%A6%81%E7%94%A8%E5%A0%86%E6%A0%88%E4%BF%9D%E6%8A%A4%E4%BB%A5%E9%98%B2%E6%AD%A2%E6%B2%A1%E6%9C%89%20C%20%E7%BC%96%E8%AF%91%E5%99%A8%E6%A0%87%E5%BF%97%E7%9A%84%E7%BC%93%E5%86%B2%E5%8C%BA%E6%BA%A2%E5%87%BA.png)
我想尝试一些 shell 代码并且我想禁用 linux 保护。
我知道我可以使用标志进行编译,但我知道存在另一种方法来禁用这些保护,我只是不记得了。你能帮助我吗?
答案1
为了扩展 vonbrand(正确的是,+1)所说的内容,Linux 的堆栈保护分为两个部分。
堆栈金丝雀
堆栈金丝雀是 vonbrand 所指的编译器强制功能。如果不重新编译,就无法禁用这些功能。
为了向自己证明这一点并了解它们是如何工作的,请使用以下代码:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
int mybadfunction(char* a_bad_idea)
{
char what[100];
strcpy(what, a_bad_idea);
printf("You passed %s\n", what);
}
int main(int argc, char** argv)
{
printf("Tralalalaala\n");
mybadfunction(argv[1]);
}
现在将 ( gcc -fstack-protector -masm=intel -S test.c
) 编译成 gnu 的东西,因为它会很乐意汇编并读取输出。重要的一点是,在退出函数时mybadfunction
,有这么一小段代码:
mov edx, DWORD PTR [ebp-12]
xor edx, DWORD PTR gs:20
je .L2
call __stack_chk_fail
正如您所猜测的,这是从 中获取堆栈 cookie[ebp-12]
并将其与 处的值进行比较gs:20
。不匹配?然后它调用 glibc 中的一个函数__stack_chk_fail
来杀死你的程序。
有多种方法可以通过编写漏洞来解决这个问题,但构建 shellcode 测试用例的简单方法是使用-fno-stack-protector
.
不可执行页面
现代 Linux 系统还有一些其他考虑因素。如果您采用通常的 shellcode 测试存根:
char buffer[] = {...};
typedef void (* func)(void);
int main(int argc, char** argv)
{
func f = (func) buffer;
f();
return 0;
}
现代 GCC/Linux 将映射.rodata
PE 文件的只读部分,没有执行权限。您需要将其关闭,这可以使用以下代码示例来完成这篇博文。基本思想:你可以mprotect
给shellcode数据所在的页面添加你想要的权限。
不可执行堆栈
如果您要使用 shellcode 测试传统的漏洞利用场景(例如上面的错误代码),那么您还需要确保堆栈对于简单情况是可执行的。 PE 文件格式包含一个用于确定堆栈是否可执行的字段 - 您可以使用以下命令查询和控制它执行堆栈。要启用可执行堆栈,请运行
execstack -s /path/to/myprog
这能可以在任意程序上完成,无需重新编译,但不会自动禁用堆栈金丝雀,因为它们是在编译时内置的。
额外奖励:aslr:
要关闭它,echo 0 > /proc/sys/kernel/randomize_va_space
.
你刚刚告诉别人如何利用我珍贵的企鹅吗?
不。任何漏洞利用都必须围绕堆栈金丝雀(非常重要)进行工作,并且要么找到带有execstack
set 的程序,要么设置它(意味着它已经可以执行任意命令),或者使用更困难的技术,例如返回 libc/return定向编程。
答案2
堆栈保护由编译器完成(向堆栈添加一些额外的数据并在调用时存储一些数据,在返回时检查完整性)。如果不重新编译就无法禁用它。这是重点的一部分,真的......
答案3
您可以使用这些选项禁用某些保护(堆栈粉碎检测并使堆栈可执行)。
--z execstack
-f no-stack-protector
您还可以使用 Bash 使用以下命令关闭 ASLR(地址空间布局随机化):
echo 0 > /proc/sys/kernel/randomize_va_space