先打断点,运行chmod +x *修改权限成可执行程序,disas把机器码转化为反汇编代码,然后查看函数汇编代码
Dump of assembler code for function phase_1:
0x0000000000001264 <+0>: sub $0x8,%rsp
0x0000000000001268 <+4>: lea 0x1841(%rip),%rsi # 0x2ab0
0x000000000000126f <+11>: callq 0x1774 <strings_not_equal>
0x0000000000001274 <+16>: test %eax,%eax
0x0000000000001276 <+18>: jne 0x127d <phase_1+25>
0x0000000000001278 <+20>: add $0x8,%rsp
0x000000000000127c <+24>: retq
0x000000000000127d <+25>: callq 0x1a78 <explode_bomb>
0x0000000000001282 <+30>: jmp 0x1278 <phase_1+20>
End of assembler dump.
解释汇编代码
- **`sub $0x8,%rsp`**:
- 减少栈指针,分配 8 字节的栈空间。
- **`lea 0x1841(%rip),%rsi`**:
- 计算一个内存地址,并将其存储在 `rsi` 寄存器中。这个地址是一个字符串常量的地址,地址为 `0x2ab0`。
- **`callq 0x1774 <strings_not_equal>`**:
- 调用 `strings_not_equal` 函数,比较两个字符串是否相等。一个字符串是用户输入的,另一个字符串是 `rsi` 寄存器中存储的字符串常量。
- **`test %eax,%eax`**:
- 测试 `eax` 寄存器的值。如果 `eax` 为 0,表示字符串相等;否则,表示字符串不相等。
- **`jne 0x127d <phase_1+25>`**:
- 如果字符串不相等,跳转到 `0x127d`,调用 `explode_bomb` 函数。
- **`add $0x8,%rsp`**:
- 恢复栈指针。
- **`retq`**:
- 返回调用者。
- **`callq 0x1a78 <explode_bomb>`**:
- 调用 `explode_bomb` 函数,表示输入错误,炸弹爆炸。
- **`jmp 0x1278 <phase_1+20>`**:
- 跳转到 `0x1278`,恢复栈指针并返回。
找到rip的地址加上偏移的0x1842即可
然后查找这个地址附件的字符串
跟第一关一样的方法
还是先解析反汇编代码
0x0000000000001284 <+0>: push %rbp
0x0000000000001285 <+1>: push %rbx
0x0000000000001286 <+2>: sub $0x28,%rsp
0x000000000000128a <+6>: mov %fs:0x28,%rax
0x0000000000001293 <+15>: mov %rax,0x18(%rsp)
0x0000000000001298 <+20>: xor %eax,%eax
0x000000000000129a <+22>: mov %rsp,%rsi
0x000000000000129d <+25>: callq 0x1ab4 <read_six_numbers>
0x00000000000012a2 <+30>: cmpl $0x0,(%rsp)
0x00000000000012a6 <+34>: jne 0x12af <phase_2+43>
0x00000000000012a8 <+36>: cmpl $0x1,0x4(%rsp)
0x00000000000012ad <+41>: je 0x12b4 <phase_2+48>
0x00000000000012af <+43>: callq 0x1a78 <explode_bomb>
0x00000000000012b4 <+48>: mov %rsp,%rbx
0x00000000000012b7 <+51>: lea 0x10(%rbx),%rbp
0x00000000000012bb <+55>: jmp 0x12c6 <phase_2+66>
0x00000000000012bd <+57>: add $0x4,%rbx
0x00000000000012c1 <+61>: cmp %rbp,%rbx
0x00000000000012c4 <+64>: je 0x12d7 <phase_2+83>
0x00000000000012c6 <+66>: mov 0x4(%rbx),%eax
0x00000000000012c9 <+69>: add (%rbx),%eax
0x00000000000012cb <+71>: cmp %eax,0x8(%rbx)
0x00000000000012ce <+74>: je 0x12bd <phase_2+57>
0x00000000000012d0 <+76>: callq 0x1a78 <explode_bomb>
0x00000000000012d5 <+81>: jmp 0x12bd <phase_2+57>
0x00000000000012d7 <+83>: mov 0x18(%rsp),%rax
0x00000000000012dc <+88>: xor %fs:0x28,%rax
0x00000000000012e5 <+97>: jne 0x12ee <phase_2+106>
0x00000000000012e7 <+99>: add $0x28,%rsp
0x00000000000012eb <+103>: pop %rbx
0x00000000000012ec <+104>: pop %rbp
push %rbp
和push %rbx
:保存rbp
和rbx
寄存器的值。sub $0x28,%rsp
:为局部变量分配 40 字节的栈空间。mov %fs:0x28,%rax
:从fs
段寄存器中读取栈保护值。mov %rax,0x18(%rsp)
:将栈保护值保存到栈中。xor %eax,%eax
:将eax
寄存器清零。mov %rsp,%rsi
:将栈指针传递给rsi
,作为read_six_numbers
函数的参数。callq 0x1ab4 <read_six_numbers>
:调用read_six_numbers
函数,读取六个数字并存储在栈中。cmpl $0x0,(%rsp)
:比较第一个数字是否为 0。jne 0x12af <phase_2+43>
:如果第一个数字不为 0,跳转到0x12af
,调用explode_bomb
。cmpl $0x1,0x4(%rsp)
:比较第二个数字是否为 1。je 0x12b4 <phase_2+48>
:如果第二个数字为 1,跳转到0x12b4
。callq 0x1a78 <explode_bomb>
:如果条件不满足,调用explode_bomb
。mov %rsp,%rbx
:将栈指针保存到rbx
。lea 0x10(%rbx),%rbp
:计算rbp
的值,指向第六个数字。jmp 0x12c6 <phase_2+66>
:跳转到循环开始处。add $0x4,%rbx
:将rbx
加 4,指向下一个数字。cmp %rbp,%rbx
:比较rbx
和rbp
,检查是否到达第六个数字。je 0x12d7 <phase_2+83>
:如果到达第六个数字,跳转到0x12d7
。mov 0x4(%rbx),%eax
:将下一个数字保存到eax
。add (%rbx),%eax
:将当前数字加到eax
。cmp %eax,0x8(%rbx)
:比较eax
和下一个数字。je 0x12bd <phase_2+57>
:如果相等,跳转到0x12bd
,继续循环。callq 0x1a78 <explode_bomb>
:如果不相等,调用explode_bomb
。mov 0x18(%rsp),%rax
:从栈中恢复栈保护值。xor %fs:0x28,%rax
:检查栈保护值是否被修改。jne 0x12ee <phase_2+106>
:如果栈保护值被修改,跳转到0x12ee
。add $0x28,%rsp
:恢复栈指针。pop %rbx
和pop %rbp
:恢复rbx
和rbp
寄存器的值。
可以看出来是反汇编代码是一段斐波那契数列