【问题标题】:Analyzing gdb disassembly分析gdb反汇编
【发布时间】:2014-03-15 02:32:02
【问题描述】:

免责声明:这是一个家庭作业问题,所以我不希望您只告诉我答案。相反,我需要帮助来理解这段代码是如何工作的。如果不允许这样做,那很好,我可以将其删除或我需要的任何内容。 我想做的是了解 x86(英特尔)。我只是在学习它,并且发生了很多事情,以至于我经常发现自己盯着屏幕没有任何进展。对我有帮助的是向我提出导致答案的问题,而不是给我答案。我知道这不是一个讨论论坛,所以也许有人可以指出我很乐意帮助我解决此类问题的地方。

目前我所理解的是,空间是由 sub 指令在堆栈上分配的。 然后将 eax 中的任何内容移动到堆栈中。然后 mov 和 lea 的组合让我感到困惑。我的直觉告诉我,指针被存储在堆栈中以供以后使用。或者它可能是对我提供的数字执行某种数学函数。在函数的开头,我发现 eax 有我输入的数字。 我发现的另一件事是执行 x/s 0x804a819 给了我“%d %d %d %d %d %d”。这是将六个数字移动到 0x4(%esp) 吗?我从 movl 指令中找到了地址 0x804a819。 就在调用 sscanf 之前有 mov %eax,(%esp) 我假设程序正在保存堆栈指针的位置以供以后使用?我尝试过的一件事是在调用 0x80488d0 <__isoc99_sscanf> 执行后我做了 p $eax = 0x7 以便指令 cmp $0x5,%eax 设置正确的标志,以便指令 jg 0x80495b5 将跳过调用 explode_bomb .但不管explode_bomb 被调用什么。所以我确定我缺少一些东西,而且它甚至可能不在这个函数中。

其他一些问题。 一个函数的局部变量存放在栈上正确吗?

sub    $0x2c,%esp
mov    0x34(%esp),%eax
lea    0x14(%eax),%edx
mov    %edx,0x1c(%esp)
lea    0x10(%eax),%edx
mov    %edx,0x18(%esp)
lea    0xc(%eax),%edx
mov    %edx,0x14(%esp)
lea    0x8(%eax),%edx
mov    %edx,0x10(%esp)
lea    0x4(%eax),%edx
mov    %edx,0xc(%esp)
mov    %eax,0x8(%esp)
movl   $0x804a819,0x4(%esp)
mov    0x30(%esp),%eax
mov    %eax,(%esp)
call   0x80488d0 <__isoc99_sscanf@plt>
cmp    $0x5,%eax
jg     0x80495b5 <read_six_numbers+76>
call   0x804941c <explode_bomb>
add    $0x2c,%esp
ret 

【问题讨论】:

  • 记住 AT&T 的语法是愚蠢和倒退的 - eax 最初是加载堆栈的。
  • 所以你想要一个提示:堆栈用于两件事,一个是(如你所说)存储自动(函数中的局部变量),另一个“调用”行可以帮助你与。
  • 我很确定这是 intel 语法
  • 编译器会选择lea指令,如果它需要做加法并在一个步骤中将结果存储在不同的寄存器中。例如 0x14(%eax),%edx 将 20 加到 eax 并将结果放在 edx 中。 lea 的不同版本可以添加 两个 寄存器,可选择将其中一个乘以 2、4 或 8,再加上一个常数,然后将结果放在不同的寄存器中。
  • 只是为了澄清你的最后一个问题,只有 自动 局部变量进入堆栈。静态局部变量将放在堆上。

标签: c gdb disassembly


【解决方案1】:

记住在 i386 上,函数参数在堆栈上传递可能会有所帮助。在函数入口处,如果你读取堆栈指针地址处的内存字,你会找到调用者的返回地址。

看起来你的神秘函数有两个参数。所以当它说

sub    $0x2c,%esp
mov    0x34(%esp),%eax

从堆栈指针中减去 0x2c 后,我们可以在 *(esp + 0x2c) 找到调用者保存的 eip,我们可以在 *(esp + 0x30) 找到第一个参数,我们可以在 *(esp + 0x34) 找到第二个参数。你可以在这里看到对第二个参数的引用,

movl   $0x804a819,0x4(%esp)
mov    0x30(%esp),%eax
mov    %eax,(%esp)
call   0x80488d0 <__isoc99_sscanf@plt>

这会将格式字符串的地址存储在 *(esp+4) 的地址 (0x804a819) - 所以这将是 sscanf() 的第二个参数。然后它将第一个参数加载到您的神秘函数(*(esp + 0x30))并将其存储在*(esp) - 所以它将成为sscanf() 的第一个参数。

希望这足以帮助您理解该功能,而不会太有帮助。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 2010-12-07
    • 2010-12-19
    • 2019-11-23
    • 1970-01-01
    相关资源
    最近更新 更多