0. 本节内容
在本次实验中,我们通过反编译的手段,获得bomb.s,并根据汇编代码得到线索,获取正确的六个输入,解除炸弹
准备
objdump -d bomb > bomb.s反编译获得汇编代码bomb.s
1. 线索一
找到phase_1代码
第一个代码很简单
其中,
400eee 行 test %eax, %eax,如果%eax为0,则跳转,否则执行爆炸函数
上面是一个调用函数callq 401338,其中第二个参数为$0x402400
我们通过gdb x/s来查看内存中的值
(gdb) x/s 0x402400
0x402400:"Border relations with Canada have never been better."
找到strings_not_equal函数
0000000000401338 <strings_not_equal>:
401338: 41 54 push %r12
40133a: 55 push %rbp
40133b: 53 push %rbx
40133c: 48 89 fb mov %rdi,%rbx
40133f: 48 89 f5 mov %rsi,%rbp
401342: e8 d4 ff ff ff callq 40131b <string_length>
401347: 41 89 c4 mov %eax,%r12d
40134a: 48 89 ef mov %rbp,%rdi
40134d: e8 c9 ff ff ff callq 40131b <string_length>
401352: ba 01 00 00 00 mov $0x1,%edx
401357: 41 39 c4 cmp %eax,%r12d
40135a: 75 3f jne 40139b <strings_not_equal+0x63>
40135c: 0f b6 03 movzbl (%rbx),%eax
40135f: 84 c0 test %al,%al
401361: 74 25 je 401388 <strings_not_equal+0x50>
401363: 3a 45 00 cmp 0x0(%rbp),%al
401366: 74 0a je 401372 <strings_not_equal+0x3a>
401368: eb 25 jmp 40138f <strings_not_equal+0x57>
40136a: 3a 45 00 cmp 0x0(%rbp),%al
40136d: 0f 1f 00 nopl (%rax)
401370: 75 24 jne 401396 <strings_not_equal+0x5e>
401372: 48 83 c3 01 add $0x1,%rbx
401376: 48 83 c5 01 add $0x1,%rbp
40137a: 0f b6 03 movzbl (%rbx),%eax
40137d: 84 c0 test %al,%al
40137f: 75 e9 jne 40136a <strings_not_equal+0x32>
401381: ba 00 00 00 00 mov $0x0,%edx
401386: eb 13 jmp 40139b <strings_not_equal+0x63>
401388: ba 00 00 00 00 mov $0x0,%edx
40138d: eb 0c jmp 40139b <strings_not_equal+0x63>
40138f: ba 01 00 00 00 mov $0x1,%edx
401394: eb 05 jmp 40139b <strings_not_equal+0x63>
401396: ba 01 00 00 00 mov $0x1,%edx
40139b: 89 d0 mov %edx,%eax
40139d: 5b pop %rbx
40139e: 5d pop %rbp
40139f: 41 5c pop %r12
4013a1: c3 retq
代码有点长哈,不过我们知道第二个参数存储在%rsi中,通过不断追踪%rsi中的值的移动,我们发现将其与%al比较,若一样,则返回0,因此对于第一个炸弹,我们仅需要输入
"Border relations with Canada have never been better." 即可。
2. 线索二
找到phase_2代码
- 最边缘的push pop 都是处理被调用者保存器,就当他们不存在(如果需要解释的话留言即可)
- 我们看到很快就进入了
read_six_numbers中
- 可以注意到熟悉的
mov $0x4025c3, %esi
(gdb) x/s 0x4025c3
0x4025c3: "%d %d %d %d %d %d"
-
这行上面的部分则分别将几个参数放入寄存器中
-
%rsi 存储在phase_2里面传入的%rsp的值也就是栈帧的起始地址
-
%rdx,由%rsi给出,%rsi又由phrase_2的%rsp给出,所以phrase2中的%rsp地址处存放sscanf中第一个输入的值
-
%rcx也就是在phase_2%rsp+0x4中存放着第二个值
-
%r8也就是在phase_2%rsp+0x8中存放着第三个值
-
%r9也就是在phase_2%rsp+0xc中存放着第四个值
-
在该函数的%rsp 中存放着第五个值也就是我们把0x10(%rsi),%rax放进了rsp
-
在该函数的%rsp+0x8 中存放着第六个值也就是我们把0x14(%rsi),%rax放进了rsp+0x8中 再看
phase_2 -
cmpl $0x1,(%rsp)要求第一个参数为1 -
400f30: 48 8d 5c 24 04 lea 0x4(%rsp),%rbx参数为一则跳转到本行,将(rsp)+ 0x4赋给了rbp -
- 第二个参数为第一个的二倍
400f17: 8b 43 fc mov -0x4(%rbx),%eax
400f1a: 01 c0 add %eax,%eax
400f1c: 39 03 cmp %eax,(%rbx)
- 我们发现接下来就是一个循环,所以数字为
1,2,4,8,16,32
3.线索三
找到phase_3代码
- 跟随我的目光迅速找到
rcx,rbx - 再次找到
mov $0x4025cf,%esi,gdb查看发现这个是"%d %d" cmpl $0x7,0x8(%rsp)要求rdx小于7- 后面代码看起来很长但有好似有规律性,重点在于
jmpq *0x402470(,%rax,8)这行,会根据你的第一个参数值选择不同的代码 - 以0为例子,
mov $0xcf, &eax, 果断gdb康一康发现是207 - 散会!
4. 线索四
找到phase_4代码
- 前几行略,注意下cmpl $0xe 0x8(%rsp)[也就是rdx 输入的第一个参数]
- 接下来需要调用函数
func4,其中,rdi: 0x8(%rsp), rsi : 0, rdx : $0xe ,有`func4(arg1,0,14)
接下来看func4
- 看起来经过复杂的计算,但其实rsi为0,所以很简单
- 当
if rdi>=7的时候 则会跳转到0x400ff2我们不妨输入rdi=7 0x400ff2后,比较rdi和rcx,此时rcx为7,如果rdi <= 7 则跳出,否则调用func4- 因此 答案:7 0
5. 线索五
找到phase_5代码
- 首先可以看到
40107f要求字符串长度为6 - 根据
jne 40108b我们发现这次又是一个递归(老套路了) - 查看
0x402542的值是“flyers”,我们要保证"(%rsp+10)的值为flyers" - 需要注意的是
mov %cl, (%rsp)和and $0xf, %edx算是两个比较常见的取低几位的方式 movzbl 0x4024b0(%rdx),%edx,将rdx+ *0x4024b0地址的值赋给rdx,根据前面代码,我们知道rdx其实是每次输入的字符,而我们发现0x4024b0又是一个字符串,也就是通过字符串,拼写出flyers
6. 线索六
找到phase_6代码
略长
00000000004010f4 <phase_6>:
4010f4: 41 56 push %r14
4010f6: 41 55 push %r13
4010f8: 41 54 push %r12
4010fa: 55 push %rbp
4010fb: 53 push %rbx
4010fc: 48 83 ec 50 sub $0x50,%rsp
401100: 49 89 e5 mov %rsp,%r13
401103: 48 89 e6 mov %rsp,%rsi
401106: e8 51 03 00 00 callq 40145c <read_six_numbers>
40110b: 49 89 e6 mov %rsp,%r14
40110e: 41 bc 00 00 00 00 mov $0x0,%r12d
401114: 4c 89 ed mov %r13,%rbp
401117: 41 8b 45 00 mov 0x0(%r13),%eax
40111b: 83 e8 01 sub $0x1,%eax
40111e: 83 f8 05 cmp $0x5,%eax
401121: 76 05 jbe 401128 <phase_6+0x34>
401123: e8 12 03 00 00 callq 40143a <explode_bomb>
401128: 41 83 c4 01 add $0x1,%r12d
40112c: 41 83 fc 06 cmp $0x6,%r12d
401130: 74 21 je 401153 <phase_6+0x5f>
401132: 44 89 e3 mov %r12d,%ebx
401135: 48 63 c3 movslq %ebx,%rax
401138: 8b 04 84 mov (%rsp,%rax,4),%eax
40113b: 39 45 00 cmp %eax,0x0(%rbp)
40113e: 75 05 jne 401145 <phase_6+0x51>
401140: e8 f5 02 00 00 callq 40143a <explode_bomb>
401145: 83 c3 01 add $0x1,%ebx
401148: 83 fb 05 cmp $0x5,%ebx
40114b: 7e e8 jle 401135 <phase_6+0x41>
40114d: 49 83 c5 04 add $0x4,%r13
401151: eb c1 jmp 401114 <phase_6+0x20>
401153: 48 8d 74 24 18 lea 0x18(%rsp),%rsi
401158: 4c 89 f0 mov %r14,%rax
40115b: b9 07 00 00 00 mov $0x7,%ecx
401160: 89 ca mov %ecx,%edx
401162: 2b 10 sub (%rax),%edx
401164: 89 10 mov %edx,(%rax)
401166: 48 83 c0 04 add $0x4,%rax
40116a: 48 39 f0 cmp %rsi,%rax
40116d: 75 f1 jne 401160 <phase_6+0x6c>
40116f: be 00 00 00 00 mov $0x0,%esi
401174: eb 21 jmp 401197 <phase_6+0xa3>
401176: 48 8b 52 08 mov 0x8(%rdx),%rdx
40117a: 83 c0 01 add $0x1,%eax
40117d: 39 c8 cmp %ecx,%eax
40117f: 75 f5 jne 401176 <phase_6+0x82>
401181: eb 05 jmp 401188 <phase_6+0x94>
401183: ba d0 32 60 00 mov $0x6032d0,%edx
401188: 48 89 54 74 20 mov %rdx,0x20(%rsp,%rsi,2)
40118d: 48 83 c6 04 add $0x4,%rsi
401191: 48 83 fe 18 cmp $0x18,%rsi
401195: 74 14 je 4011ab <phase_6+0xb7>
401197: 8b 0c 34 mov (%rsp,%rsi,1),%ecx
40119a: 83 f9 01 cmp $0x1,%ecx
40119d: 7e e4 jle 401183 <phase_6+0x8f>
40119f: b8 01 00 00 00 mov $0x1,%eax
4011a4: ba d0 32 60 00 mov $0x6032d0,%edx
4011a9: eb cb jmp 401176 <phase_6+0x82>
4011ab: 48 8b 5c 24 20 mov 0x20(%rsp),%rbx
4011b0: 48 8d 44 24 28 lea 0x28(%rsp),%rax
4011b5: 48 8d 74 24 50 lea 0x50(%rsp),%rsi
4011ba: 48 89 d9 mov %rbx,%rcx
4011bd: 48 8b 10 mov (%rax),%rdx
4011c0: 48 89 51 08 mov %rdx,0x8(%rcx)
4011c4: 48 83 c0 08 add $0x8,%rax
4011c8: 48 39 f0 cmp %rsi,%rax
4011cb: 74 05 je 4011d2 <phase_6+0xde>
4011cd: 48 89 d1 mov %rdx,%rcx
4011d0: eb eb jmp 4011bd <phase_6+0xc9>
4011d2: 48 c7 42 08 00 00 00 movq $0x0,0x8(%rdx)
4011d9: 00
4011da: bd 05 00 00 00 mov $0x5,%ebp
4011df: 48 8b 43 08 mov 0x8(%rbx),%rax
4011e3: 8b 00 mov (%rax),%eax
4011e5: 39 03 cmp %eax,(%rbx)
4011e7: 7d 05 jge 4011ee <phase_6+0xfa>
4011e9: e8 4c 02 00 00 callq 40143a <explode_bomb>
4011ee: 48 8b 5b 08 mov 0x8(%rbx),%rbx
4011f2: 83 ed 01 sub $0x1,%ebp
4011f5: 75 e8 jne 4011df <phase_6+0xeb>
4011f7: 48 83 c4 50 add $0x50,%rsp
4011fb: 5b pop %rbx
4011fc: 5d pop %rbp
4011fd: 41 5c pop %r12
4011ff: 41 5d pop %r13
401201: 41 5e pop %r14
401203: c3 retq
既然长就分着看
输入部分
4010f4 - 401151
- 前几行push是被调用者保存寄存器,不用管
401121行以前是输入六个数,并判断第一个数小于等于6r12d很明显是循环中的i,而40112c: 41 83 fc 06 cmp $0x6,%r12d告诉我们要循环几次,- 后面是费劲周张的两个循环,判断六个参数是否小于6的同时也判断是否互相不等。
七减参数
401153 - 40116d 这部分很简单,就是用七减去六个参数
链表
mov $0x6032d0,%edx查看这部分地址发现了链表的存在-
40117d: 39 c8 cmp %ecx,%eax 40117f: 75 f5 jne 401176 <phase_6+0x82> ```这部分可以看出,是一个之前7-参数次数的循环 %rdx,0x20(%rsp,%rsi,2)将从链表中读入的数存入rdx- 最后是按照大小排序,其数组索引为3 4 5 6 1 2,7减索引即可