csapp bomblab,1—6+secret,西工大爆炸实验满分策略(每个人的题目不一样,但是我都做了一遍,都总结出来了)

csapp bomblab,1—6+secret,西工大爆炸实验满分策略(每个人的题目不一样,但是我都做了一遍,都总结出来了)

我先把的answer公布一下,应该就知道,当然如果你的代码和我的情况有一点点差距,也没有关系,文章中有总结各个情况(不全面,只是我见到的)
answer

bomb-1

黑盒子,里面又一句口令,找到口令即可。
1.反汇编 命令行输入objdump -d bomp >asm.txt
:>为输出文件,也可以写成myname,txt,无所谓。
2.然后打开,找到函数<phase_1>
080488a0 <phase_1>:
80488a0: 55 push %ebp
80488a1: 89 e5 mov %esp,%ebp
80488a3: 83 ec 10 sub $0x10,%esp
80488a6: 68 a4 92 04 08 push $0x80492a4
80488ab: ff 75 08 pushl 0x8(%ebp)
80488ae: e8 27 05 00 00 call 8048dda <strings_not_equal>
80488b3: 83 c4 10 add $0x10,%esp
80488b6: 85 c0 test %eax,%eax
80488b8: 74 05 je 80488bf <phase_1+0x1f>
80488ba: e8 1e 06 00 00 call 8048edd <explode_bomb>
80488bf: c9 leave
80488c0: c3 ret
关键在于8048b36: 68 44 a2 04 08 push $0x80492a4
把这个压栈的地址拿出来看看就行,需要用到gdb工具,自行百度安装。命令依次输入 1.bomb-test
2. b main
3. r
4.x /s 0x80492a4
我的是这样的,每个人应该不一样
返回的字符串:
Crikey! I have lost my mojo!就是答案。

bomb-2

找phase_2函数,但是每个人的题目应该是不一样。
我见过是:斐波拉契数列,加序号增,程序员数列
我的是斐波拉契数列:
080488c1 <phase_2>:
80488c1: 55 push %ebp
80488c2: 89 e5 mov %esp,%ebp
80488c4: 56 push %esi
80488c5: 53 push %ebx
80488c6: 83 ec 28 sub $0x28,%esp
80488c9: 65 a1 14 00 00 00 mov %gs:0x14,%eax
80488cf: 89 45 f4 mov %eax,-0xc(%ebp)
80488d2: 31 c0 xor %eax,%eax
80488d4: 8d 45 dc lea -0x24(%ebp),%eax
80488d7: 50 push %eax
80488d8: ff 75 08 pushl 0x8(%ebp)
80488db: e8 25 06 00 00 call 8048f05 <read_six_numbers>
80488e0: 83 c4 10 add $0x10,%esp
80488e3: 83 7d dc 00 cmpl $0x0,-0x24(%ebp)
80488e7: 75 06 jne 80488ef <phase_2+0x2e>
80488e9: 83 7d e0 01 cmpl $0x1,-0x20(%ebp)
80488ed: 74 05 je 80488f4 <phase_2+0x33>
80488ef: e8 e9 05 00 00 call 8048edd <explode_bomb>
80488f4: 8d 5d dc lea -0x24(%ebp),%ebx
80488f7: 8d 75 ec lea -0x14(%ebp),%esi
80488fa: 8b 43 04 mov 0x4(%ebx),%eax
80488fd: 03 03 add (%ebx),%eax
80488ff: 39 43 08 cmp %eax,0x8(%ebx)
8048902: 74 05 je 8048909 <phase_2+0x48>
8048904: e8 d4 05 00 00 call 8048edd <explode_bomb>
8048909: 83 c3 04 add $0x4,%ebx
804890c: 39 f3 cmp %esi,%ebx
804890e: 75 ea jne 80488fa <phase_2+0x39>
8048910: 8b 45 f4 mov -0xc(%ebp),%eax
8048913: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
804891a: 74 05 je 8048921 <phase_2+0x60>
804891c: e8 7f fc ff ff call 80485a0 __stack_chk_fail@plt
8048921: 8d 65 f8 lea -0x8(%ebp),%esp
8048924: 5b pop %ebx
8048925: 5e pop %esi
8048926: 5d pop %ebp
8048927: c3 ret
具体的汇编代码不分析了,有时间有需求就慢慢分析一遍。
自行判别是哪种情况:
斐波拉契数列:
0 1 1 2 3 5
加序号增:
0 1 3 6 10 15
程序员数列:
1 2 4 8 16 32

