问题标签 [stack-smash]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
1805 浏览

c - 使用 GCC 的堆栈保护和粉碎

我正在阅读Smashing the Stack for Fun and Profit(特别是,这篇文章指的是“缓冲区溢出”部分)。这篇文章是为 32 位机器编写的,但是我正在使用 64 位机器,我在我的示例中对此进行了考虑。一个特殊的例子是导致一些我无法解释的问题。example3.c 具有覆盖返回地址以跳过主函数中的指令的功能。这是我的代码:

我用 gcc v4.8.2 用以下命令编译这个程序:

请注意,默认情况下 gcc 编译器似乎实现了一些堆栈保护,例如地址空间布局随机化和堆栈金丝雀。我在计算 ret 指针值时考虑了这些安全措施。以下是由 生成的相应程序集 gcc example3.c -S -fverbose-asm -o stack-protection.s

执行 example3 具有跳过第二个分配到x和程序输出的预期效果0

但是,如果我改为使用以下-fno-stack-protector选项进行编译:

我收到以下汇编文件:

并且相应的可执行文件不会产生所需的 0 值,而是一个我无法与程序集文件协调的随机值。

在这种情况下,我对堆栈帧的-fno-stack-protector印象是(sfp = 保存的帧指针,ret = 返回地址):

我的问题:

我是否在不受保护的情况下误算了退货地址的位置?

0 投票
1 回答
637 浏览

c - 粉碎堆栈 example3 ala Aleph One

我已经复制了示例 3,来自Smashing the Stack for Fun and Profit on Linux x86_64。但是,我无法理解应该增加到返回地址以跳过指令的正确字节数是多少:

这就是我认为x = 1指令所在的地方。我写了以下内容:

并在 gdb 中对其进行反汇编。-fno-stack-protector我已禁用地址随机化并使用该选项编译程序。

问题 1

我可以从下面的反汇编程序输出中看到,我想跳过 address 处的指令0x0000000000400595:返回地址 fromcallq <fn>movl指令的地址。因此,如果返回地址是0x0000000000400595,下一条指令是0x000000000040059c,我应该在返回地址上加 7 个字节吗?

问题2

我注意到我可以向返回地址添加 5 个字节来代替 7 并获得相同的结果。当我这样做时,我不是跳到指令的中间0x0000000000400595 <+35>: movl $0x1,-0x4(%rbp)吗?在这种情况下,为什么这不会使程序崩溃,例如当我将 6 个字节添加到返回地址而不是 5 个字节或 7 个字节时。

问题 3

就在堆栈上的 buffer1[] 之前是 SFP,在它之前是返回地址。即 4 个字节通过 buffer1[] 的末尾。但请记住,buffer1[] 实际上是 2 个字,所以它有 8 个字节长。所以返回地址是从 buffer1[] 开始的 12 个字节。

在 Aleph 1 的示例中,他/她从 buffer1[] 的开始计算返回地址的偏移量为 12 个字节。由于我使用的是 x86_64,而不是 x86_32,因此我需要重新计算返回地址的偏移量。在x86_64上,是不是buffer1[]还是2个字,也就是16个字节;并且 SFP 和返回地址各为 8 个字节(因为我们使用的是 64 位),因此返回地址位于:buf1 + (8 * 2) + 8相当于buf1 + 24?

0 投票
0 回答
88 浏览

c - 在内核空间中模拟函数返回

我正在尝试将指令点 ( regs->ip) 设置为可加载内核模块(对于 Linux 3.13)中函数的返回地址。但是,它会引发stack smashing检测。我的问题是如何绕过它。

更具体地说,在内核模块中设置指令点之前,用户态进程的堆栈如下所示:

内核模块将ip(指令点)设置为的返回地址bar,这显然是堆栈溢出......

所以我在想我是否可以foo在内核模块中模拟返回,这样设置ip就不会导致smashing detected错误。

首先,这个猜测正确吗?也就是说,通过foo在内核空间中模拟返回允许我返回bar而不检测到粉碎?

二、如果正确,如何在内核空间实现?

更新:一个有趣的(或未定义的)行为:该bar函数看起来像:

a永远不会填充任何数据,也不会在之后引用。如果我删除声明,smashing将消失。否则,它会留下来。(顺便说一句,我可以end of bar()在打印输出中看到)。

0 投票
1 回答
481 浏览

stack-overflow - 将 shellcode 注入堆栈粉碎时出现分段错误

我一直试图了解堆栈溢出攻击是如何工作的。到目前为止,我可以成功地将返回地址重定向到原始代码中的一条指令。我在汇编中编写了一个 shellcode 启动器,并让它在 ac 程序中工作。通过使用 gdb 进行调试,我获得了代表 shellcode 启动器的十六进制,并且 c 程序运行良好。然而,当我尝试将这个十六进制字符串注入另一个程序时,我得到了分段错误。当我跟踪返回地址时,我意识到它已成功设置为在程序退出之前指向十六进制字符串。快照显示了这些步骤。我无法弄清楚为什么注入不起作用,因为相同的代码可以在程序集中创建 shell 并且主函数的返回地址被设置为指向 sc (创建新 shell 的字符串)。

当我编译并运行上述包含程序集的 c 代码时,它运行得非常好。我使用gdb在上面的c程序中获得了asm代码的十六进制并生成了以下堆栈粉碎代码。

