首先来看phase_3的代码
0000000000400f43 <phase_3>:
400f43: 48 83 ec 18 sub $0x18,%rsp
400f47: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
400f4c: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
400f51: be cf 25 40 00 mov $0x4025cf,%esi
400f56: b8 00 00 00 00 mov $0x0,%eax
400f5b: e8 90 fc ff ff callq 400bf0 <__isoc99_sscanf@plt>
400f60: 83 f8 01 cmp $0x1,%eax
400f63: 7f 05 jg 400f6a <phase_3+0x27>
400f65: e8 d0 04 00 00 callq 40143a <explode_bomb>
400f6a: 83 7c 24 08 07 cmpl $0x7,0x8(%rsp)
400f6f: 77 3c ja 400fad <phase_3+0x6a>
400f71: 8b 44 24 08 mov 0x8(%rsp),%eax
400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)
400f7c: b8 cf 00 00 00 mov $0xcf,%eax
400f81: eb 3b jmp 400fbe <phase_3+0x7b>
400f83: b8 c3 02 00 00 mov $0x2c3,%eax
400f88: eb 34 jmp 400fbe <phase_3+0x7b>
400f8a: b8 00 01 00 00 mov $0x100,%eax
400f8f: eb 2d jmp 400fbe <phase_3+0x7b>
400f91: b8 85 01 00 00 mov $0x185,%eax
400f96: eb 26 jmp 400fbe <phase_3+0x7b>
400f98: b8 ce 00 00 00 mov $0xce,%eax
400f9d: eb 1f jmp 400fbe <phase_3+0x7b>
400f9f: b8 aa 02 00 00 mov $0x2aa,%eax
400fa4: eb 18 jmp 400fbe <phase_3+0x7b>
400fa6: b8 47 01 00 00 mov $0x147,%eax
400fab: eb 11 jmp 400fbe <phase_3+0x7b>
400fad: e8 88 04 00 00 callq 40143a <explode_bomb>
400fb2: b8 00 00 00 00 mov $0x0,%eax
400fb7: eb 05 jmp 400fbe <phase_3+0x7b>
400fb9: b8 37 01 00 00 mov $0x137,%eax
400fbe: 3b 44 24 0c cmp 0xc(%rsp),%eax
400fc2: 74 05 je 400fc9 <phase_3+0x86>
400fc4: e8 71 04 00 00 callq 40143a <explode_bomb>
400fc9: 48 83 c4 18 add $0x18,%rsp
400fcd: c3 retq
首先rcx被赋予rsp+12,rdx被赋予rsp+8的值,rsi被赋予0x4025cf,rax=0
调用sscanf,这个函数在phase_2中介绍过,其第一个参数是一个指针,也就是rdi,它指向我们在main函数中输入的字符串所在地址
然后第二个参数rsi被赋予了0x4025cf,x/s读取这个地址发现那里是"%d %d",说明要读取两个整型数,它们被存入rdx、rcx所指向的地址
在400f6a得知第一个数不能超过7,否则直接触雷,满足条件则将第一个数赋给rax
有意思的事在400f75,这是一个跳转命令,它要跳转到的地址与rax有关:目的地址是一个数,这个数存在一个地方,那个地方的地址是由基础地址0x402470加上8*rax得到的。
用x/a读取这个基础地址,发现那里正存着一个数字0x400f7c,我们发现在这个地址处rax被赋予了值0xcf,然后跳转400fbe将其与rcx比较,也就是我们输入的第二个数比较,
如果相等就能跳过最后一个炸弹通过这个phase,很显然我们如果输入第一个数0的话,第二个数就应该是0xcf了
考虑到第一个数目前只有小于等于7的限制,我们不妨用x/8a读取那个基础地址,这样会得到:
0x402470: 0x400f7c <phase_3+57> 0x400fb9 <phase_3+118>
0x402480: 0x400f83 <phase_3+64> 0x400f8a <phase_3+71>
0x402490: 0x400f91 <phase_3+78> 0x400f98 <phase_3+85>
0x4024a0: 0x400f9f <phase_3+92> 0x400fa6 <phase_3+99>
在400f75这个命令处,我们输入的第一个数rax在0到7上,每个数加上那个基础地址后都得到某条命令语句的地址,这个地址都对应了phase_3中的一条给rax赋值的命令,然后均跳转到400fbe处将其与第二个数对比
看到这里就能明白,这其实是一个switch结构,我们输入的第一个数决定了第二个数应当是多少。把每个case都试试会得到下面这张表(十进制):
0 207
1 311
2 707
3 256
4 389
5 206
6 682
7 327
输入上述任意一个组合都能通过这个phase