bomb-3

总体思路:switch语句,第一个输入0—7,根据你的第一个输入,得到后面的结果。
我见过二种,一种输入是“%d %d”
另一种是“%d %c %d ”
第一种网上资料比较全,很常见,建议先看看那些
我刚好遇到 了第二种,
8048928: 55 push %ebp
8048929: 89 e5 mov %esp,%ebp
804892b: 83 ec 24 sub $0x24,%esp
804892e: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048934: 89 45 f4 mov %eax,-0xc(%ebp)
8048937: 31 c0 xor %eax,%eax
8048939: 8d 45 f0 lea -0x10(%ebp),%eax
804893c: 50 push %eax
804893d: 8d 45 eb lea -0x15(%ebp),%eax
8048940: 50 push %eax
8048941: 8d 45 ec lea -0x14(%ebp),%eax
8048944: 50 push %eax
8048945: 68 c1 92 04 08 push $0x80492c1
804894a: ff 75 08 pushl 0x8(%ebp)
804894d: e8 9e fc ff ff call 80485f0 <__isoc99_sscanf@plt>

在调用函数 call 80485f0 <__isoc99_sscanf@plt>
之前有一个压栈操作 push $0x80492c1
根据这个地址push $0x80492c1
通过命令行查看到底你的实验属于哪种情况:

我的是一个int 一个char 一个int。
看如下重点代码:
804895f: 83 7d ec 07 cmpl $0x7,-0x14(%ebp)
8048963: 0f 87 ec 00 00 00 ja 8048a55 <phase_3+0x12d>
8048969: 8b 45 ec mov -0x14(%ebp),%eax
804896c: ff 24 85 e0 92 04 08 jmp *0x80492e0(,%eax,4)
8048973: b8 66 00 00 00 mov $0x66,%eax
8048978: 81 7d f0 c2 00 00 00 cmpl $0xc2,-0x10(%ebp)
804897f: 0f 84 da 00 00 00 je 8048a5f <phase_3+0x137>
8048985: e8 53 05 00 00 call 8048edd <explode_bomb>
804898a: b8 66 00 00 00 mov $0x66,%eax
804898f: e9 cb 00 00 00 jmp 8048a5f <phase_3+0x137>
8048994: b8 63 00 00 00 mov $0x63,%eax
8048999: 83 7d f0 43 cmpl $0x43,-0x10(%ebp)
804899d: 0f 84 bc 00 00 00 je 8048a5f <phase_3+0x137>
80489a3: e8 35 05 00 00 call 8048edd <explode_bomb>

解析:
804895f: 83 7d ec 07 cmpl $0x7,-0x14(%ebp)
8048963: 0f 87 ec 00 00 00 ja 8048a55 <phase_3+0x12d>
;第一个int在大于7,就会bomb。
mov -0x14(%ebp),%eax
;将第一个输入传给eax,我输的是1。
804896c: ff 24 85 e0 92 04 08 jmp *0x80492e0(,%eax,4)
;根据你的选择给你跳转到不同位置, *0x80492e0反汇编代码里面没有这个地址,我猜是在别处引用的宏?或者由其他程序操作好了的内存空间?我第一个数是1,所以到第二个分支。
8048994: b8 63 00 00 00 mov $0x63,%eax
8048999: 83 7d f0 43 cmpl $0x43,-0x10(%ebp)
804899d: 0f 84 bc 00 00 00 je 8048a5f <phase_3+0x137>
80489a3: e8 35 05 00 00 call 8048edd <explode_bomb>
;第一句把0x63给eax
;第二句,比较第三个int类型的数是否为0x43,即67
;第三句,如果是,就跳转到 0x8048a5f处执行
;第四句,如果第三个数不等于67继续执行,召唤雷暴(天空龙的召雷弹,没玩过游戏王的小伙伴忽略),call 8048edd <explode_bomb>。
所以第一个数是1.第三个就是67,接下来,跳转到 0x8048a5f处执行:
8048a5f: 3a 45 eb cmp -0x15(%ebp),%al
8048a62: 74 05 je 8048a69 <phase_3+0x141>
8048a64: e8 74 04 00 00 call 8048edd <explode_bomb>
;比较第二个char字符是不是等于eax的第八位,之前赋值了,mov $0x63,%eax(自行往上看看代码),那就是看看ASCII是不是ox63,即99,即c
;是c,就跳转
;不是,召雷弹,bomb
所以答案是 1 c 67;
不唯一,你可以试试第一个数是其他,把代码过一遍,

