我很难追踪以下二进制炸弹的汇编代码(学校布置的一项作业,其中必须拆除炸弹,该炸弹包含 6 个阶段,每个阶段都有 1 个正确的输入才能进入下一阶段)。有人可以帮助我找到正确的输入并解释如何进行吗?
我目前处于 Phase_3,它有一个 jmp 表,对输入进行了算术运算。我已经确定输入是“%d %d”,它是两个整数。我知道最后 %eax 必须是 316 %edx 必须是 1 才能解决这个问题,但是,我不太清楚我的两个输入正在做什么。
0000000000400f58 <phase_3>:
400f58: 48 83 ec 18 sub $0x18,%rsp
400f5c: 48 8d 4c 24 08 lea 0x8(%rsp),%rcx
400f61: 48 8d 54 24 0c lea 0xc(%rsp),%rdx
400f66: be 1e 27 40 00 mov $0x40271e,%esi
400f6b: b8 00 00 00 00 mov $0x0,%eax
400f70: e8 bb fc ff ff callq 400c30 <__isoc99_sscanf@plt>
400f75: 83 f8 01 cmp $0x1,%eax
400f78: 7e 16 jle 400f90 <phase_3+0x38>
400f7a: 8b 44 24 08 mov 0x8(%rsp),%eax
400f7e: 83 7c 24 0c 07 cmpl $0x7,0xc(%rsp)
400f83: 77 73 ja 400ff8 <phase_3+0xa0>
400f85: 8b 54 24 0c mov 0xc(%rsp),%edx
400f89: ff 24 d5 00 25 40 00 jmpq *0x402500(,%rdx,8)
400f90: e8 3f 07 00 00 callq 4016d4 <explode_bomb>
400f95: eb e3 jmp 400f7a <phase_3+0x22>
400f97: 83 c0 01 add $0x1,%eax
400f9a: ba 10 00 00 00 mov $0x10,%edx
400f9f: eb 05 jmp 400fa6 <phase_3+0x4e>
400fa1: ba 20 00 00 00 mov $0x20,%edx
400fa6: 83 c0 01 add $0x1,%eax
400fa9: d1 fa sar %edx
400fab: 83 c0 01 add $0x1,%eax
400fae: d1 fa sar %edx
400fb0: 83 c0 01 add $0x1,%eax
400fb3: d1 fa sar %edx
400fb5: 83 c0 01 add $0x1,%eax
400fb8: d1 fa sar %edx
400fba: 83 c0 01 add $0x1,%eax
400fbd: d1 fa sar %edx
400fbf: 83 c0 01 add $0x1,%eax
400fc2: d1 fa sar %edx
400fc4: 3d 3c 01 00 00 cmp $0x13c,%eax
400fc9: 75 32 jne 400ffd <phase_3+0xa5>
400fcb: 83 fa 01 cmp $0x1,%edx
400fce: 75 2d jne 400ffd <phase_3+0xa5>
400fd0: 48 83 c4 18 add $0x18,%rsp
400fd4: c3 retq
400fd5: ba 20 00 00 00 mov $0x20,%edx
400fda: eb cf jmp 400fab <phase_3+0x53>
400fdc: ba 20 00 00 00 mov $0x20,%edx
400fe1: eb cd jmp 400fb0 <phase_3+0x58>
400fe3: ba 20 00 00 00 mov $0x20,%edx
400fe8: eb cb jmp 400fb5 <phase_3+0x5d>
400fea: ba 20 00 00 00 mov $0x20,%edx
400fef: eb c9 jmp 400fba <phase_3+0x62>
400ff1: ba 20 00 00 00 mov $0x20,%edx
400ff6: eb c7 jmp 400fbf <phase_3+0x67>
400ff8: e8 d7 06 00 00 callq 4016d4 <explode_bomb>
400ffd: e8 d2 06 00 00 callq 4016d4 <explode_bomb>
401002: eb cc jmp 400fd0 <phase_3+0x78>
401004: ba 20 00 00 00 mov $0x20,%edx
401009: eb b9 jmp 400fc4 <phase_3+0x6c>
跳转表。 这是一个非 PIE 可执行文件,因此这些是绝对地址,即使在 GDB 之外运行,也不会在运行中随机化
.text
地址。
(gdb) x/8gx0x402500
0x402500: 0x0000000000400fe3 0x0000000000400fd5
0x402510: 0x0000000000400ff1 0x0000000000400f97
0x402520: 0x0000000000400fdc 0x0000000000400fa1
0x402530: 0x0000000000401004 0x0000000000400fea
它对
EDX <= 7u
的第一个输入进行范围检查,然后使用它来索引跳转表,因此您有 8 个可能的位置供 switch
移动。
由于您已经在使用 GDB,因此您只需运行它并单步执行即可查看某些示例输入会发生什么情况。
许多开关
case
跳转到 edx >>= 1
(sar
= 算术右移)和 eax += 1
(add
) 的序列,最后要求 EDX=1 和 EAX=0x13c,否则会爆炸.
如果您在反汇编中文本搜索跳转表中的地址,您将看到 EDX 值可以跳转的 8 个可能位置,以及那里的代码的作用。 我使用鼠标复制/粘贴地址(不包括前导零或 0x),按 control-f(或在文本 konsole 终端中按 ctrl-shift-f),如果搜索还没有,则按 ctrl-v接受我的选择。 反汇编标记地址如
400fab:
,这就是为什么我必须省略前导零才能获得文本匹配。
我知道最后 %eax 必须是 316 %edx 必须是 1 才能解决这个问题,但是,我不太清楚我的两个输入正在做什么。
EDX=1 跳转到
400fd5
,其中 mov
设置 EDX=0x20(第一对之后有 1<<5) and jumps int the sequence of sar
/add
指令,因此运行 5 个 sar %edx
指令,将 1<<5
变成 1
) .
其他 EDX 值跳转到具有相同 EDX=0x20 的不同点,因此最终不会导致 EDX=1。