当我运行代码时,出现以下错误。程序收到信号 SIGSEGV,分段错误。sc()中的0x0804a01c

0 投票
1 回答
159 浏览

c - __interceptor_strchr 做什么?

我的函数在此机器指令之后立即崩溃(由于堆栈溢出):

做什么__interceptor_strchr(char const*, int)

0 投票
1 回答
129 浏览

c - 堆栈粉碎,找不到溢出错误

我正在尝试编写一个函数,如果字符串的长度小于分配给 char 缓冲区的最大大小,它将用某个字符填充字符串。我遇到了“ *检测到堆栈粉碎*:./test 终止”错误,它停止了我的测试程序,因为我假设某处有溢出覆盖了一些受保护的内存。这似乎是一个简单的功能,但我似乎无法找到错误的原因。

我认为这可能是一个问题,但测试字符串的长度似乎没有超过缓冲区的大小。

任何人都可以提供帮助吗?

谢谢

0 投票
0 回答
600 浏览

c - 检测到堆栈粉碎 - 从 C 到汇编

我正在尝试从 C 转换为汇编两个函数,一个对索引数组进行排序,另一个从索引开始查找最小数字。当我运行它工作的程序时,新数组被排序但最后它给了我这个错误

这是我的 .c 文件

和我的 .s 文件

编译我使用

我不认为问题出在程序集翻译中,因为它正确打印了新数组。可能是什么问题呢?

0 投票
1 回答
2063 浏览

c++ - *** stack smashing detected *** error at the return of a function using FEAST

I have a long program in which I have a function for calculating eigenvalues of a large matrix using FEAST. Right at the return of that function I get a * stack smashing detected * error and I lose all the results. Here is my the function

The dfeast_scsrev is a function from FEAST library (also part of intel MKL). The error happens right at the return (i.e. after the "Written eigenvalues to file evals.dat." is printing). Depending on the problem I run, sometimes I also get segmentation fault right at the same point.

If I remove the FEAST function call, there is no error. So, I am confused what I am doing wrong. I am trying valgrind, but because of the size of my code, it is taking a long time to run.

0 投票
2 回答
3010 浏览

stack - ***检测到堆栈粉碎***:a.out终止

因此,我正在我的编程 I 课程中编写一个程序,我们被分配创建一个程序,该程序将检查银行的​​路由号码是否有效。每次我在 NetBeans 上运行这个程序时,我都没有问题。但是,当我通过我们的 Ubuntu 学生服务器运行它时,我得到了这个疯狂的错误。我一直在尝试调试这个程序一段时间,但不太清楚这个错误是从哪里来的。我已经尝试更改数组大小,但没有运气,我仍然收到此错误。这是错误的副本:

这是我的源代码的副本:

如果您有任何人熟悉此错误消息,请帮助!太感谢了!

0 投票
1 回答
3324 浏览

c - 基于堆栈的缓冲区溢出 - 使用有限输入的 scanf 在 C 中的挑战

作为安全 CS 课程的一部分,我的班级被赋予了利用漏洞利用堆栈/缓冲区溢出来击败密码检查的任务。存在漏洞的代码如下:

我理解经典的“堆栈粉碎”原理(我认为),这里有一个明显的溢出漏洞,correct_hash可以通过在提示时输入超过 15 个字符的密码来覆盖数组的前 14 个字节。但是,我不明白如何利用它来让memcmp检查通过,完成挑战。我发现/尝试的一些事情:

  • 设置password为等价的correct_hash不起作用,因为password使用哈希MD5()(无论如何都不可能将两者设置为相等,因为scanf将精确地插入一个唯一的 ASCIINUL字符到可用的 30 个空格中,这意味着这两个数组永远不会等价.NUL字符(据我所知)不能插入scanf字符串中间)。

  • scanf用(总是附加一个字符)覆盖最大字节数NUL意味着最后 3 个字节correct_hash总是0x00 0x91 0xeb. 尝试随机生成一个 16 个字符的密码,然后用最后 3 个字节/字符(考虑到使用 MD5,计算上相当容易)进行哈希处理是行不通的,但是,由于使用strlen(password)(这将给出一个值29而不是像 16 这样方便的东西,这要归功于NUL在对MD5(). 这意味着,不是对 16 个字符的密码进行散列以产生预期的输出,而是对 16 个字符的调用进行MD5()散列,password然后是 13 个字符correct_hash,产生不同的最终散列值。

    • 为了解决这个问题,我相信必须找到一个 29 个字符的字符串(称为 S),其中 S 的前 16 个字符散列到由 S 的最后 13 个字符组成的字符串 R,然后是0x00 0x91 0xeb. 我不确定通过随机 MD5 哈希计算找到这一点有多可行,但它并不看好我的机会。

一些注意事项(在上面的解释中提到):

  • scanf限制为 29 个字符的字符串,但会附加一个 ASCIINUL字符,从而允许覆盖总共 30 个字符(数组中的 16 个,password数组中的 14 个)。correct_hash

  • NUL无法输入ASCII字符,scanf因此strlen(password)在调用中MD5()(如果使用最大密码长度)将为 29。

所以这里的问题是,我还能怎么做呢?我错过了一些非常明显的东西吗?随机生成是可行的解决方案,还是唯一的解决方案?

解决方案必须使用缓冲区溢出(否则我想我可以做一些像 preload amemcmp总是返回 0 的事情),并且必须可以作为 shell 脚本执行(如果有任何相关性的话)。