You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何%rbp不等于值为0x28的%rsp?汇编逻辑错误排查

汇编代码分析:phase_2函数拆解

栈帧初始化与栈保护

164b:       f3 0f 1e fa             endbr64
164f:       55                      push   %rbp
1650:       53                      push   %rbx
1651:       48 83 ec 28             sub    $0x28,%rsp
1655:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
165c:       00 00
165e:       48 89 44 24 18          mov    %rax,0x18(%rsp)
1663:       31 c0                   xor    %eax,%eax
  • push %rbp/push %rbx:保存调用者的非易失性寄存器,遵循x86-64调用约定
  • sub $0x28, %rsp:在栈上开辟40字节空间,用于存储输入数据和栈保护值
  • 最后三行是栈金丝雀机制:从fs段取出随机校验值存入栈中,函数结束时会校验该值,防止栈溢出攻击

输入读取与第一关校验

1665:       48 89 e6                mov    %rsp,%rsi
1668:       e8 18 08 00 00          call   1e85 <read_six_numbers>
166d:       83 3c 24 01             cmpl   $0x1,(%rsp)
1671:       75 0a                   jne    167d <phase_2+0x32>
167d:       e8 c1 07 00 00          call   1e43 <explode_bomb>
  • mov %rsp, %rsi:将栈顶地址传给read_six_numbers作为参数,输入的6个整数会被存在从%rsp开始的连续24字节空间中
  • cmpl $0x1, (%rsp):强制要求第一个输入数字必须是1,否则直接触发explode_bomb

循环逻辑初始化(你的错误点在这里)

1673:       48 89 e5                mov    %rsp,%rbp
1676:       bb 02 00 00 00          mov    $0x2,%ebx
167b:       eb 13                   jmp    1690 <phase_2+0x45>

你之前推测%rbp为十进制-40是完全错误的:

  • mov %rsp, %rbp是把当前栈顶的绝对地址赋值给%rbp,而非偏移量。此时%rbp直接指向第一个输入数字的存储位置,后续作为指针遍历所有输入数字
  • mov $0x2, %ebx:%ebx作为循环计数器,初始值为2,代表当前要检查第2个输入数字

循环核心校验逻辑

1690:       89 d8                   mov    %ebx,%eax
1692:       0f af 45 00             imul   0x0(%rbp),%eax
1696:       39 45 04                cmp    %eax,0x4(%rbp)
1699:       74 e9                   je     1684 <phase_2+0x39>
169b:       e8 a3 07 00 00          call   1e43 <explode_bomb>
  • 第一次循环时:%eax = 2 * [rbp]([rbp]是第一个输入数字1),结果为2
  • cmp %eax, 0x4(%rbp):检查第二个输入数字是否等于2,相等则继续循环,否则触发炸弹
  • 总结逻辑:第n个输入数字(n从2到6)必须等于n乘以第n-1个输入数字

循环迭代与终止

1684:       83 c3 01                add    $0x1,%ebx
1687:       48 83 c5 04             add    $0x4,%rbp
168b:       83 fb 07                cmp    $0x7,%ebx
168e:       74 12                   je     16a2 <phase_2+0x57>
16a0:       eb e2                   jmp    1684 <phase_2+0x39>
  • add $0x1, %ebx:计数器自增(2→3→4→5→6→7)
  • add $0x4, %rbp:%rbp向后移动4字节,指向下一个输入数字的地址
  • 当%ebx等于7时,循环终止(因为只需要检查6个输入数字,计数器到7说明所有数字校验完成)

符合要求的输入示例:1 2 6 24 120 720

函数收尾与栈校验

16a2:       48 8b 44 24 18          mov    0x18(%rsp),%rax
16a7:       64 48 2b 04 25 28 00    sub    %fs:0x28,%rax
16ae:       00 00
16b0:       75 07                   jne    16b9 <phase_2+0x6e>
16b2:       48 83 c4 28             add    $0x28,%rsp
16b6:       5b                      pop    %rbx
16b7:       5d                      pop    %rbp
16b8:       c3                      ret
16b9:       e8 c2 fb ff ff          call   1280 <__stack_chk_fail@plt>
  • 取出栈上的金丝雀值与fs段原始值比较,若不等说明栈被篡改,调用__stack_chk_fail终止程序
  • 恢复栈指针和寄存器,返回调用者

内容的提问来源于stack exchange,提问作者Ryan Kam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 16:05:33