没时间看CSAPP?那总要看看实验吧——BOMBLAB| 牛气冲天新年正文

213 阅读7分钟

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行以前是输入六个数,并判断第一个数小于等于6
  • r12d很明显是循环中的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减索引即可