如何关闭 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
参数。
【讨论】:
-m32
在64 位机器 上构建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 编译器优化以启用缓冲区溢出的主要内容,如果未能解决你的问题,请参考以下文章