Fork me on GitHub

csapp_bombLab

phase_1

1
2
3
4
5
6
7
8
9
10
11
12
13
08048b30 <phase_1>:
8048b30: 55 push %ebp
8048b31: 89 e5 mov %esp,%ebp
8048b33: 83 ec 10 sub $0x10,%esp
8048b36: 68 24 a1 04 08 push $0x804a124
8048b3b: ff 75 08 pushl 0x8(%ebp)
8048b3e: e8 63 05 00 00 call 80490a6 <strings_not_equal>
8048b43: 83 c4 10 add $0x10,%esp
8048b46: 85 c0 test %eax,%eax
8048b48: 74 05 je 8048b4f <phase_1+0x1f>
8048b4a: e8 5a 06 00 00 call 80491a9 <explode_bomb>
8048b4f: c9 leave
8048b50: c3 ret

直接查看0x804a124地址里的值

Border relations with Canada have never been better.

phase_2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
08048b51 <phase_2>:
8048b51: 55 push %ebp
8048b52: 89 e5 mov %esp,%ebp
8048b54: 53 push %ebx
8048b55: 83 ec 2c sub $0x2c,%esp
8048b58: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048b5e: 89 45 f4 mov %eax,-0xc(%ebp)
8048b61: 31 c0 xor %eax,%eax
8048b63: 8d 45 dc lea -0x24(%ebp),%eax
8048b66: 50 push %eax
8048b67: ff 75 08 pushl 0x8(%ebp)#准备工作
8048b6a: e8 62 06 00 00 call 80491d1 <read_six_numbers>
8048b6f: 83 c4 10 add $0x10,%esp
8048b72: 83 7d dc 00 cmpl $0x0,-0x24(%ebp)
8048b76: 79 05 jns 8048b7d <phase_2+0x2c> #-36(%ebp)=0
8048b78: e8 2c 06 00 00 call 80491a9 <explode_bomb>
8048b7d: bb 01 00 00 00 mov $0x1,%ebx
8048b82: 89 d8 mov %ebx,%eax
8048b84: 03 44 9d d8 add -0x28(%ebp,%ebx,4),%eax #上一个数加上ebx也是eax里的值
8048b88: 39 44 9d dc cmp %eax,-0x24(%ebp,%ebx,4) #比较计算后的值和上一单元的值
8048b8c: 74 05 je 8048b93 <phase_2+0x42>
8048b8e: e8 16 06 00 00 call 80491a9 <explode_bomb>
8048b93: 83 c3 01 add $0x1,%ebx
8048b96: 83 fb 06 cmp $0x6,%ebx
8048b99: 75 e7 jne 8048b82 <phase_2+0x31>
8048b9b: 8b 45 f4 mov -0xc(%ebp),%eax
8048b9e: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048ba5: 74 05 je 8048bac <phase_2+0x5b>
8048ba7: e8 e4 fb ff ff call 8048790 <__stack_chk_fail@plt>
8048bac: 8b 5d fc mov -0x4(%ebp),%ebx
8048baf: c9 leave
8048bb0: c3 ret

地址为8048b72一行和下一行表示ebp-36和0比较,如果0-(ebp-36)里面的值之后不是非负数那么就会调用bomb函数,引起爆炸,所以,ebp-36里的值只能为0。再往下看,设ebx里的值为i,地址为 8048b7d~ 8048b84三行运行之后就是eax赋值为1,地址为ebp+4i-40的值加上eax里的1相加后放到eax里。下一行是eax里的值和地址为ebp+4i-36也就是上一个单元里的值进行比较,不相等也会调用bomb函数,所以,根据这个,第一遍可以推出ebp-32的值为1,之后就可以一直如此(下一数等于其上一个数加上ebx里的值,ebx是逐一递增的)推出ebp-16~ebp-36之间的六个值分别为0 1 3 6 10 15