bomb-4

我见过二种情况的代码,一种特别简单出答案,还有一种需要看代码,二种情况都是输入2 个数。
第一种:
主要找到这段代码:
8048ce4: e8 6a ff ff ff 8048c53 call func4
8048ce9: 83 c4 10 add $0x10,%esp
8048cec: 3b 45 f0 cmp -0x10(%ebp),%eax
8048cef: 74 05 je 8048cf6 <phase_4+0x58>
;调用了函数func4,返回结果存在eax。
;esp栈指针加0x10,忽略
;第三句把函数返回的eax和输入的第一个数相比,相等就跳转,意味着成功。
其实你可以,先输入1 3,然后,运行到这里设置断点,
在gdb下,设置断点的技巧如下,
1.用b +地址/label,设置断点
2.已经ni +num代表 从当前往走num步
3.stepi,走一步
设置 b 0x 8048cec断点(上面字体加重处),然后使用
print $eax
查看eax的值,把第一个数设置为这个值就好。不用看func4。
第二种:
可以慢慢看func4函数,也可以通过上面的方法估算出来,现在看代码的要求:
8048b01: 83 7d ec 0e cmpl $0xe,-0x14(%ebp)
8048b05: 76 05 jbe 8048b0c <phase_4+0x39>
这说明,第一个输入不超过0xe,即14;
8048b0f: 6a 0e push $0xe
8048b11: 6a 00 push $0x0
8048b13: ff 75 ec pushl -0x14(%ebp)
;传参给func4
8048b16: e8 61 ff ff ff call 8048a7c func4
8048b1b: 83 c4 10 add $0x10,%esp
8048b1e: 83 f8 1b cmp $0x1b,%eax
8048b21: 75 06 jne 8048b29 <phase_4+0x56>
8048b23: 83 7d f0 1b cmpl $0x1b,-0x10(%ebp)
8048b27: 74 05 je 8048b2e <phase_4+0x5b>
8048b29: e8 af 03 00 00 call 8048edd <explode_bomb>
;调用func4,返回给eax
;看eax的值是不是0x1b即27,如果不是,召雷
;如果是,再判断第二个参数是不是等于0x1b,即27
;否则召雷
;读到这里,我们知道第一个参数是小于等于14
;第二个参数是27
;这时候,需要去读func4,看看函数的逻辑,也可以不,就把第一个数从0到14遍历的试一遍,也可以得到解。
;我的代码算出来是 9 27。

bomb-5

主要就是数组操作。
我见过二种情况,第一种情况网上的参考资料比较多,直接搜bomblab,基本上绝大多数讲的都是一个字符寻找的故事。
我遇到的情况是第二种,这里讲一下。

