tip:每个人的实验都不一样,网上找了很多都讲得很学术,感觉关键地方就跳过了,总之听不懂走了很多弯路。纯小白边做边学很痛苦,慢慢摸出来的答案,故按自己的方法来再巩固一次。
如果你也想动手试试,我把代码链接附在这里:
前置:
1.使用 objdump 反汇编 bomb 得到汇编语言代码
● $ objdump –d bomb > asm.txt
“>”:重定向,将反汇编出来的源程序输出至 asm.txt 文件中
2.gdb bomb//用gdb打开
开始:
1. phase_1
08048b30 <phase_1>:
8048b30: 55 push %ebp
8048b31: 89 e5 mov %esp,%ebp
8048b33: 83 ec 10 sub $0x10,%esp
8048b36: 68 64 a0 04 08 push $0x804a064//查看此处内容
8048b3b: ff 75 08 push 0x8(%ebp)
8048b3e: e8 b9 04 00 00 call 8048ffc <strings_not_equal>//此函数检查字符串
8048b43: 83 c4 10 add $0x10,%esp
8048b46: 85 c0 test %eax,%eax//等价于检查是否为0
8048b48: 74 05 je 8048b4f <phase_1+0x1f>//等于就跳转到8048b4f
8048b4a: e8 b0 05 00 00 call 80490ff <explode_bomb>//不跳转就爆炸
8048b4f: c9 leave
8048b50: c3 ret
1.如何查看?
1.(gdb)x/s 0x804a217(意为查看0x804a217处的值);
x/100s 0x804a217(意为查看从0x804a217往后一百个地址的值)
2. phase_2
08048b51 <phase_2>:
8048b51: 55 push %ebp//新建栈底
8048b52: 89 e5 mov %esp,%ebp//esp是栈顶指针
8048b54: 56 push %esi
8048b55: 53 push %ebx
8048b56: 83 ec 28 sub $0x28,%esp//开栈
8048b59: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048b5f: 89 45 f4 mov %eax,-0xc(%ebp)
8048b62: 31 c0 xor %eax,%eax
8048b64: 8d 45 dc lea -0x24(%ebp),%eax
8048b67: 50 push %eax
8048b68: ff 75 08 push 0x8(%ebp)
8048b6b: e8 b7 05 00 00 call 8049127 <read_six_numbers>//要求输入六个数字
8048b70: 83 c4 10 add $0x10,%esp
8048b73: 83 7d dc 01 cmpl $0x1,-0x24(%ebp)
//第一个数是1(紧挨着栈顶的是参数,越早输入的参数离栈底越远,一共有六个参数所以第一个在(4*6))
8048b77: 74 05 je 8048b7e <phase_2+0x2d>
8048b79: e8 81 05 00 00 call 80490ff <explode_bomb>
8048b7e: 8d 5d dc lea -0x24(%ebp),%ebx
8048b81: 8d 75 f0 lea -0x10(%ebp),%esi
8048b84: 8b 03 mov (%ebx),%eax//eax获取前数值
8048b86: 01 c0 add %eax,%eax//eax*=2
8048b88: 39 43 04 cmp %eax,0x4(%ebx)
// 0x4(%ebx)意为紧邻ebx的下一位,这三句的意思是比较下一位是否是上一位的两倍
8048b8b: 74 05 je 8048b92 <phase_2+0x41>
8048b8d: e8 6d 05 00 00 call 80490ff <explode_bomb>
8048b92: 83 c3 04 add $0x4,%ebx//移到下一位
8048b95: 39 f3 cmp %esi,%ebx//比较是否已经六个数了
8048b97: 75 eb jne 8048b84 <phase_2+0x33>//不等于就继续回去
8048b99: 8b 45 f4 mov -0xc(%ebp),%eax
8048b9c: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048ba3: 74 05 je 8048baa <phase_2+0x59>
8048ba5: e8 e6 fb ff ff call 8048790 <__stack_chk_fail@plt>
8048baa: 8d 65 f8 lea -0x8(%ebp),%esp
8048bad: 5b pop %ebx
8048bae: 5e pop %esi
8048baf: 5d pop %ebp
8048bb0: c3 ret
结果为:1 2 4 8 16 32
1. phase_3
08048bb1 <phase_3>:
8048bb1: 55 push %ebp
8048bb2: 89 e5 mov %esp,%ebp
8048bb4: 83 ec 18 sub $0x18,%esp
8048bb7: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048bbd: 89 45 f4 mov %eax,-0xc(%ebp)
8048bc0: 31 c0 xor %eax,%eax
8048bc2: 8d 45 f0 lea -0x10(%ebp),%eax//第二个参数
8048bc5: 50 push %eax
8048bc6: 8d 45 ec lea -0x14(%ebp),%eax//第一个参数
8048bc9: 50 push %eax
8048bca: 68 17 a2 04 08 push $0x804a217//查看这里的值,%d %d
8048bcf: ff 75 08 push 0x8(%ebp)
8048bd2: e8 39 fc ff ff call 8048810 <__isoc99_sscanf@plt>//输入两数
8048bd7: 83 c4 10 add $0x10,%esp
8048bda: 83 f8 01 cmp $0x1,%eax//检查函数返回值(即输入是否正确
8048bdd: 7f 05 jg 8048be4 <phase_3+0x33>//有符号大于则跳转
8048bdf: e8 1b 05 00 00 call 80490ff <explode_bomb>
8048be4: 83 7d ec 07 cmpl $0x7,-0x14(%ebp)
8048be8: 77 65 ja 8048c4f <phase_3+0x9e>//无符号大于则跳转
8048bea: 8b 45 ec mov -0x14(%ebp),%eax//eax等于第一个参数
8048bed: ff 24 85 80 a0 04 08 jmp *0x804a080(,%eax,4)
//无条件跳转,到804a080+4*eax,我输入零,用p/x 查看地址处值
8048bf4: b8 e9 00 00 00 mov $0xe9,%eax//跳转到此处
8048bf9: eb 05 jmp 8048c00 <phase_3+0x4f>
//无条件跳转,接下来就是计算
8048bfb: b8 00 00 00 00 mov $0x0,%eax
8048c00: 2d 9c 00 00 00 sub $0x9c,%eax
8048c05: eb 05 jmp 8048c0c <phase_3+0x5b>
8048c07: b8 00 00 00 00 mov $0x0,%eax
8048c0c: 05 a6 02 00 00 add $0x2a6,%eax
8048c11: eb 05 jmp 8048c18 <phase_3+0x67>
8048c13: b8 00 00 00 00 mov $0x0,%eax
8048c18: 2d 56 02 00 00 sub $0x256,%eax
8048c1d: eb 05 jmp 8048c24 <phase_3+0x73>
8048c1f: b8 00 00 00 00 mov $0x0,%eax
8048c24: 05 56 02 00 00 add $0x256,%eax
8048c29: eb 05 jmp 8048c30 <phase_3+0x7f>
8048c2b: b8 00 00 00 00 mov $0x0,%eax
8048c30: 2d 56 02 00 00 sub $0x256,%eax
8048c35: eb 05 jmp 8048c3c <phase_3+0x8b>
8048c37: b8 00 00 00 00 mov $0x0,%eax
8048c3c: 05 56 02 00 00 add $0x256,%eax
8048c41: eb 05 jmp 8048c48 <phase_3+0x97>
8048c43: b8 00 00 00 00 mov $0x0,%eax
8048c48: 2d 56 02 00 00 sub $0x256,%eax
8048c4d: eb 0a jmp 8048c59 <phase_3+0xa8>
8048c4f: e8 ab 04 00 00 call 80490ff <explode_bomb>
8048c54: b8 00 00 00 00 mov $0x0,%eax
8048c59: 83 7d ec 05 cmpl $0x5,-0x14(%ebp)//第一个数是否大于五
8048c5d: 7f 05 jg 8048c64 <phase_3+0xb3>//大于就爆炸
8048c5f: 3b 45 f0 cmp -0x10(%ebp),%eax//第二个数等于计算出的eax
8048c62: 74 05 je 8048c69 <phase_3+0xb8>
8048c64: e8 96 04 00 00 call 80490ff <explode_bomb>
8048c69: 8b 45 f4 mov -0xc(%ebp),%eax
8048c6c: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048c73: 74 05 je 8048c7a <phase_3+0xc9>
8048c75: e8 16 fb ff ff call 8048790 <__stack_chk_fail@plt>
8048c7a: c9 leave
8048c7b: c3 ret
结果为:0 157
4. phase_4
08048c7c <func4>:
8048c7c: 55 push %ebp
8048c7d: 89 e5 mov %esp,%ebp
8048c7f: 56 push %esi
8048c80: 53 push %ebx
8048c81: 8b 55 08 mov 0x8(%ebp),%edx//小于0xe
8048c84: 8b 4d 0c mov 0xc(%ebp),%ecx//等于0xe
8048c87: 8b 75 10 mov 0x10(%ebp),%esi//等于0x0
8048c8a: 89 f0 mov %esi,%eax
8048c8c: 29 c8 sub %ecx,%eax
8048c8e: 89 c3 mov %eax,%ebx
8048c90: c1 eb 1f shr $0x1f,%ebx//逻辑右移(补零)
8048c93: 01 d8 add %ebx,%eax
8048c95: d1 f8 sar %eax//等价于(算术右移)一位
8048c97: 8d 1c 08 lea (%eax,%ecx,1),%ebx
8048c9a: 39 d3 cmp %edx,%ebx
8048c9c: 7e 15 jle 8048cb3 <func4+0x37>//小于等于就跳转
8048c9e: 83 ec 04 sub $0x4,%esp
8048ca1: 8d 43 ff lea -0x1(%ebx),%eax
8048ca4: 50 push %eax
8048ca5: 51 push %ecx
8048ca6: 52 push %edx
8048ca7: e8 d0 ff ff ff call 8048c7c <func4>
8048cac: 83 c4 10 add $0x10,%esp
8048caf: 01 d8 add %ebx,%eax
8048cb1: eb 19 jmp 8048ccc <func4+0x50>
8048cb3: 89 d8 mov %ebx,%eax
8048cb5: 39 d3 cmp %edx,%ebx
8048cb7: 7d 13 jge 8048ccc <func4+0x50>
//大于等于就跳转,可知结束条件是edx等于ebx
8048cb9: 83 ec 04 sub $0x4,%esp
8048cbc: 56 push %esi
8048cbd: 8d 43 01 lea 0x1(%ebx),%eax
8048cc0: 50 push %eax
8048cc1: 52 push %edx
8048cc2: e8 b5 ff ff ff call 8048c7c <func4>
8048cc7: 83 c4 10 add $0x10,%esp
8048cca: 01 d8 add %ebx,%eax
8048ccc: 8d 65 f8 lea -0x8(%ebp),%esp
8048ccf: 5b pop %ebx
8048cd0: 5e pop %esi
8048cd1: 5d pop %ebp
8048cd2: c3 ret
08048cd3 <phase_4>:
8048cd3: 55 push %ebp
8048cd4: 89 e5 mov %esp,%ebp
8048cd6: 83 ec 18 sub $0x18,%esp
8048cd9: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048cdf: 89 45 f4 mov %eax,-0xc(%ebp)
8048ce2: 31 c0 xor %eax,%eax
8048ce4: 8d 45 f0 lea -0x10(%ebp),%eax
8048ce7: 50 push %eax
8048ce8: 8d 45 ec lea -0x14(%ebp),%eax
8048ceb: 50 push %eax
8048cec: 68 17 a2 04 08 push $0x804a217//要求输入两数
8048cf1: ff 75 08 push 0x8(%ebp)
8048cf4: e8 17 fb ff ff call 8048810 <__isoc99_sscanf@plt>
8048cf9: 83 c4 10 add $0x10,%esp
8048cfc: 83 f8 02 cmp $0x2,%eax
8048cff: 75 06 jne 8048d07 <phase_4+0x34>
8048d01: 83 7d ec 0e cmpl $0xe,-0x14(%ebp)//第一个参数小于14
8048d05: 76 05 jbe 8048d0c <phase_4+0x39>
8048d07: e8 f3 03 00 00 call 80490ff <explode_bomb>
8048d0c: 83 ec 04 sub $0x4,%esp
8048d0f: 6a 0e push $0xe
8048d11: 6a 00 push $0x0
8048d13: ff 75 ec push -0x14(%ebp)
8048d16: e8 61 ff ff ff call 8048c7c <func4>
8048d1b: 83 c4 10 add $0x10,%esp
8048d1e: 83 f8 0f cmp $0xf,%eax
8048d21: 75 06 jne 8048d29 <phase_4+0x56>
8048d23: 83 7d f0 0f cmpl $0xf,-0x10(%ebp)//第二个参数等于十五
8048d27: 74 05 je 8048d2e <phase_4+0x5b>
8048d29: e8 d1 03 00 00 call 80490ff <explode_bomb>
8048d2e: 8b 45 f4 mov -0xc(%ebp),%eax
8048d31: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048d38: 74 05 je 8048d3f <phase_4+0x6c>
8048d3a: e8 51 fa ff ff call 8048790 <__stack_chk_fail@plt>
8048d3f: c9 leave
8048d40: c3 ret
结果为:5 15