phase_3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<phase_3>:
8048bb1: 55 push %ebp
8048bb2: 89 e5 mov %esp,%ebp
8048bb4: 83 ec 24 sub $0x24,%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 eb lea -0x15(%ebp),%eax
8048bc9: 50 push %eax
8048bca: 8d 45 ec lea -0x14(%ebp),%eax
8048bcd: 50 push %eax
8048bce: 68 82 a1 04 08 push $0x804a182 #%d %c %d
8048bd3: ff 75 08 pushl 0x8(%ebp)
8048bd6: e8 35 fc ff ff call 8048810 <__isoc99_sscanf@plt>
8048bdb: 83 c4 20 add $0x20,%esp
8048bde: 83 f8 02 cmp $0x2,%eax
8048be1: 7f 05 jg 8048be8 <phase_3+0x37>
8048be3: e8 c1 05 00 00 call 80491a9 <explode_bomb>
8048be8: 83 7d ec 07 cmpl $0x7,-0x14(%ebp)
8048bec: 0f 87 ef 00 00 00 ja 8048ce1 <phase_3+0x130> #输入的数要小于7
8048bf2: 8b 45 ec mov -0x14(%ebp),%eax
8048bf5: ff 24 85 a0 a1 04 08 jmp *0x804a1a0(,%eax,4) #0x08048c3e
8048bfc: b8 6a 00 00 00 mov $0x6a,%eax
8048c01: 81 7d f0 d9 00 00 00 cmpl $0xd9,-0x10(%ebp)
8048c08: 0f 84 dd 00 00 00 je 8048ceb <phase_3+0x13a>
8048c0e: e8 96 05 00 00 call 80491a9 <explode_bomb>
8048c13: b8 6a 00 00 00 mov $0x6a,%eax
8048c18: e9 ce 00 00 00 jmp 8048ceb <phase_3+0x13a>
8048c1d: b8 68 00 00 00 mov $0x68,%eax
8048c22: 81 7d f0 e4 01 00 00 cmpl $0x1e4,-0x10(%ebp)
8048c29: 0f 84 bc 00 00 00 je 8048ceb <phase_3+0x13a>
8048c2f: e8 75 05 00 00 call 80491a9 <explode_bomb>
8048c34: b8 68 00 00 00 mov $0x68,%eax
8048c39: e9 ad 00 00 00 jmp 8048ceb <phase_3+0x13a>
8048c3e: b8 72 00 00 00 mov $0x72,%eax #跳到这
8048c43: 81 7d f0 82 03 00 00 cmpl $0x382,-0x10(%ebp)#898 也就是第三个数
8048c4a: 0f 84 9b 00 00 00 je 8048ceb <phase_3+0x13a>
8048c50: e8 54 05 00 00 call 80491a9 <explode_bomb>
8048c55: b8 72 00 00 00 mov $0x72,%eax
8048c5a: e9 8c 00 00 00 jmp 8048ceb <phase_3+0x13a>
8048c5f: b8 6d 00 00 00 mov $0x6d,%eax
8048c64: 81 7d f0 06 03 00 00 cmpl $0x306,-0x10(%ebp)
8048c6b: 74 7e je 8048ceb <phase_3+0x13a>
8048c6d: e8 37 05 00 00 call 80491a9 <explode_bomb>
8048c72: b8 6d 00 00 00 mov $0x6d,%eax
8048c77: eb 72 jmp 8048ceb <phase_3+0x13a>
8048c79: b8 62 00 00 00 mov $0x62,%eax
8048c7e: 81 7d f0 0d 02 00 00 cmpl $0x20d,-0x10(%ebp)
8048c85: 74 64 je 8048ceb <phase_3+0x13a>
8048c87: e8 1d 05 00 00 call 80491a9 <explode_bomb>
8048c8c: b8 62 00 00 00 mov $0x62,%eax
8048c91: eb 58 jmp 8048ceb <phase_3+0x13a>
8048c93: b8 63 00 00 00 mov $0x63,%eax
8048c98: 81 7d f0 4b 02 00 00 cmpl $0x24b,-0x10(%ebp)
8048c9f: 74 4a je 8048ceb <phase_3+0x13a>
8048ca1: e8 03 05 00 00 call 80491a9 <explode_bomb>
8048ca6: b8 63 00 00 00 mov $0x63,%eax
8048cab: eb 3e jmp 8048ceb <phase_3+0x13a>
8048cad: b8 65 00 00 00 mov $0x65,%eax
8048cb2: 81 7d f0 53 02 00 00 cmpl $0x253,-0x10(%ebp)
8048cb9: 74 30 je 8048ceb <phase_3+0x13a>
8048cbb: e8 e9 04 00 00 call 80491a9 <explode_bomb>
8048cc0: b8 65 00 00 00 mov $0x65,%eax
8048cc5: eb 24 jmp 8048ceb <phase_3+0x13a>
8048cc7: b8 65 00 00 00 mov $0x65,%eax
8048ccc: 81 7d f0 5c 01 00 00 cmpl $0x15c,-0x10(%ebp)
8048cd3: 74 16 je 8048ceb <phase_3+0x13a>
8048cd5: e8 cf 04 00 00 call 80491a9 <explode_bomb>
8048cda: b8 65 00 00 00 mov $0x65,%eax
8048cdf: eb 0a jmp 8048ceb <phase_3+0x13a>
8048ce1: e8 c3 04 00 00 call 80491a9 <explode_bomb>
8048ce6: b8 73 00 00 00 mov $0x73,%eax
8048ceb: 3a 45 eb cmp -0x15(%ebp),%al #也就是第二个字符的ascii是0x72 也就是r
8048cee: 74 05 je 8048cf5 <phase_3+0x144>
8048cf0: e8 b4 04 00 00 call 80491a9 <explode_bomb>
8048cf5: 8b 45 f4 mov -0xc(%ebp),%eax
8048cf8: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048cff: 74 05 je 8048d06 <phase_3+0x155>
8048d01: e8 8a fa ff ff call 8048790 <__stack_chk_fail@plt>
8048d06: c9 leave
8048d07: c3 ret

