第三弹啦!继续上代码!
08048ea1<phase_3>:
8048ea1: 55 push %ebp
8048ea2: 89e5 mov %esp,%ebp
8048ea4: 83ec 28 sub $0x28,%esp //开辟了10个地址
8048ea7: 8d45 f0 lea -0x10(%ebp),%eax
8048eaa: 89 44 24 0c mov %eax,0xc(%esp)
8048eae: 8d45 f4 lea -0xc(%ebp),%eax //将第一个参数给eax
8048eb1: 8944 24 08 mov %eax,0x8(%esp)
8048eb5: c744 24 04 3e a2 04 movl $0x804a23e,0x4(%esp) //$0x804a23e应该很重要
8048ebc: 08
8048ebd: 8b45 08 mov 0x8(%ebp),%eax
8048ec0: 8904 24 mov %eax,(%esp)
8048ec3: e878 f9 ff ff call 8048840<__isoc99_sscanf@plt>
8048ec8: 83f8 01 cmp $0x1,%eax //eax大于1就不bomb
8048ecb: 7f05 jg 8048ed2<phase_3+0x31>
8048ecd: e8ff 01 00 00 call 80490d1<explode_bomb>
8048ed2: 837d f4 07 cmpl $0x7,-0xc(%ebp) //-0xc(%ebp)大于7就bomb -0xc(%ebp)是第一个参数
8048ed6: 776b ja 8048f43<phase_3+0xa2>
8048ed8: 8b45 f4 mov -0xc(%ebp),%eax //eax变成了我输入的第一个数
8048edb: ff24 85 a0 a1 04 08 jmp *0x804a1a0(,%eax,4) //以0x804a1a0(,%eax,4)作为读地址,相当于switch语句,eax值改变,就jump到不同位置
//这里比如输入0,就jump到 8048f12,得到147;如果输入1,就jump到8048f19,得到-641;我测试了两个都可以通过。
8048ee2: b800 00 00 00 mov $0x0,%eax
8048ee7: eb53 jmp 8048f3c<phase_3+0x9b>
8048ee9: b800 00 00 00 mov $0x0,%eax
8048eee: 6690 xchg %ax,%ax //xchg是交换,不过好像在这里没什么用啊
8048ef0: eb45 jmp 8048f37<phase_3+0x96>
8048ef2: b800 00 00 00 mov $0x0,%eax
8048ef7: eb39 jmp 8048f32 <phase_3+0x91>
8048ef9: b800 00 00 00 mov $0x0,%eax
8048efe: 6690 xchg %ax,%ax
8048f00: eb2b jmp 8048f2d<phase_3+0x8c>
8048f02: b800 00 00 00 mov $0x0,%eax
8048f07: eb1f jmp 8048f28<phase_3+0x87>
8048f09: b800 00 00 00 mov $0x0,%eax
8048f0e: 6690 xchg %ax,%ax
8048f10: eb11 jmp 8048f23<phase_3+0x82>
8048f12: b814 03 00 00 mov $0x314,%eax//当输入为0时 就会跳转到这里。往下执行
8048f17: eb05 jmp 8048f1e<phase_3+0x7d>
8048f19: b800 00 00 00 mov $0x0,%eax
8048f1e: 2d5a 03 00 00 sub $0x35a,%eax
8048f23: 05ef 02 00 00 add $0x2ef,%eax
8048f28: 2d16 02 00 00 sub $0x216,%eax
8048f2d: 0516 02 00 00 add $0x216,%eax
8048f32: 2d16 02 00 00 sub $0x216,%eax
8048f37: 0516 02 00 00 add $0x216,%eax
8048f3c: 2d16 02 00 00 sub $0x216,%eax
8048f41: eb0a jmp 8048f4d <phase_3+0xac>
8048f43: e889 01 00 00 call 80490d1<explode_bomb>
8048f48: b800 00 00 00 mov $0x0,%eax
8048f4d: 837d f4 05 cmpl $0x5,-0xc(%ebp)
8048f51: 7f05 jg8048f58<phase_3+0xb7> //-0xc(%ebp)比5大,就bomb
8048f53: 3b45 f0 cmp -0x10(%ebp),%eax
8048f56: 74 05 je 8048f5d <phase_3+0xbc> //%eax和-0x10(%ebp)一样,就不会bomb
8048f58: e874 01 00 00 call 80490d1<explode_bomb>
8048f5d: c9 leave
8048f5e: 6690 xchg %ax,%ax
8048f60: c3 ret
分析分析吧:
粗粗看一下代码,应该会留意到这里有几个点:
movl $0x804a23e,0x4(%esp) //$0x804a23e应该很重要,有了第一关的经验,我就用gdb查看了0x804a23e的内容,发现是 %d %d,结合call 8048840 <__isoc99_sscanf@plt>指令,就可以大概确定这是要输入两个整形的节奏。下一条指令cmp $0x1,%eax //eax大于1就不bomb,更加确定了这一点。
cmpl $0x7,-0xc(%ebp) //-0xc(%ebp)大于7就bomb -0xc(%ebp)是第一个参数。cmpl $0x5,-0xc(%ebp) jg8048f58<phase_3+0xb7> //-0xc(%ebp)比5大,就bomb。这两条指令都是确定第一个参数的范围的。
最关键的代码来了:
mov -0xc(%ebp),%eax //eax变成了我输入的第一个数
jmp *0x804a1a0(,%eax,4)//以*0x804a1a0(,%eax,4)作为读地址,相当于switch语句,eax值改变,就jump到不同位置。到这里我就可以确定这个phase3想干嘛了,大概就是像c程序中的Switch一样,输入不同的参数,匹配到不同的代码段执行相应内容。(一开始我找不到代码上0x804a1a的地址,后来发现前面有个*,原来是读内容啊,所以我就又用gdb x/xw 0x804a1a命令尝试了一下,发现内容0x8048f12,所以是从0x8048f12开始读,看下图:)
je 8048f5d <phase_3+0xbc>//%eax和-0x10(%ebp)一样,就不会bomb,所以我们输入的第二个参数要等于计算出的那个值。
还是试一下吧,比如我输入的第一个参数为1,这样就会跳到0x8048f12+0*4=0x8048f12;然后顺序执行下面的语句,是一系列的加减运算,用机器自带的程序员计算器就ok了,0x314-0x35a+0x2ef-0x216+0x216-0x216+0x216-0x216=147,看截图:
哈哈,又成功过了一关。
这说明我对代码的理解是正确的,那么我就再来试一下当第一个参数为1的时候,经过我的计算应该是-641,来看一下:
恩!又对了,说明不止一个答案,我就不一一试了。还有好多弹等着我拆呢!