在解释之前先附上一段代码:
0000000000400e8c <phase_2>: 400e8c: 48 89 5c 24 e0 mov %rbx,-0x20(%rsp) 400e91: 48 89 6c 24 e8 mov %rbp,-0x18(%rsp) 400e96: 4c 89 64 24 f0 mov %r12,-0x10(%rsp) 400e9b: 4c 89 6c 24 f8 mov %r13,-0x8(%rsp) 400ea0: 48 83 ec 48 sub $0x48,%rsp 400ea4: 48 89 e6 mov %rsp,%rsi 400ea7: e8 97 08 00 00 callq 401743 <read_six_numbers> 400eac: 48 89 e5 mov %rsp,%rbp 400eaf: 4c 8d 6c 24 0c lea 0xc(%rsp),%r13 400eb4: 41 bc 00 00 00 00 mov $0x0,%r12d 400eba: 48 89 eb mov %rbp,%rbx 400ebd: 8b 45 0c mov 0xc(%rbp),%eax 400ec0: 39 45 00 cmp %eax,0x0(%rbp) 400ec3: 74 05 je 400eca <phase_2+0x3e> 400ec5: e8 73 07 00 00 callq 40163d <explode_bomb> 400eca: 44 03 23 add (%rbx),%r12d 400ecd: 48 83 c5 04 add $0x4,%rbp 400ed1: 4c 39 ed cmp %r13,%rbp 400ed4: 75 e4 jne 400eba <phase_2+0x2e> 400ed6: 45 85 e4 test %r12d,%r12d 400ed9: 75 05 jne 400ee0 <phase_2+0x54> 400edb: e8 5d 07 00 00 callq 40163d <explode_bomb> 400ee0: 48 8b 5c 24 28 mov 0x28(%rsp),%rbx 400ee5: 48 8b 6c 24 30 mov 0x30(%rsp),%rbp 400eea: 4c 8b 64 24 38 mov 0x38(%rsp),%r12 400eef: 4c 8b 6c 24 40 mov 0x40(%rsp),%r13 400ef4: 48 83 c4 48 add $0x48,%rsp 400ef8: c3 retq
phase_2 会调用 read_six_numbers,所以我们要输入的应该是6个数字。
这里很明显,读入的6个数字被存放在从%rsp指向的地址开始向上的位置。
这段汇编代码是让我们比较
(1) 0x0(%rbp) 与 0xc(%rbp)
(2) 0x4(%rbp) 与 0x10(%rbp)
(3) 0x8(%rbp) 与 0x14(%rbp)
的内容,一旦有一个不符就引爆炸弹。
(1)
mov 0xc(%rbp),%eax cmp %eax,0x0(%rbp) je 400eca <phase_2+0x3e> callq 40163d <explode_bomb>
这里用 mov 将 0xc(%rbp) 存入到 %eax 中,通过 cmp 比较 0x0(%rbp) 与 0xc(%rbp) ,je表示如果被比较的两项(进行减操作)得到的结果是0,即 0x0(%rbp) 与 0xc(%rbp) 的值相等,就跳转到0x400eca行,否则跳到40163d <explode_bomb>执行爆破!
(2,3)循环
mov $0x0,%r12d ... ... add (%rbx),%r12d add $0x4,%rbp cmp %r13,%rbp jne 400eba <phase_2+0x2e>
(3)同时还会检测的和是否为0,为0则引爆炸弹。
test %r12d,%r12d jne 400ee0 <phase_2+0x54> callq 40163d <explode_bomb>
0x0(%rbp) + 0x4(%rbp) + 0x8(%rbp)
那么上面这些与我们输入的数字又有什么关系呢?只要在gdb中打印出来看看就行了。
在这里,我输入1 4 2 5 3 6
可见这里的六个数字表示的就是我们输入进去的数字,所以我们只要保证后三位与前三位相同同时前三位之和不为0就没问题了。
然后再让我们看看与之相关联的函数
0000000000401743 <read_six_numbers>: 401743: 48 83 ec 18 sub $0x18,%rsp 401747: 48 89 f2 mov %rsi,%rdx 40174a: 48 8d 4e 04 lea 0x4(%rsi),%rcx 40174e: 48 8d 46 14 lea 0x14(%rsi),%rax 401752: 48 89 44 24 08 mov %rax,0x8(%rsp) 401757: 48 8d 46 10 lea 0x10(%rsi),%rax 40175b: 48 89 04 24 mov %rax,(%rsp) 40175f: 4c 8d 4e 0c lea 0xc(%rsi),%r9 401763: 4c 8d 46 08 lea 0x8(%rsi),%r8 401767: be b2 1e 40 00 mov $0x401eb2,%esi 40176c: b8 00 00 00 00 mov $0x0,%eax 401771: e8 3a f3 ff ff callq 400ab0 <__isoc99_sscanf@plt> 401776: 83 f8 05 cmp $0x5,%eax 401779: 7f 05 jg 401780 <read_six_numbers+0x3d> 40177b: e8 bd fe ff ff callq 40163d <explode_bomb> 401780: 48 83 c4 18 add $0x18,%rsp 401784: c3 retq
可以看到,我们输入的6个数是通过这里调用的0x400ab0 <__isoc99_sscanf@plt>函数输入的。
0000000000400ab0 <__isoc99_sscanf@plt>: 400ab0: ff 25 02 1a 20 00 jmpq *0x201a02(%rip) # 6024b8 <__isoc99_sscanf@GLIBC_2.7> 400ab6: 68 04 00 00 00 pushq $0x4 400abb: e9 a0 ff ff ff jmpq 400a60 <.plt>400ab0 <__isoc99_sscanf@plt> 指明了 sscanf 是标准库函数,经查文档,得到该函数的 signature 为 int sscanf(const char *buffer,const char *format,[argument ]...);