【问题标题】:Regarding state of stack关于堆栈状态
【发布时间】:2011-12-08 11:40:22
【问题描述】:

我有一个程序,我想了解堆栈在其执行期间的状态。我的示例程序很简单,

#include <stdio.h>
 int main(){
   setuid(0);
   system("/bin/bash");
   return 1;
 }

现在,当我使用 gdb 调试该程序时,我得到了 setuid() 函数的地址,但是当我查看堆栈时,我无法确定它的地址。

我的堆栈在开始执行main()后的状态,

Ajai@ubuntu:/tmp$ gdb -q mal
Reading symbols from /tmp/mal...done.
(gdb) b 2
Breakpoint 1 at 0x80483fd: file mal.c, line 2.
(gdb) r
Starting program: /tmp/mal 

Breakpoint 1, main () at mal.c:4
4        setuid(0);
(gdb) x/32xw $esp
0xbffff3a0:    0x0015ed35    0x0011ea50    0x0804842b    0x0028bff4
0xbffff3b0:    0x08048420    0x00000000    0xbffff438    0x00145e37
0xbffff3c0:    0x00000001    0xbffff464    0xbffff46c    0x0012e414
0xbffff3d0:    0xffffffff    0x0012cff4    0x08048243    0x00000001
0xbffff3e0:    0xbffff420    0x0011da31    0x0012dad0    0xb7fffb48
0xbffff3f0:    0x00000001    0x0028bff4    0x00000000    0x00000000
0xbffff400:    0xbffff438    0xb68cac87    0x61d0d5f8    0x00000000
0xbffff410:    0x00000000    0x00000000    0x00000001    0x08048340
(gdb) p setuid
$1 = {<text variable, no debug info>} 0x1c8ee0 <setuid>

我是不是看错了堆栈?

我也想知道当main()函数开始执行时setuid()函数调用及其参数和system()函数调用及其参数的地址如何入栈。

很抱歉,如果有人问过这类问题,但我找不到。

【问题讨论】:

  • 函数的地址可能根本不在栈中。代码中需要它;堆栈中不需要它。在从main() 调用的函数中,main() 内部的返回地址将在堆栈上,但这与main() 本身的地址不同。

标签: c function gdb stack


【解决方案1】:

您的问题非常不清楚,可能是因为您不了解堆栈和调用如何工作和交互。

不知何故,您希望在调用该函数之前在堆栈上找到 setuid 的地址。但该地址根本不存在(在通话之前、通话过程中、通话结束后都不存在)。

如果您在setuid 本身上设置断点,请运行到该断点并检查堆栈。然后,您将看到main 中的地址(不是main 本身的地址,而是main 中的指令,该指令紧跟在首先让您进入setuid 的CALL 指令之后)。

我假设这是当执行即将转到 setuid() 函数时堆栈的样子(假设我在 setuid 函数调用处有一个断点)

1.调用setuid()

2.setuid()函数调用后要到达的返回地址

3.setuid() 函数的参数。

正如我所说,您的假设不正确:堆栈上没有“调用 setuid”(但 2. 和 3. 是正确的)。

【讨论】:

  • 好的,我会尽量把我的问题说清楚一点。在堆栈中,如果在这种情况下进行函数调用 setuid() 我假设这是当执行即将转到 setuid() 函数时堆栈的样子(假设我在 setuid 函数调用处有一个断点)> 1.call setuid() 2. setuid() 函数调用后要到达的返回地址 3. setuid() 函数的参数。我说的对吗?
  • 这不是很清楚,但我认为你真的混淆了堆栈上的内容。程序执行由代码段(cs 寄存器)控制,您可以使用 EIP 指针查看该代码段。马蹄莲的地址通常在寄存器中;哪一个,您可以通过单步执行程序集来查看。堆栈是局部变量和函数参数的临时存储。所以是的,你会在堆栈上或附近找到 (3),但不是 (1) 或 (2)(除了两个,你的意思是旧的 ESP/EBP,但我对此表示怀疑。我认为你的意思是下面的行旧 EIP。
  • 如果我写的东西对你来说没有意义,我真的建议抓住任何关于这方面的书。旧的“黑客。剥削的艺术”。虽然过时了,但如果您从未这样做过,那么在此类问题上表现出色。
  • 好吧,旧的 EIP 实际上保存在堆栈中,但是您需要更清楚地处理堆栈信息等,我强烈建议您阅读上述书籍或任何免费的在线资源,否则这会让您感到困惑。
  • 很抱歉给您带来了困惑。我得到了它。我对其他问题感到震惊,并将其与其他问题混淆了。我现在明白你在说什么了。谢谢。
【解决方案2】:

正如 ER 所指出的,单步执行组装说明。被调用函数的地址通常在函数调用之前放入 EAX 寄存器。检查它,或者你的编译器放入的任何其他内容。

【讨论】:

    猜你喜欢
    • 2021-06-04
    • 1970-01-01
    • 2018-08-06
    • 2019-11-27
    • 2013-02-11
    • 2012-06-02
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多