08048bb8 <phase_3>:
8048bb8: 55 push %ebp
8048bb9: 89 e5 mov %esp,%ebp 开辟栈帧
8048bbb: 83 ec 18 sub $0x18,%esp 分配0x18即24个字节的空间
8048bbe: 65 a1 14 00 00 00 mov %gs:0x14,%eax 堆栈金丝雀
8048bc4: 89 45 f4 mov %eax,-0xc(%ebp)
8048bc7: 31 c0 xor %eax,%eax
8048bc9: 8d 45 f0 lea -0x10(%ebp),%eax
8048bcc: 50 push %eax ebp-16位置的数传给eax, 并且压栈
8048bcd: 8d 45 ec lea -0x14(%ebp),%eax
8048bd0: 50 push %eax 同上
8048bd1: 68 f3 a1 04 08 push $0x804a1f3 可以查出输入输入两个数
8048bd6: ff 75 08 pushl 0x8(%ebp) 第一个参数压栈
8048bd9: e8 32 fc ff ff call 8048810 <__isoc99_sscanf@plt>
8048bde: 83 c4 10 add $0x10,%esp esp加16,开辟16个字节
8048be1: 83 f8 01 cmp $0x1,%eax 比较eax和1的大小
8048be4: 7f 05 jg 8048beb <phase_3+0x33> eax大于1就不爆炸
8048be6: e8 15 05 00 00 call 8049100 <explode_bomb>
8048beb: 83 7d ec 07 cmpl $0x7,-0x14(%ebp) -0x14(%ebp)大于7就爆炸,这里-0x14(%ebp)是第一个参数
8048bef: 77 65 ja 8048c56 <phase_3+0x9e>
8048bf1: 8b 45 ec mov -0x14(%ebp),%eax 第一个参数给eax
8048bf4: ff 24 85 b4 a0 04 08 jmp *0x804a0b4(,%eax,4) 无条件跳转,跳转的位置是*(0x804a0b4 + eax * 4),这可以通过p/x查到跳转的位置,这个位置和输入的第一个参数有关,我输入的是2,可以查到跳转到0x8048c0e处,先加后查找,否则会找不到
8048bfb: b8 34 00 00 00 mov $0x34,%eax eax赋值为0x34
8048c00: eb 05 jmp 8048c07 <phase_3+0x4f> 从最上面跳转之后,只用赋一次eax初值,后面遇到eax赋值的语句就跳过,只用做计算
8048c02: b8 00 00 00 00 mov $0x0,%eax
8048c07: 2d ad 01 00 00 sub $0x1ad,%eax
8048c0c: eb 05 jmp 8048c13 <phase_3+0x5b>
8048c0e: b8 00 00 00 00 mov $0x0,%eax eax = 0x0
8048c13: 05 6c 03 00 00 add $0x36c,%eax eax += 0x36c
8048c18: eb 05 jmp 8048c1f <phase_3+0x67>
8048c1a: b8 00 00 00 00 mov $0x0,%eax
8048c1f: 2d f1 00 00 00 sub $0xf1,%eax eax -= 0xf1
8048c24: eb 05 jmp 8048c2b <phase_3+0x73>
8048c26: b8 00 00 00 00 mov $0x0,%eax
8048c2b: 05 f1 00 00 00 add $0xf1,%eax eax += 0xf1
8048c30: eb 05 jmp 8048c37 <phase_3+0x7f>
8048c32: b8 00 00 00 00 mov $0x0,%eax
8048c37: 2d f1 00 00 00 sub $0xf1,%eax eax -= 0xf1
8048c3c: eb 05 jmp 8048c43 <phase_3+0x8b>
8048c3e: b8 00 00 00 00 mov $0x0,%eax
8048c43: 05 f1 00 00 00 add $0xf1,%eax eax += 0xf1
8048c48: eb 05 jmp 8048c4f <phase_3+0x97>
8048c4a: b8 00 00 00 00 mov $0x0,%eax
8048c4f: 2d f1 00 00 00 sub $0xf1,%eax eax -= 0xf1
8048c54: eb 0a jmp 8048c60 <phase_3+0xa8>
8048c56: e8 a5 04 00 00 call 8049100 <explode_bomb>
8048c5b: b8 00 00 00 00 mov $0x0,%eax
8048c60: 83 7d ec 05 cmpl $0x5,-0x14(%ebp)
8048c64: 7f 05 jg 8048c6b <phase_3+0xb3>第一个参数大于5爆炸
8048c66: 3b 45 f0 cmp -0x10(%ebp),%eax %eax和-0x10(%ebp)一样,就不会爆炸,-0x10(%ebp)是第二个参数,所以第二个参数需要等于eax的值,即计算后的结果
8048c69: 74 05 je 8048c70 <phase_3+0xb8>
8048c6b: e8 90 04 00 00 call 8049100 <explode_bomb>
8048c70: 8b 45 f4 mov -0xc(%ebp),%eax
8048c73: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048c7a: 74 05 je 8048c81 <phase_3+0xc9>
8048c7c: e8 0f fb ff ff call 8048790 <__stack_chk_fail@plt>
8048c81: c9 leave
8048c82: c3 ret
综合分析:
- 首先,整个函数的输入是两个数字
- 通过爆炸,可以判断第一个参数的范围,在1到7之间(后面又作限制在1到5之间)
- jmp *0x804a0b4(,%eax,4),通过此语句完成跳转,eax是输入的第一个参数,*0x804a0b4(,%eax,4)作用类似于上课讲的switch case语句的那个表的作用,控制跳转的位置,而且是一个没有break的switch case语句,所以从一个地址执行,一直到最后。输入不同的数会有不同的答案
- 输入的数为2,结果为0x0 + 0x36c - 0xf1 + 0xf1 - 0xf1 + 0xf1 - 0xf1 = 635(十进制),所以第二个参数是635
结果测试: