如何关闭 gcc 编译器优化以启用缓冲区溢出

Posted

技术标签:

【中文标题】如何关闭 gcc 编译器优化以启用缓冲区溢出【英文标题】:How to turn off gcc compiler optimization to enable buffer overflow 【发布时间】:2011-01-21 08:48:49 【问题描述】:

我正在开发一个homework problem,它需要禁用编译器优化保护才能使其工作。我在 ubuntu linux 上使用 gcc 4.4.1,但不知道哪些标志是正确的。我意识到它依赖于架构 - 我的机器使用 32 位 Intel 处理器运行。

谢谢。

【问题讨论】:

【参考方案1】:

您无需禁用 ASLR 即可进行缓冲区溢出!虽然启用了 ASLR (kernel_randomize_va_space = 2),但除非编译的可执行文件是 PIE,否则它不会生效。所以除非你用-fPIC -pie标志编译你的文件,否则ASLR不会生效。

我认为只用-fno-stack-protector 禁用金丝雀就足够了。 如果要检查 ASLR 是否工作(必须设置与位置无关的代码),请使用:

hardening-check executable_name

【讨论】:

【参考方案2】:

呃,到目前为止,所有的答案都是错误的,因为 Rook 的答案是正确的。

输入:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

接着是:

gcc -fno-stack-protector -z execstack -o bug bug.c

禁用 ASLR、SSP/Propolice 和 Ubuntu 的 NoneXec(放置在 9.10 中,并且工作起来相当简单,请参阅 mprotect(2) 将页面映射为可执行文件和 jmp 的技术)应该会有所帮助,但是这些“安全功能”绝不是万无一失的。如果没有 `-z execstack' 标志,页面将具有不可执行的堆栈标记。

【讨论】:

您没有阅读这些人的链接。如果你这样做了,你就会知道他正在尝试执行 g(),这是一个编译到二进制文件中的函数。这是一个函数的地址。当您尝试在堆或堆栈上执行 shellcode 时,NX 位就会发挥作用,他的攻击要简单得多。 我同意其他人都是完全错误的,很明显我们是唯一两个利用缓冲区溢出的人。但是我仍然认为我的答案更正确。 嗯,刚刚看到链接——我认为这只是另一个通用的,你是对的。我道歉。 我知道这是一篇旧帖子,但您不能将 sudo 与 > echo 0 | sudo tee /proc/sys/kernel/randomize_va_space【参考方案3】:

在较新的发行版上(截至 2016 年),PIE 似乎默认启用,因此您需要在编译时明确禁用它。

这里有一些命令的小结,对于在本地玩一般的缓冲区溢出练习很有帮助:

禁用金丝雀:

gcc vuln.c -o vuln_disable_canary -fno-stack-protector

禁用 DEP:

gcc vuln.c -o vuln_disable_dep -z execstack

禁用 PIE:

gcc vuln.c -o vuln_disable_pie -no-pie

禁用上面列出的所有保护机制(警告:仅用于本地测试):

gcc vuln.c -o vuln_disable_all -fno-stack-protector -z execstack -no-pie

对于 32 位机器,您还需要添加 -m32 参数。

【讨论】:

-m3264 位机器 上构建32 位代码 时需要。此外,您可以使用-fno-pie 让编译器生成不会干扰PIE 的asm,以及使用-no-pie 让它不将该机器代码链接到PIE。对于 32 位模式,-fno-pie 将显着简化 asm,去除像 call __x86.get_pc_thunk.bx 这样的废话。对于 64 位模式,大多数情况下只允许 mov-immediate 而不是 RIP-relative LEA 用于静态地址,以及 more efficient indexing of static arrays。【参考方案4】:

这是个好问题。为了解决这个问题,您还必须禁用 ASLR,否则 g() 的地址将无法预测。

禁用 ASLR:

sudo bash -c 'echo 0 > /proc/sys/kernel/randomize_va_space'

禁用金丝雀:

gcc overflow.c -o overflow -fno-stack-protector

禁用金丝雀和 ASLR 后,它应该是像 Smashing the Stack for Fun and Profit 中描述的直接攻击

这里是 ubuntu 中使用的安全功能列表:https://wiki.ubuntu.com/Security/Features 您不必担心 NX 位,g() 的地址将始终位于内存的可执行区域中,因为它位于 TEXT 内存中部分。只有当您尝试在堆栈或堆上执行 shellcode 时,NX 位才会发挥作用,这不是此分配所必需的。

现在去破坏那个EIP

【讨论】:

谢谢,我会这样做的 :) 哦 - 我如何重新启用保护以解除我的机器损坏?.. 我的猜测是 sudo echo 1 > /proc/sys/kernel /randomize_va_space @sa125 是的,它就是这样重新启用的。事实上,这就是您在系统运行时打开和关闭其他内核模块的方式;) 似乎值得指出的是,在我的系统上,randomize_va_space 默认为 2,而不是 1,因此如果您打算重新启用它,值得事先检查。 实际上 g() 的地址很可能不会被 ASLR 随机化,因为它是主二进制文件的一部分。仅当您使用 -PIE 编译二进制文件时,它才会被随机化。 现代 Linux 发行版 configure GCC to build PIE executables by default、@RobertLarsen(以及未来的读者)。您可以使用gcc overflow.c -fno-stack-protector -fno-pie -no-pie 来制作传统的 ELF 可执行文件,而不是共享对象。 (那么您不必为系统范围内的非堆栈段或此可执行文件禁用 ASLR,BTW 是 GDB 所做的。根本不需要禁用系统范围。)【参考方案5】:

我不会引用整个页面,但完整的优化手册可以在这里找到:http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Optimize-Options.html#Optimize-Options

从它的声音你至少想要-O0,默认值,并且:

-fmudflap -fmudflapth -fmudflapir

对于支持它的前端(C 和 C++),检测所有风险 指针/数组解引用 操作,一些标准库 字符串/堆函数,以及其他一些 相关的结构 范围/有效性测试。模块如此 仪表应该不受 缓冲区溢出,无效堆使用, 和其他一些 C/C++ 类 编程错误。这 仪器依赖于一个单独的 运行时库 (libmudflap),其中 将被链接到一个程序中,如果 -fmudflap 在链接时给出。检测的运行时行为 程序由控制 MUDFLAP_OPTIONS 环境变量。 请参阅环境 MUDFLAP_OPTIONS=-help a.out 供其选择。

【讨论】:

【参考方案6】:

试试-fno-stack-protector 标志。

【讨论】:

以上是关于如何关闭 gcc 编译器优化以启用缓冲区溢出的主要内容,如果未能解决你的问题,请参考以下文章

如何启用递归函数以避免堆栈溢出?

gcc地址清理程序核心转储出错

gcc编译选项-Wextra(启用额外的警告信息,提高代码质量和安全性)

在研究缓冲区溢出时,我应该使用哪些版本的 GCC 或标志?

如何解决栈溢出

缓冲区溢出攻击实践