首先给出了明地址8048bce,看看里面是啥 ,发现是%d %c %d,这意味着输入一个数一个字符和一个数,再往下看,8048bde这里把scanf函数的返回值和2比较,由于我们之前已经找到了输入的格式,所以此时的eax为确定的3。接着往后,地址为ebp-14里的内容和7比较,也就是说,第一个数要小于7,初步测试用2,之后通过gdb调试发现跳到0x08048c3e,之后是地址为ebp-16的值和0x382即898比较,只有相等才不会调用bomb函数,也就是说第三个数是898,再往后跳转到8048ceb,此时的eax里是0x72,要求地址为ebp-21的值和al里的值相等,又因为之前看到输入里有一个字符,也就是说,字符的ascii码为0x72,即r,至此,第三个字符完成。当然,如果一开始输入的不是二而是其他小于7的数,后面的各个跳转到的位置也会变化,后两个输入也会不同,也就是这个字符的答案不唯一。

phase_4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
08048d08 <func4>:
8048d08: 55 push %ebp
8048d09: 89 e5 mov %esp,%ebp
8048d0b: 56 push %esi
8048d0c: 53 push %ebx
8048d0d: 8b 4d 08 mov 0x8(%ebp),%ecx
8048d10: 8b 5d 0c mov 0xc(%ebp),%ebx
8048d13: 8b 75 10 mov 0x10(%ebp),%esi
8048d16: 89 f0 mov %esi,%eax
8048d18: 29 d8 sub %ebx,%eax
8048d1a: 89 c2 mov %eax,%edx
8048d1c: c1 ea 1f shr $0x1f,%edx
8048d1f: 01 d0 add %edx,%eax
8048d21: d1 f8 sar %eax
8048d23: 8d 14 18 lea (%eax,%ebx,1),%edx
8048d26: 39 ca cmp %ecx,%edx
8048d28: 7e 15 jle 8048d3f <func4+0x37>
8048d2a: 83 ec 04 sub $0x4,%esp
8048d2d: 83 ea 01 sub $0x1,%edx
8048d30: 52 push %edx
8048d31: 53 push %ebx
8048d32: 51 push %ecx
8048d33: e8 d0 ff ff ff call 8048d08 <func4>
8048d38: 83 c4 10 add $0x10,%esp
8048d3b: 01 c0 add %eax,%eax
8048d3d: eb 1e jmp 8048d5d <func4+0x55>
8048d3f: b8 00 00 00 00 mov $0x0,%eax
8048d44: 39 ca cmp %ecx,%edx
8048d46: 7d 15 jge 8048d5d <func4+0x55>
8048d48: 83 ec 04 sub $0x4,%esp
8048d4b: 56 push %esi
8048d4c: 83 c2 01 add $0x1,%edx
8048d4f: 52 push %edx
8048d50: 51 push %ecx
8048d51: e8 b2 ff ff ff call 8048d08 <func4>
8048d56: 83 c4 10 add $0x10,%esp
8048d59: 8d 44 00 01 lea 0x1(%eax,%eax,1),%eax #eax=2
8048d5d: 8d 65 f8 lea -0x8(%ebp),%esp
8048d60: 5b pop %ebx
8048d61: 5e pop %esi
8048d62: 5d pop %ebp
8048d63: c3 ret
1
2
3
4
5
6
7
8
9
10
static int func4(int a, int b, int c){
int tmp = (((c - b) + ((c - b) >> 31)) >> 1) + b;
if (tmp <= a) {
if (tmp == a) {
return (0); }
else {
return func4(a, tmp + 1, c) * 2 + 1; }
}
else { return func4(a, b, tmp - 1) * 2; }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
08048d64 <phase_4>:
8048d64: 55 push %ebp
8048d65: 89 e5 mov %esp,%ebp
8048d67: 83 ec 18 sub $0x18,%esp
8048d6a: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048d70: 89 45 f4 mov %eax,-0xc(%ebp)
8048d73: 31 c0 xor %eax,%eax
8048d75: 8d 45 f0 lea -0x10(%ebp),%eax
8048d78: 50 push %eax
8048d79: 8d 45 ec lea -0x14(%ebp),%eax
8048d7c: 50 push %eax
8048d7d: 68 0f a3 04 08 push $0x804a30f # %d %d
8048d82: ff 75 08 pushl 0x8(%ebp)
8048d85: e8 86 fa ff ff call 8048810 <__isoc99_sscanf@plt>
8048d8a: 83 c4 10 add $0x10,%esp
8048d8d: 83 f8 02 cmp $0x2,%eax #输入两个数
8048d90: 75 06 jne 8048d98 <phase_4+0x34>
8048d92: 83 7d ec 0e cmpl $0xe,-0x14(%ebp)
8048d96: 76 05 jbe 8048d9d <phase_4+0x39> #<=
8048d98: e8 0c 04 00 00 call 80491a9 <explode_bomb>
8048d9d: 83 ec 04 sub $0x4,%esp
8048da0: 6a 0e push $0xe
8048da2: 6a 00 push $0x0
8048da4: ff 75 ec pushl -0x14(%ebp)
8048da7: e8 5c ff ff ff call 8048d08 <func4>
8048dac: 83 c4 10 add $0x10,%esp
8048daf: 83 f8 05 cmp $0x5,%eax #返回值必须为5
8048db2: 75 06 jne 8048dba <phase_4+0x56>
8048db4: 83 7d f0 05 cmpl $0x5,-0x10(%ebp)
8048db8: 74 05 je 8048dbf <phase_4+0x5b>
8048dba: e8 ea 03 00 00 call 80491a9 <explode_bomb>
8048dbf: 8b 45 f4 mov -0xc(%ebp),%eax
8048dc2: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048dc9: 74 05 je 8048dd0 <phase_4+0x6c>
8048dcb: e8 c0 f9 ff ff call 8048790 <__stack_chk_fail@plt>
8048dd0: c9 leave
8048dd1: c3 ret

首先打印地址0x804a30f的内容发现是%d %d初步判定是输入两个整型,再往下看有一个输入返回值和2的比较也就是说必须输入两个数,这就基本确定是输入两个数。再往后看,发现是调用func4函数,这个函数的参数第一个是输入的值,第二个是0,第三个是0xe。看func4的功能,func4的c函数见上。再回来看phase_4函数,发现要求返回值是5,不然就会调用bomb函数。再去看func4,是一个递归,最后一次只能是0才能回去,那就从0开始,两个选择,要么是2×返回值,要么是2×返回值+1,从零开始,先乘二加一,再乘二,再乘二加一就是5,也就是第一次要输入的数>tmp,在这里就是输入的数大于7,第二次是输入的数小于tmp,在这里是输入的数小于11,第三次是输入的数大于tmp,在这里是输入的数大于5,第四次就是输入的数等于tmp,计算出tmp=10,这就是输入的第一个参数。再往后看,很简单了,第二个参数和5比较,不相等就bomb,所以第二个参数是5.

phase_5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
08048dd2 <phase_5>:
8048dd2: 55 push %ebp
8048dd3: 89 e5 mov %esp,%ebp
8048dd5: 83 ec 18 sub $0x18,%esp
8048dd8: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048dde: 89 45 f4 mov %eax,-0xc(%ebp)
8048de1: 31 c0 xor %eax,%eax
8048de3: 8d 45 f0 lea -0x10(%ebp),%eax
8048de6: 50 push %eax
8048de7: 8d 45 ec lea -0x14(%ebp),%eax
8048dea: 50 push %eax
8048deb: 68 0f a3 04 08 push $0x804a30f #%d %d
8048df0: ff 75 08 pushl 0x8(%ebp)
8048df3: e8 18 fa ff ff call 8048810 <__isoc99_sscanf@plt>
8048df8: 83 c4 10 add $0x10,%esp
8048dfb: 83 f8 01 cmp $0x1,%eax
8048dfe: 7f 05 jg 8048e05 <phase_5+0x33>
8048e00: e8 a4 03 00 00 call 80491a9 <explode_bomb>
8048e05: 8b 45 ec mov -0x14(%ebp),%eax
8048e08: 83 e0 0f and $0xf,%eax
8048e0b: 89 45 ec mov %eax,-0x14(%ebp)
8048e0e: 83 f8 0f cmp $0xf,%eax
8048e11: 74 2c je 8048e3f <phase_5+0x6d>
8048e13: b9 00 00 00 00 mov $0x0,%ecx
8048e18: ba 00 00 00 00 mov $0x0,%edx
8048e1d: 83 c2 01 add $0x1,%edx
8048e20: 8b 04 85 c0 a1 04 08 mov 0x804a1c0(,%eax,4),%eax
8048e27: 01 c1 add %eax,%ecx
8048e29: 83 f8 0f cmp $0xf,%eax
8048e2c: 75 ef jne 8048e1d <phase_5+0x4b>
8048e2e: c7 45 ec 0f 00 00 00 movl $0xf,-0x14(%ebp)
8048e35: 83 fa 0f cmp $0xf,%edx
8048e38: 75 05 jne 8048e3f <phase_5+0x6d>
8048e3a: 3b 4d f0 cmp -0x10(%ebp),%ecx
8048e3d: 74 05 je 8048e44 <phase_5+0x72>
8048e3f: e8 65 03 00 00 call 80491a9 <explode_bomb>
8048e44: 8b 45 f4 mov -0xc(%ebp),%eax
8048e47: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048e4e: 74 05 je 8048e55 <phase_5+0x83>
8048e50: e8 3b f9 ff ff call 8048790 <__stack_chk_fail@plt>
8048e55: c9 leave
8048e56: c3 ret

地址为0x804a30f 的内容是%d %d ,根据之前的经验,还是输入两个整型。再往后看,这个的意思就是ecx中存放sum,edx中存放数组下标i,eax中存放a[i],a的起始地址为0x804a1c0,要求找到相应的正确起始下标并且保证值为15的数在数组下标为15的地方,打印出这个数组:12 3 7 11 13 9 4 8 0 10 1 2 14 6 15 也就是要想办法让第a[1]的值是12,mov %eax,-0x14(%ebp) cmp $0xf,%eax je 8048e3f <phase_5+0x6d>这三句给了提示,输入的数组下标不超过14,从头来,试到第五个就是12开头了。也就是第一个数是5,再往后看,-0x10(%ebp),%ecx要求第二个参数和ecx中的值一样,通过gdb调试发现执行到这步的时候,ecx值为115,也就是第二个数是115.

phase_6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
08048e57 <phase_6>:
8048e57: 55 push %ebp
8048e58: 89 e5 mov %esp,%ebp
8048e5a: 56 push %esi
8048e5b: 53 push %ebx
8048e5c: 83 ec 48 sub $0x48,%esp
8048e5f: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048e65: 89 45 f4 mov %eax,-0xc(%ebp)
8048e68: 31 c0 xor %eax,%eax
8048e6a: 8d 45 c4 lea -0x3c(%ebp),%eax
8048e6d: 50 push %eax
8048e6e: ff 75 08 pushl 0x8(%ebp)
8048e71: e8 5b 03 00 00 call 80491d1 <read_six_numbers> #读六个数
8048e76: 83 c4 10 add $0x10,%esp
8048e79: be 00 00 00 00 mov $0x0,%esi
8048e7e: 8b 44 b5 c4 mov -0x3c(%ebp,%esi,4),%eax
8048e82: 83 e8 01 sub $0x1,%eax
8048e85: 83 f8 05 cmp $0x5,%eax
8048e88: 76 05 jbe 8048e8f <phase_6+0x38>
8048e8a: e8 1a 03 00 00 call 80491a9 <explode_bomb>
8048e8f: 83 c6 01 add $0x1,%esi
8048e92: 83 fe 06 cmp $0x6,%esi
8048e95: 74 1b je 8048eb2 <phase_6+0x5b>
8048e97: 89 f3 mov %esi,%ebx
8048e99: 8b 44 9d c4 mov -0x3c(%ebp,%ebx,4),%eax
8048e9d: 39 44 b5 c0 cmp %eax,-0x40(%ebp,%esi,4)
8048ea1: 75 05 jne 8048ea8 <phase_6+0x51>
8048ea3: e8 01 03 00 00 call 80491a9 <explode_bomb>
8048ea8: 83 c3 01 add $0x1,%ebx
8048eab: 83 fb 05 cmp $0x5,%ebx
8048eae: 7e e9 jle 8048e99 <phase_6+0x42>
8048eb0: eb cc jmp 8048e7e <phase_6+0x27#6个小于等于6的不同的数
8048eb2: 8d 45 c4 lea -0x3c(%ebp),%eax
8048eb5: 8d 5d dc lea -0x24(%ebp),%ebx
8048eb8: b9 07 00 00 00 mov $0x7,%ecx
8048ebd: 89 ca mov %ecx,%edx
8048ebf: 2b 10 sub (%eax),%edx
8048ec1: 89 10 mov %edx,(%eax)
8048ec3: 83 c0 04 add $0x4,%eax
8048ec6: 39 c3 cmp %eax,%ebx
8048ec8: 75 f3 jne 8048ebd <phase_6+0x66>
8048eca: bb 00 00 00 00 mov $0x0,%ebx
8048ecf: eb 16 jmp 8048ee7 <phase_6+0x90>
8048ed1: 8b 52 08 mov 0x8(%edx),%edx
8048ed4: 83 c0 01 add $0x1,%eax
8048ed7: 39 c8 cmp %ecx,%eax
8048ed9: 75 f6 jne 8048ed1 <phase_6+0x7a>
8048edb: 89 54 b5 dc mov %edx,-0x24(%ebp,%esi,4)
8048edf: 83 c3 01 add $0x1,%ebx
8048ee2: 83 fb 060 cmp $0x6,%ebx
8048ee5: 74 17 je 8048efe <phase_6+0xa7>
8048ee7: 89 de mov %ebx,%esi
8048ee9: 8b 4c 9d c4 mov -0x3c(%ebp,%ebx,4),%ecx
8048eed: b8 01 00 00 00 mov $0x1,%eax
8048ef2: ba 3c c1 04 08 mov $0x804c13c,%edx
8048ef7: 83 f9 01 cmp $0x1,%ecx
8048efa: 7f d5 jg 8048ed1 <phase_6+0x7a>
8048efc: eb dd jmp 8048edb <phase_6+0x84>
8048efe: 8b 5d dc mov -0x24(%ebp),%ebx
8048f01: 8d 45 dc lea -0x24(%ebp),%eax
8048f04: 8d 75 f0 lea -0x10(%ebp),%esi
8048f07: 89 d9 mov %ebx,%ecx
8048f09: 8b 50 04 mov 0x4(%eax),%edx
8048f0c: 89 51 08 mov %edx,0x8(%ecx)#
8048f0f: 83 c0 04 add $0x4,%eax
8048f12: 89 d1 mov %edx,%ecx
8048f14: 39 c6 cmp %eax,%esi
8048f16: 75 f1 jne 8048f09 <phase_6+0xb2>
8048f18: c7 42 08 00 00 00 00 movl $0x0,0x8(%edx)
8048f1f: be 05 00 00 00 mov $0x5,%esi
8048f24: 8b 43 08 mov 0x8(%ebx),%eax
8048f27: 8b 00 mov (%eax),%eax
8048f29: 39 03 cmp %eax,(%ebx)
8048f2b: 7d 05 jge 8048f32 <phase_6+0xdb>
8048f2d: e8 77 02 00 00 call 80491a9 <explode_bomb>
8048f32: 8b 5b 08 mov 0x8(%ebx),%ebx
8048f35: 83 ee 01 sub $0x1,%esi
8048f38: 75 ea jne 8048f24 <phase_6+0xcd>
8048f3a: 8b 45 f4 mov -0xc(%ebp),%eax
8048f3d: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048f44: 74 05 je 8048f4b <phase_6+0xf4>
8048f46: e8 45 f8 ff ff call 8048790 <__stack_chk_fail@plt>
8048f4b: 8d 65 f8 lea -0x8(%ebp),%esp
8048f4e: 5b pop %ebx
8048f4f: 5e pop %esi
8048f50: 5d pop %ebp
8048f51: c3 ret

首先是调用了读取六个数的函数,也就是要输入六个数,再往后有两个循环,一个是保证每个数都不一样,另一个是保证每个数都小于等于6,也就是说,只能输入1 2 3 4 5 6,但是顺序不确定,之后是待保输入数组的值的范围在1 ~ 6且不存在重复值;再往后用7减去输入数组的每个元素,相当于求补。之后出现了一个常数地址0x804c13c,打印发现里面的内容是281,不知道是啥,但是有个node节点,再往后看看有啥,打印一下地址,发现,是一个链表,最后的next都指向了下一个节点,最后指向NULL。而地址里有六个数,分别如下表。

1 2 3 4 5 6
281 438 714 78 962 875

之后是根据前面构建的地址数组,修改结构体数组的next的值,实现单链表的排序,要求单链表递减排序,若满足要求,那么拆弹成功。也就是说排序顺序为5 6 3 2 1 4。而且前面有一个7-x的操作也就是答案为2 1 4 5 6 3。

secret_phase

因为之前说过有个隐藏炸弹,正好在做phase_6的时候发现了一个叫secret_phase的函数,发现只有通过phase_defused这个函数才能调用这个隐藏函数,而phase_defused函数在main函数里每一次调用完相应的六个函数之后都会调用,但是在前面的拆弹过程中没有体现出来,比如说phase_1:

1
2
8048a81:	e8 aa 00 00 00       	call   8048b30 <phase_1>
8048a86: e8 83 08 00 00 call 804930e <phase_defused>

defused函数如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
0804930e <phase_defused>:
804930e: 55 push %ebp
804930f: 89 e5 mov %esp,%ebp
8049311: 83 ec 68 sub $0x68,%esp
8049314: 65 a1 14 00 00 00 mov %gs:0x14,%eax
804931a: 89 45 f4 mov %eax,-0xc(%ebp)
804931d: 31 c0 xor %eax,%eax
804931f: 83 3d cc c3 04 08 06 cmpl $0x6,0x804c3cc #这个地址里存放着输入的字符串个数,也就是说,只有执行完上面六个phase之后才能解锁这个隐藏函数
8049326: 75 6f jne 8049397 <phase_defused+0x89>
8049328: 83 ec 0c sub $0xc,%esp
804932b: 8d 45 a4 lea -0x5c(%ebp),%eax
804932e: 50 push %eax
804932f: 8d 45 a0 lea -0x60(%ebp),%eax
8049332: 50 push %eax
8049333: 8d 45 9c lea -0x64(%ebp),%eax
8049336: 50 push %eax
8049337: 68 69 a3 04 08 push $0x804a369 #%d %d %s
804933c: 68 d0 c4 04 08 push $0x804c4d0 #<input_strings+240>: ""
8049341: e8 ca f4 ff ff call 8048810 <__isoc99_sscanf@plt>
8049346: 83 c4 20 add $0x20,%esp
8049349: 83 f8 03 cmp $0x3,%eax #输入三个
804934c: 75 39 jne 8049387 <phase_defused+0x79>
804934e: 83 ec 08 sub $0x8,%esp
8049351: 68 72 a3 04 08 push $0x804a372 # 0x804a372 -> DrEvil
8049356: 8d 45 a4 lea -0x5c(%ebp),%eax
8049359: 50 push %eax
804935a: e8 47 fd ff ff call 80490a6 <strings_not_equal> #要找个地方输入 DrEvil
804935f: 83 c4 10 add $0x10,%esp
8049362: 85 c0 test %eax,%eax
8049364: 75 21 jne 8049387 <phase_defused+0x79>
8049366: 83 ec 0c sub $0xc,%esp
8049369: 68 38 a2 04 08 push $0x804a238 #Curses, you've found the secret phase!
804936e: e8 4d f4 ff ff call 80487c0 <puts@plt>
8049373: c7 04 24 60 a2 04 08 movl $0x804a260,(%esp) #But finding it and solving it are quite different...
804937a: e8 41 f4 ff ff call 80487c0 <puts@plt>
804937f: e8 20 fc ff ff call 8048fa4 <secret_phase>
8049384: 83 c4 10 add $0x10,%esp
8049387: 83 ec 0c sub $0xc,%esp
804938a: 68 98 a2 04 08 push $0x804a298 #"Congratulations! You've defused the bomb!"

804938f: e8 2c f4 ff ff call 80487c0 <puts@plt>
8049394: 83 c4 10 add $0x10,%esp
8049397: 8b 45 f4 mov -0xc(%ebp),%eax
804939a: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
80493a1: 74 05 je 80493a8 <phase_defused+0x9a>
80493a3: e8 e8 f3 ff ff call 8048790 <__stack_chk_fail@plt>
80493a8: c9 leave
80493a9: c3 ret

分析第27行,因为 调用了string_not_equal函数,之前push了0x804a372 (DrEvil)也就是说要找一个地方输入这个字符串,又因为%d %d %s,猜测是在第四个或者第五个之后输入,在第四个尝试之后成功了。接下来就是secret-phase了。

secret_phase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
08048fa4 <secret_phase>:
8048fa4: 55 push %ebp
8048fa5: 89 e5 mov %esp,%ebp
8048fa7: 53 push %ebx
8048fa8: 83 ec 04 sub $0x4,%esp
8048fab: e8 5b 02 00 00 call 804920b <read_line>
8048fb0: 83 ec 04 sub $0x4,%esp
8048fb3: 6a 0a push $0xa
8048fb5: 6a 00 push $0x0
8048fb7: 50 push %eax
8048fb8: e8 c3 f8 ff ff call 8048880 <strtol@plt>
8048fbd: 89 c3 mov %eax,%ebx
8048fbf: 8d 40 ff lea -0x1(%eax),%eax
8048fc2: 83 c4 10 add $0x10,%esp
8048fc5: 3d e8 03 00 00 cmp $0x3e8,%eax
8048fca: 76 05 jbe 8048fd1 <secret_phase+0x2d>
8048fcc: e8 d8 01 00 00 call 80491a9 <explode_bomb>
8048fd1: 83 ec 08 sub $0x8,%esp
8048fd4: 53 push %ebxr
8048fd5: 68 88 c0 04 08 push $0x804c088 #"$"
8048fda: e8 73 ff ff ff call 8048f52 <fun7>
8048fdf: 83 c4 10 add $0x10,%esp
8048fe2: 83 f8 03 cmp $0x3,%eax #fun7返回值必须为3
8048fe5: 74 05 je 8048fec <secret_phase+0x48>
8048fe7: e8 bd 01 00 00 call 80491a9 <explode_bomb>
8048fec: 83 ec 0c sub $0xc,%esp
8048fef: 68 5c a1 04 08 push $0x804a15c #Wow! You've defused the secret stage!
8048ff4: e8 c7 f7 ff ff call 80487c0 <puts@plt>
8048ff9: e8 10 03 00 00 call 804930e <phase_defused>
8048ffe: 83 c4 10 add $0x10,%esp
8049001: 8b 5d fc mov -0x4(%ebp),%ebx
8049004: c9 leave
8049005: c3 ret

根据第23行,也就是说调用fun7之后,返回值必须是3,这样就结束了。

fun7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
08048f52 <fun7>:
8048f52: 55 push %ebp
8048f53: 89 e5 mov %esp,%ebp
8048f55: 53 push %ebx
8048f56: 83 ec 04 sub $0x4,%esp
8048f59: 8b 55 08 mov 0x8(%ebp),%edx
8048f5c: 8b 4d 0c mov 0xc(%ebp),%ecx
8048f5f: 85 d2 test %edx,%edx
8048f61: 74 37 je 8048f9a <fun7+0x48>
8048f63: 8b 1a mov (%edx),%ebx
8048f65: 39 cb cmp %ecx,%ebx
8048f67: 7e 13 jle 8048f7c <fun7+0x2a>
8048f69: 83 ec 08 sub $0x8,%esp
8048f6c: 51 push %ecx
8048f6d: ff 72 04 pushl 0x4(%edx)
8048f70: e8 dd ff ff ff call 8048f52 <fun7>
8048f75: 83 c4 10 add $0x10
,%esp
8048f78: 01 c0 add %eax,%eax
8048f7a: eb 23 jmp 8048f9f <fun7+0x4d>
8048f7c: b8 00 00 00 00 mov $0x0,%eax
8048f81: 39 cb cmp %ecx,%ebx
8048f83: 74 1a je 8048f9f <fun7+0x4d>
8048f85: 83 ec 08 sub $0x8,%esp
8048f88: 51 push %ecx
8048f89: ff 72 08 pushl 0x8(%edx)
8048f8c: e8 c1 ff ff ff call 8048f52 <fun7>
8048f91: 83 c4 10 add $0x10,%esp
8048f94: 8d 44 00 01 lea 0x1(%eax,%eax,1),%eax
8048f98: eb 05 jmp 8048f9f <fun7+0x4d>
8048f9a: b8 ff ff ff ff mov $0xffffffff,%eax
8048f9f: 8b 5d fc mov -0x4(%ebp),%ebx
8048fa2: c9 leave
8048fa3: c3 ret
1
2
3
4
5
6
int func7(int *a, int b){

if (b== *a) return 0;
else if(*a>b) return 2*fun7(x+4,y); //root->left
else return 2*fun7(x+8,y)+1;//root—>right
}

这是fun7的c代码,是一个和fun4很像的递归代码。最后一个数是3,那么上一个就是1,再上一个就是0,二叉树方向:root->right->right。从节点最初在secret_phase中传入的地址作为根节点开始往回找,

1576647719(1).png

也就是0x6b=107

至此所有的炸弹都拆完了。

1576641101(1).png

0%