8048b4c: e8 67 02 00 00 call 8048db8 <string_length>
8048b51: 83 c4 10 add $0x10,%esp
8048b54: 83 f8 06 cmp $0x6,%eax
8048b57: 74 05 je 8048b5e <phase_5+0x1d>
8048b59: e8 7f 03 00 00 call 8048edd <explode_bomb>
;上面的代码功能简单自行阅读,就是输入六个字符串,不允许多也不允许少。
8048b5e: 89 d8 mov %ebx,%eax
8048b60: 83 c3 06 add $0x6,%ebx
;ebx=eax+6,后面循环每次eax加一,当ebx==eax时,循环结束,遍历了6个字符。
8048b63: b9 00 00 00 00 mov $0x0,%ecx
;ecx初始化,这是最关键的遍历。
8048b68: 0f b6 10 movzbl (%eax),%edx
8048b6b: 83 e2 0f and $0xf,%edx
;依次取出eax的值,赋给edx,and操作是与操作,edx与0xf,只要字符所对应ASCII码的二进制数的后四位,赋给edx,作为后面的偏移量
8048b6e: 03 0c 95 add 0x8049300(,%edx,4),%ecx
8048b75: 83 c0 01 add $0x1,%eax
8048b78: 39 d8 cmp %ebx,%eax
;0x8049300是数组的第一个数字所在位置,0x8049300(,%edx,4)=0x8049300+edx*4,就是把edx作为偏移量,取出数组中的值,加到ecx中
;然后,eax加一,遍历下一个字符
;比较ebx和eax相等与否,相等结束循环。
8048b7c: 83 f9 3f cmp $0x3f,%ecx
最后看ecx的累加和是不是0x3f,即63.
现在我们看看数组里面有什么值吧,先再gdb中用
1.b phase_5
2.run answer(用一个文件把前面的结果写在一个名为answer的文件中)
新建文档,名为answer
answer里面的编辑
3.在 phase_5处产生了断点停顿,再输入
x /64w 0x8049300
如下图:
运行结果

现在就是找6个字符,他们的二进制最后四位最为偏移(起始点为2,然后是10,6,1.。。。每个人的代码可能不一样),从数组中取出6个数,其何为63(每个人的代码不一样,见上面代码分析)。

举个例子,如果你的6个字母中有A,其ASCII码值是0100 0001
取其后四位,0001,偏移是1,那就是相当于把10加入到了ecx中,再例如是B 0100 0010,其后四位是0010,偏移是2,就是数组中的6。同理,其他字符。(注意如果偏移是0,就是数组第一个)
数组情况如下:

bomb-6

我的代码是一个链表,然后让你a[i]=7-a[i],最后降序排列,把排序顺序输出。
8048b8b: 55 push %ebp
8048b8c: 89 e5 mov %esp,%ebp
8048b8e: 56 push %esi
8048b8f: 53 push %ebx
8048b90: 83 ec 48 sub $0x48,%esp
8048b93: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048b99: 89 45 f4 mov %eax,-0xc(%ebp)
8048b9c: 31 c0 xor %eax,%eax
8048b9e: 8d 45 c4 lea -0x3c(%ebp),%eax
8048ba1: 50 push %eax
8048ba2: ff 75 08 pushl 0x8(%ebp)
8048ba5: e8 5b 03 00 00 call 8048f05 <read_six_numbers>
;有了前面5题基础,很显然,初始化栈帧,读六个数
8048baa: 83 c4 10 add $0x10,%esp
8048bad: be 00 00 00 00 mov $0x0,%esi
8048bb2: 8b 44 b5 c4 mov -0x3c(%ebp,%esi,4),%eax
8048bb6: 83 e8 01 sub $0x1,%eax
8048bb9: 83 f8 05 cmp $0x5,%eax
8048bbc: 76 05 jbe 8048bc3 <phase_6+0x38>
8048bbe: e8 1a 03 00 00 call 8048edd <explode_bomb>
8048bc3: 83 c6 01 add $0x1,%esi;esi=0+1
8048bc6: 83 fe 06 cmp $0x6,%esi
8048bc9: 74 1b je 8048be6 <phase_6+0x5b>
8048bcb: 89 f3 mov %esi,%ebx
8048bcd: 8b 44 9d c4 mov -0x3c(%ebp,%ebx,4),%eax
8048bd1: 39 44 b5 c0 cmp %eax,-0x40(%ebp,%esi,4)
8048bd5: 75 05 jne 8048bdc <phase_6+0x51>
8048bd7: e8 01 03 00 00 call 8048edd <explode_bomb>
8048bdc: 83 c3 01 add $0x1,%ebx
8048bdf: 83 fb 05 cmp $0x5,%ebx
8048be2: 7e e9 jle 8048bcd <phase_6+0x42>
8048be4: eb cc jmp 8048bb2 <phase_6+0x27>
;输入的数进行限制,不许大于6,有二个循环嵌套,不许用值相同。

8048be6: 8d 45 c4 lea -0x3c(%ebp),%eax
8048be9: 8d 5d dc lea -0x24(%ebp),%ebx
8048bec: b9 07 00 00 00 mov $0x7,%ecx
8048bf1: 89 ca mov %ecx,%edx
8048bf3: 2b 10 sub (%eax),%edx
8048bf5: 89 10 mov %edx,(%eax)
8048bf7: 83 c0 04 add $0x4,%eax
8048bfa: 39 c3 cmp %eax,%ebx
8048bfc: 75 f3 jne 8048bf1 <phase_6+0x66>
;让a[i]=7-a[i];
8048bfe: bb 00 00 00 00 mov $0x0,%ebx
8048c03: eb 16 jmp 8048c1b <phase_6+0x90>
8048c05: 8b 52 08 mov 0x8(%edx),%edx
8048c08: 83 c0 01 add $0x1,%eax
8048c0b: 39 c8 cmp %ecx,%eax
8048c0d: 75 f6 jne 8048c05 <phase_6+0x7a>
8048c0f: 89 54 b5 dc mov %edx,-0x24(%ebp,%esi,4)
8048c13: 83 c3 01 add $0x1,%ebx
8048c16: 83 fb 06 cmp $0x6,%ebx
8048c19: 74 17 je 8048c32 <phase_6+0xa7>
8048c1b: 89 de mov %ebx,%esi
8048c1d: 8b 4c 9d c4 mov -0x3c(%ebp,%ebx,4),%ecx
8048c21: b8 01 00 00 00 mov $0x1,%eax
8048c26: ba 34 b1 04 08 mov $0x804b134,%edx
8048c2b: 83 f9 01 cmp $0x1,%ecx
8048c2e: 7f d5 jg 8048c05 <phase_6+0x7a>
8048c30: eb dd jmp 8048c0f <phase_6+0x84>
8048c32: 8b 5d dc mov -0x24(%ebp),%ebx
8048c35: 8d 45 dc lea -0x24(%ebp),%eax
8048c38: 8d 75 f0 lea -0x10(%ebp),%esi
8048c3b: 89 d9 mov %ebx,%ecx
8048c3d: 8b 50 04 mov 0x4(%eax),%edx
8048c40: 89 51 08 mov %edx,0x8(%ecx)
8048c43: 83 c0 04 add $0x4,%eax
8048c46: 89 d1 mov %edx,%ecx
8048c48: 39 c6 cmp %eax,%esi
8048c4a: 75 f1 jne 8048c3d <phase_6+0xb2>
8048c4c: c7 42 08 00 00 00 00 movl $0x0,0x8(%edx)
8048c53: be 05 00 00 00 mov $0x5,%esi
8048c58: 8b 43 08 mov 0x8(%ebx),%eax
8048c5b: 8b 00 mov (%eax),%eax
8048c5d: 39 03 cmp %eax,(%ebx)
8048c5f: 7d 05 jge 8048c66 <phase_6+0xdb>
8048c61: e8 77 02 00 00 call 8048edd <explode_bomb>
8048c66: 8b 5b 08 mov 0x8(%ebx),%ebx
8048c69: 83 ee 01 sub $0x1,%esi
8048c6c: 75 ea jne 8048c58 <phase_6+0xcd>
8048c6e: 8b 45 f4 mov -0xc(%ebp),%eax
8048c71: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048c78: 74 05 je 8048c7f <phase_6+0xf4>
;根据每个序号下的数值,进行倒序排列
那数值是多少?它是事先写好在程序中的,可以查看。其地址为:
0x804b134,可以理解它为链表的头指针
我们通过gdb查看:
链表
查看步骤还是设断点,run answer,再用x /20dw 0x804b134。

需要我们输入的就是这个排列的顺序:
996 6
934 1
529 2
345 3
211 4
133 5
别忘了,a[i]=7-a[i],所以结果是:
1 6 5 4 3 2

secret

打开汇编程序,找到函数phase_defused
08049042 <phase_defused>:
8049042: 55 push %ebp
8049043: 89 e5 mov %esp,%ebp
8049045: 83 ec 68 sub $0x68,%esp
8049048: 65 a1 14 00 00 00 mov %gs:0x14,%eax
804904e: 89 45 f4 mov %eax,-0xc(%ebp)
8049051: 31 c0 xor %eax,%eax
8049053: 83 3d ac b7 04 08 06 cmpl $0x6,0x804b7ac
804905a: 75 6f jne 80490cb <phase_defused+0x89>
804905c: 83 ec 0c sub $0xc,%esp
804905f: 8d 45 a4 lea -0x5c(%ebp),%eax
8049062: 50 push %eax
8049063: 8d 45 a0 lea -0x60(%ebp),%eax
8049066: 50 push %eax
8049067: 8d 45 9c lea -0x64(%ebp),%eax
804906a: 50 push %eax
804906b: 68 d3 94 04 08 push $0x80494d3
8049070: 68 b0 b8 04 08 push $0x804b8b0
8049075: e8 76 f5 ff ff call 80485f0 __isoc99_sscanf@plt
804907a: 83 c4 20 add $0x20,%esp
804907d: 83 f8 03 cmp $0x3,%eax
8049080: 75 39 jne 80490bb <phase_defused+0x79>
8049082: 83 ec 08 sub $0x8,%esp
8049085: 68 dc 94 04 08 push $0x80494dc
804908a: 8d 45 a4 lea -0x5c(%ebp),%eax
804908d: 50 push %eax
804908e: e8 47 fd ff ff call 8048dda <strings_not_equal>
8049093: 83 c4 10 add $0x10,%esp
8049096: 85 c0 test %eax,%eax
8049098: 75 21 jne 80490bb <phase_defused+0x79>
804909a: 83 ec 0c sub $0xc,%esp
804909d: 68 a0 93 04 08 push $0x80493a0
80490a2: e8 19 f5 ff ff call 80485c0 puts@plt
80490a7: c7 04 24 c8 93 04 08 movl $0x80493c8,(%esp)
80490ae: e8 0d f5 ff ff call 80485c0 puts@plt
80490b3: e8 20 fc ff ff call 8048cd8 <secret_phase>
80490b8: 83 c4 10 add $0x10,%esp
80490bb: 83 ec 0c sub $0xc,%esp
80490be: 68 00 94 04 08 push $0x8049400
80490c3: e8 f8 f4 ff ff call 80485c0 puts@plt
80490c8: 83 c4 10 add $0x10,%esp
80490cb: 8b 45 f4 mov -0xc(%ebp),%eax
80490ce: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
80490d5: 74 05 je 80490dc <phase_defused+0x9a>
80490d7: e8 c4 f4 ff ff call 80485a0 __stack_chk_fail@plt
80490dc: c9 leave
80490dd: c3 ret
80490de: 66 90 xchg %ax,%ax
;把加粗的字符串打印出来 x /s 地址

有第一个可知,在输入为 %d %d后有一个%s,然而有连续二个int输入就是第四关,而%s的字符串就是密码。这个密码是最后一个,我的是hamster。(每个人可能不同)。
因此在回答第四关结果的时候,输入:9 27 hamster
hmaster为开启秘密关卡的钥匙,没有这个,第六关结束后不会秘密关卡不会爆出。加上这个口令才会触发秘密关卡,是不是很有趣呢?

秘密关卡,根据上面6个实验g观赏汇编的经验,自己去做吧,不会的话可以求助互联网,也可以问我。

  • 37
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值