CSAPP BombLab

背景

大三上的《系统级程序设计》使用了CMU的经典教材CSAPP(Computer System: A Programmer’s Perspective),其实对这门课早有耳闻,是CMU的神课。正好大三上学期学校安排了这门课,而且是大三上学期唯一一门专业必修课,也让人很期待。

这门课,确实是很有质量的课。原因如下:

  • 上课用的是CMU原版全英文的PPT,增加对一些常见的计算机组成的英文词汇的了解。
  • 设置了助教,并且会让助教在课上演示实际代码的运行情况(很多专业课都没有)
  • 老师讲的很好,能够看出来对这门课的教学经验很足

BombLab是设置的第一次实验,助教课上演示了第一关的过关方法,并提醒我们一些注意事项:每个人下载的代码都不一样等等

实验记录

软件包构成:

  • bomb(可执行文件)
  • bomb.c
  • Readme(记录学号和编号)

前置知识:

X86-64有16个64位寄存器,每一个的用途:

img

img

X86-64的栈帧结构:https://www.jianshu.com/p/997dddb3122c

https://zhuanlan.zhihu.com/p/27339191

objdump:objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息。

GDB :gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具。

gdb_quickreference:

image-20211101135039742

image-20211101135134390

由于我使用的是macOS,又不希望安装庞大的虚拟机软件占用空间,因此选择使用docker配置环境,建立了一个ubuntu的容器。

使用docker cp 命令将文件夹copy到容器下,安装gcc,gdb,objdump,vim

apt update //升级apt
apt install build-essential
apt install binutils
apt install vim

拆弹思路:

因为每一关都是输入一段正确的字符串通关。阅读bomb.c文件,可以发现每一关都是一个函数phase_x(),却没有提供函数体,因此,需要对可执行文件进行反汇编,阅读汇编代码,找到输入的参数,再分析如何避免引爆炸弹。(其实使用IDA反编译可以直接看到源码,但是这样达不到效果,因为这个实验就是锻炼阅读汇编代码的能力,但其实不会的部分还是参考了IDA的反编译代码,后面几关,尤其是最后一关还挺难理解的)

phase_1

使用objdump命令,将bomb可执行程序反汇编,保存到bomb.txt文件

objdump -d bomb > bomb.txt
gdb -q bomb //进入调试
disas phase_1

显示结果及分析如下:

Dump of assembler code for function phase_1:
   0x0000558037001204 <+0>:	sub    $0x8,%rsp  #开栈
   0x0000558037001208 <+4>:	lea    0x17c1(%rip),%rsi        # 0x5580370029d0 #rsi = rip + 0x17c1,rdi为第一个参数,rsi为第二个参数。接着调用string_not_equal函数,可以大胆猜测这里的rsi存放的地址就是标准答案的字符串的地址
   0x000055803700120f <+11>:	callq  0x558037001706 <strings_not_equal> #调用string_not_equal函数
   0x0000558037001214 <+16>:	test   %eax,%eax #eax为string_not_eaual的返回值,为0或1,与运算后设置标志位也为0或1
   0x0000558037001216 <+18>:	jne    0x55803700121d <phase_1+25> #,跟据标志位跳转,两字符串不相等就跳转到explode_bomb
   0x0000558037001218 <+20>:	add    $0x8,%rsp
   0x000055803700121c <+24>:	retq   
   0x000055803700121d <+25>:	callq  0x558037001996 <explode_bomb>
   0x0000558037001222 <+30>:	jmp    0x558037001218 <phase_1+20>

在0x000055803700120f打断点:

b *0x000055803700120f
c //继续运行

在0x0000558037001208指令执行完后,查看所有寄存器内容:

 info all-registers

可以找到rsi寄存器存放的地址为:0x5580370029d0

rsi存放的地址也可以看到

查看该地址存放的内容:

x/s 0x5580370029d0

输出:

0x5580370029d0:	"I am just a renegade hockey mom."

执行程序

./bomb

输入上面的字符串,显示进入下一关:

Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
I am just a renegade hockey mom.
Phase 1 defused. How about the next one?

我们也可以看rdi的值是不是输入的字符串

(gdb) x/s 0x560d15a046c0
0x560d15a046c0 <input_strings>:	"test"

可以看到rdi存放的值确实是我测试输入的字符串test

小插曲:

​ 执行./bomb时,电脑网恰好断了,程序运行不了,提示如下:

# ./bomb 

Initialization error:

Error: DNS is unable to resolve server address

说明程序是联网的,果然会记录你每一关爆炸的次数(CMU原版的是这样说的,武大的版本是把爆炸次数发给课程的服务器)

phase_2

采用同样的方法:

0000000000001224 <phase_2>:
    1224:	55                   	push   %rbp
    1225:	53                   	push   %rbx
    1226:	48 83 ec 28          	sub    $0x28,%rsp #开栈
    122a:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax # rax = 0x28
    1231:	00 00 
    1233:	48 89 44 24 18       	mov    %rax,0x18(%rsp)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ) #这里就说明了有6个参数0x18 = 24 = 4 * 6,int32是4个字节,总共有6个
    1238:	31 c0                	xor    %eax,%eax
    123a:	48 89 e6             	mov    %rsp,%rsi #rsi = rsp
    123d:	e8 90 07 00 00       	callq  19d2 <read_six_numbers> #可以看出是输入6个数字
    1242:	83 3c 24 00          	cmpl   $0x0,(%rsp) # rsp - 0,rsp此时指向第一个参数
    1246:	78 0a                	js     1252 <phase_2+0x2e> #js:结果为负则转移,1252就是explode_bomb,说明rsp - 0 >= 0不会爆炸,即rsp >= 0,第一个参数要非负
    1248:	bb 01 00 00 00       	mov    $0x1,%ebx #ebx = 0x1
    124d:	48 89 e5             	mov    %rsp,%rbp #rbp指向第一个参数
    1250:	eb 11                	jmp    1263 <phase_2+0x3f>
    1252:	e8 3f 07 00 00       	callq  1996 <explode_bomb>
    1257:	eb ef                	jmp    1248 <phase_2+0x24>
    1259:	48 83 c3 01          	add    $0x1,%rbx  # rbx = rbx + 0x1 = 0x2
    125d:	48 83 fb 06          	cmp    $0x6,%rbx  #rbx 与0x6比较
    1261:	74 13                	je     1276 <phase_2+0x52> #相等则跳转
    1263:	89 d8                	mov    %ebx,%eax #从1250跳转过来,第一次,eax = ebx = 0x1
    1265:	03 44 9d fc          	add    -0x4(%rbp,%rbx,4),%eax  #eax =eax + %rbp + 4%rbx -0x4 = eax, rbx在循环中为1,2,3...所以每次等于数组中的上一个元素,即eax = eax + a[i-1]
    1269:	39 44 9d 00          	cmp    %eax,0x0(%rbp,%rbx,4) #将eax与a[i] 比较,如果a[i] != eax,爆炸
    126d:	74 ea                	je     1259 <phase_2+0x35>
    126f:	e8 22 07 00 00       	callq  1996 <explode_bomb>
    1274:	eb e3                	jmp    1259 <phase_2+0x35>
    1276:	48 8b 44 24 18       	mov    0x18(%rsp),%rax #从1261跳转过来, rax=rsp + 0x18
    127b:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax 
    1282:	00 00 
    1284:	75 07                	jne    128d <phase_2+0x69>
    1286:	48 83 c4 28          	add    $0x28,%rsp
    128a:	5b                   	pop    %rbx
    128b:	5d                   	pop    %rbp
    128c:	c3                   	retq   
    128d:	e8 be fb ff ff       	callq  e50 <__stack_chk_fail@plt>

所以输入的6个数满足如下关系:

if(a[0] < 0) bomb();
b = 1;
i = 1;
while(b != 6){
	a[i] = a[i-1] + b;
	b++;
}

可以列举出来一个符合条件的数组如:[0, 1, 3, 6, 10, 15]

输入:0 1 3 6 10 15

程序输出:

That's number 2.  Keep going!

第二关顺利通过

phase_3

汇编代码:

0000000000001292 <phase_3>:
    1292:       48 83 ec 18             sub    $0x18,%rsp #开栈
    1296:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax 
    129d:       00 00
    129f:       48 89 44 24 08          mov    %rax,0x8(%rsp) 
    12a4:       31 c0                   xor    %eax,%eax 
    12a6:       48 8d 4c 24 04          lea    0x4(%rsp),%rcx 
    12ab:       48 89 e2                mov    %rsp,%rdx
    12ae:       48 8d 35 a8 19 00 00    lea    0x19a8(%rip),%rsi        # 2c5d <array.3415+0x21d> #输入参数
    12b5:       e8 36 fc ff ff          callq  ef0 <__isoc99_sscanf@plt> #输入
    12ba:       83 f8 01                cmp    $0x1,%eax #输入参数的个数 <= 1,jle跳转到引爆炸弹
    12bd:       7e 1d                   jle    12dc <phase_3+0x4a>
    12bf:       83 3c 24 07             cmpl   $0x7,(%rsp)
    12c3:       0f 87 99 00 00 00       ja     1362 <phase_3+0xd0>
    12c9:       8b 04 24                mov    (%rsp),%eax
    12cc:       48 8d 15 4d 17 00 00    lea    0x174d(%rip),%rdx        # 2a20 <_IO_stdin_used+0x1a0>
    12d3:       48 63 04 82             movslq (%rdx,%rax,4),%rax
    12d7:       48 01 d0                add    %rdx,%rax 
    12da:       ff e0                   jmpq   *%rax #根据rax的值在跳转表中跳转
    12dc:       e8 b5 06 00 00          callq  1996 <explode_bomb>
    12e1:       eb dc                   jmp    12bf <phase_3+0x2d> 
    12e3:       b8 b3 00 00 00          mov    $0xb3,%eax #case0: eax = 179
    12e8:       eb 05                   jmp    12ef <phase_3+0x5d>
    12ea:       b8 00 00 00 00          mov    $0x0,%eax
    12ef:       2d 05 03 00 00          sub    $0x305,%eax #-773,
    12f4:       05 57 02 00 00          add    $0x257,%eax #+599
    12f9:       2d 88 01 00 00          sub    $0x188,%eax #-392
    12fe:       05 88 01 00 00          add    $0x188,%eax #+392
    1303:       2d 88 01 00 00          sub    $0x188,%eax #-392
    1308:       05 88 01 00 00          add    $0x188,%eax #+392
    130d:       2d 88 01 00 00          sub    $0x188,%eax #-392
    1312:       83 3c 24 05             cmpl   $0x5,(%rsp) #第一个参数 > 5,炸
    1316:       7f 06                   jg     131e <phase_3+0x8c>
    1318:       39 44 24 04             cmp    %eax,0x4(%rsp) #第二个参数 != 经过处理完的数,炸
    131c:       74 05                   je     1323 <phase_3+0x91>
    131e:       e8 73 06 00 00          callq  1996 <explode_bomb>
    1323:       48 8b 44 24 08          mov    0x8(%rsp),%rax
    1328:       64 48 33 04 25 28 00    xor    %fs:0x28,%rax
    132f:       00 00
    1331:       75 3b                   jne    136e <phase_3+0xdc>
    1333:       48 83 c4 18             add    $0x18,%rsp
    1337:       c3                      retq
    1338:       b8 00 00 00 00          mov    $0x0,%eax #case 1
    133d:       eb b5                   jmp    12f4 <phase_3+0x62>
    133f:       b8 00 00 00 00          mov    $0x0,%eax #case 2
		1344:       eb b3                   jmp    12f9 <phase_3+0x67>
    1346:       b8 00 00 00 00          mov    $0x0,%eax #case 3
    134b:       eb b1                   jmp    12fe <phase_3+0x6c>
    134d:       b8 00 00 00 00          mov    $0x0,%eax #case 4
    1352:       eb af                   jmp    1303 <phase_3+0x71>
    1354:       b8 00 00 00 00          mov    $0x0,%eax #case 5
    1359:       eb ad                   jmp    1308 <phase_3+0x76>
    135b:       b8 00 00 00 00          mov    $0x0,%eax #case 6
    1360:       eb ab                   jmp    130d <phase_3+0x7b>
    1362:       e8 2f 06 00 00          callq  1996 <explode_bomb>
    1367:       b8 00 00 00 00          mov    $0x0,%eax #case 7
    136c:       eb a4                   jmp    1312 <phase_3+0x80>
    136e:       e8 dd fa ff ff          callq  e50 <__stack_chk_fail@plt>

这一关汇编代码比较长,但是可以看出很有规律,后面全是jmp和mov,其实是swich-case语句

先看

12ae:       48 8d 35 a8 19 00 00    lea    0x19a8(%rip),%rsi        # 2c5d <array.3415+0x21d> 
12b5:       e8 36 fc ff ff          callq  ef0 <__isoc99_sscanf@plt> #输入

12b5调用了sccanf,能猜出来是在输入,在该处打断点,查看rsi的值,发现为

rsi            0x56413d802c5d      94838204673117
x/s 0x56413d802c5d

输出:

0x56413d802c5d:	"%d %d" #说明输入两个整数
12bf:       83 3c 24 07             cmpl   $0x7,(%rsp)

说明输入第一个的数字<7,下一条的ja说明第一个数字>=0

后面分析起来很乱,借助ida的流程图:

image-20211101153055084

image-20211101153742392

可以看到下面是一个跳转表,根据第一个参数的数值进行跳转的表

结合上面的汇编代码,可以知道是有多个答案的

假设第一个参数为0,则过程为:

进入case 0 –> eax = 710 –> eax -= 773 –>eax +=599 –>eax -= 392 –>eax += 392 –> eax-=392 –>eax += 392

–>eax-=392 最后eax = -387。而eax必须和输入的第二个参数相等,所以第二个参数为-387

所以其中一个答案为:0, -387

phase_4

    13ac:       48 83 ec 18             sub    $0x18,%rsp
    13b0:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
    13b7:       00 00
    13b9:       48 89 44 24 08          mov    %rax,0x8(%rsp)
    13be:       31 c0                   xor    %eax,%eax
    13c0:       48 89 e1                mov    %rsp,%rcx
    13c3:       48 8d 54 24 04          lea    0x4(%rsp),%rdx
    13c8:       48 8d 35 8e 18 00 00    lea    0x188e(%rip),%rsi        # 2c5d <array.3415+0x21d>
    13cf:       e8 1c fb ff ff          callq  ef0 <__isoc99_sscanf@plt>
    13d4:       83 f8 02                cmp    $0x2,%eax
    13d7:       75 0b                   jne    13e4 <phase_4+0x38>
    13d9:       8b 04 24                mov    (%rsp),%eax
    13dc:       83 e8 02                sub    $0x2,%eax
    13df:       83 f8 02                cmp    $0x2,%eax
    13e2:       76 05                   jbe    13e9 <phase_4+0x3d>
    13e4:       e8 ad 05 00 00          callq  1996 <explode_bomb>
    13e9:       8b 34 24                mov    (%rsp),%esi
    13ec:       bf 09 00 00 00          mov    $0x9,%edi
    13f1:       e8 7d ff ff ff          callq  1373 <func4>
    13f6:       39 44 24 04             cmp    %eax,0x4(%rsp)
    13fa:       74 05                   je     1401 <phase_4+0x55>
    13fc:       e8 95 05 00 00          callq  1996 <explode_bomb>
    1401:       48 8b 44 24 08          mov    0x8(%rsp),%rax
    1406:       64 48 33 04 25 28 00    xor    %fs:0x28,%rax
    140d:       00 00
    140f:       75 05                   jne    1416 <phase_4+0x6a>
    1411:       48 83 c4 18             add    $0x18,%rsp
    1415:       c3                      retq
    1416:       e8 35 fa ff ff          callq  e50 <__stack_chk_fail@plt>

Func4:

0000000000001373 <func4>:
    1373:       b8 00 00 00 00          mov    $0x0,%eax
    1378:       85 ff                   test   %edi,%edi
    137a:       7e 07                   jle    1383 <func4+0x10>
    137c:       89 f0                   mov    %esi,%eax
    137e:       83 ff 01                cmp    $0x1,%edi
    1381:       75 02                   jne    1385 <func4+0x12>
    1383:       f3 c3                   repz retq
    1385:       41 54                   push   %r12
    1387:       55                      push   %rbp
    1388:       53                      push   %rbx
    1389:       41 89 f4                mov    %esi,%r12d
    138c:       89 fb                   mov    %edi,%ebx
    138e:       8d 7f ff                lea    -0x1(%rdi),%edi
    1391:       e8 dd ff ff ff          callq  1373 <func4>
    1396:       42 8d 2c 20             lea    (%rax,%r12,1),%ebp
    139a:       8d 7b fe                lea    -0x2(%rbx),%edi
    139d:       44 89 e6                mov    %r12d,%esi
    13a0:       e8 ce ff ff ff          callq  1373 <func4>
    13a5:       01 e8                   add    %ebp,%eax
    13a7:       5b                      pop    %rbx
    13a8:       5d                      pop    %rbp
    13a9:       41 5c                   pop    %r12
    13ab:       c3                      retq

phase_5

000000000000141b <phase_5>:
    141b:       48 83 ec 18             sub    $0x18,%rsp
    141f:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
    1426:       00 00
    1428:       48 89 44 24 08          mov    %rax,0x8(%rsp)
    142d:       31 c0                   xor    %eax,%eax
    142f:       48 8d 4c 24 04          lea    0x4(%rsp),%rcx
    1434:       48 89 e2                mov    %rsp,%rdx
    1437:       48 8d 35 1f 18 00 00    lea    0x181f(%rip),%rsi        # 2c5d <array.3415+0x21d>
    143e:       e8 ad fa ff ff          callq  ef0 <__isoc99_sscanf@plt>
    1443:       83 f8 01                cmp    $0x1,%eax
    1446:       7e 5a                   jle    14a2 <phase_5+0x87>
    1448:       8b 04 24                mov    (%rsp),%eax
    144b:       83 e0 0f                and    $0xf,%eax
    144e:       89 04 24                mov    %eax,(%rsp)
    1451:       83 f8 0f                cmp    $0xf,%eax
    1454:       74 32                   je     1488 <phase_5+0x6d>
    1456:       b9 00 00 00 00          mov    $0x0,%ecx
    145b:       ba 00 00 00 00          mov    $0x0,%edx
    1460:       48 8d 35 d9 15 00 00    lea    0x15d9(%rip),%rsi        # 2a40 <array.3415>
    1467:       83 c2 01                add    $0x1,%edx
    146a:       48 98                   cltq
    146c:       8b 04 86                mov    (%rsi,%rax,4),%eax
    146f:       01 c1                   add    %eax,%ecx
    1471:       83 f8 0f                cmp    $0xf,%eax
    1474:       75 f1                   jne    1467 <phase_5+0x4c>
    1476:       c7 04 24 0f 00 00 00    movl   $0xf,(%rsp)
    147d:       83 fa 0f                cmp    $0xf,%edx
    1480:       75 06                   jne    1488 <phase_5+0x6d>
    1482:       39 4c 24 04             cmp    %ecx,0x4(%rsp)
    1486:       74 05                   je     148d <phase_5+0x72>
    1488:       e8 09 05 00 00          callq  1996 <explode_bomb>
    148d:       48 8b 44 24 08          mov    0x8(%rsp),%rax
    1492:       64 48 33 04 25 28 00    xor    %fs:0x28,%rax
    1499:       00 00
    149b:       75 0c                   jne    14a9 <phase_5+0x8e>
    149d:       48 83 c4 18             add    $0x18,%rsp
    14a1:       c3                      retq
    14a2:       e8 ef 04 00 00          callq  1996 <explode_bomb>
    14a7:       eb 9f                   jmp    1448 <phase_5+0x2d>
    14a9:       e8 a2 f9 ff ff          callq  e50 <__stack_chk_fail@plt>

phase_6

00000000000014ae <phase_6>:
    14ae:       41 55                   push   %r13
    14b0:       41 54                   push   %r12
    14b2:       55                      push   %rbp
    14b3:       53                      push   %rbx
    14b4:       48 83 ec 68             sub    $0x68,%rsp
    14b8:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
    14bf:       00 00
    14c1:       48 89 44 24 58          mov    %rax,0x58(%rsp)
    14c6:       31 c0                   xor    %eax,%eax
    14c8:       49 89 e4                mov    %rsp,%r12
    14cb:       4c 89 e6                mov    %r12,%rsi
    14ce:       e8 ff 04 00 00          callq  19d2 <read_six_numbers>
    14d3:       41 bd 00 00 00 00       mov    $0x0,%r13d
    14d9:       eb 25                   jmp    1500 <phase_6+0x52>
    14db:       e8 b6 04 00 00          callq  1996 <explode_bomb>
    14e0:       eb 2d                   jmp    150f <phase_6+0x61>
    14e2:       83 c3 01                add    $0x1,%ebx
    14e5:       83 fb 05                cmp    $0x5,%ebx
    14e8:       7f 12                   jg     14fc <phase_6+0x4e>
    14ea:       48 63 c3                movslq %ebx,%rax
    14ed:       8b 04 84                mov    (%rsp,%rax,4),%eax
    14f0:       39 45 00                cmp    %eax,0x0(%rbp)
    14f3:       75 ed                   jne    14e2 <phase_6+0x34>
    14f5:       e8 9c 04 00 00          callq  1996 <explode_bomb>
    14fa:       eb e6                   jmp    14e2 <phase_6+0x34>
    14fc:       49 83 c4 04             add    $0x4,%r12
    1500:       4c 89 e5                mov    %r12,%rbp
    1503:       41 8b 04 24             mov    (%r12),%eax
    1507:       83 e8 01                sub    $0x1,%eax
    150a:       83 f8 05                cmp    $0x5,%eax
    150d:       77 cc                   ja     14db <phase_6+0x2d>
    150f:       41 83 c5 01             add    $0x1,%r13d
    1513:       41 83 fd 06             cmp    $0x6,%r13d
    1517:       74 35                   je     154e <phase_6+0xa0>
    1519:       44 89 eb                mov    %r13d,%ebx
    151c:       eb cc                   jmp    14ea <phase_6+0x3c>
    151e:       48 8b 52 08             mov    0x8(%rdx),%rdx
    1522:       83 c0 01                add    $0x1,%eax
    1525:       39 c8                   cmp    %ecx,%eax
    1527:       75 f5                   jne    151e <phase_6+0x70>
    1529:       48 89 54 f4 20          mov    %rdx,0x20(%rsp,%rsi,8)
    152e:       48 83 c6 01             add    $0x1,%rsi
    1532:       48 83 fe 06             cmp    $0x6,%rsi
    1536:       74 1d                   je     1555 <phase_6+0xa7>
    1538:       8b 0c b4                mov    (%rsp,%rsi,4),%ecx
    153b:       b8 01 00 00 00          mov    $0x1,%eax
    1540:       48 8d 15 e9 2c 20 00    lea    0x202ce9(%rip),%rdx        # 204230 <node1>
    1547:       83 f9 01                cmp    $0x1,%ecx
    154a:       7f d2                   jg     151e <phase_6+0x70>
    154c:       eb db                   jmp    1529 <phase_6+0x7b>
    154e:       be 00 00 00 00          mov    $0x0,%esi
    1553:       eb e3                   jmp    1538 <phase_6+0x8a>
    1555:       48 8b 5c 24 20          mov    0x20(%rsp),%rbx
    155a:       48 8b 44 24 28          mov    0x28(%rsp),%rax
    155f:       48 89 43 08             mov    %rax,0x8(%rbx)
    1563:       48 8b 54 24 30          mov    0x30(%rsp),%rdx
    1568:       48 89 50 08             mov    %rdx,0x8(%rax)
    156c:       48 8b 44 24 38          mov    0x38(%rsp),%rax
    1571:       48 89 42 08             mov    %rax,0x8(%rdx)
    1575:       48 8b 54 24 40          mov    0x40(%rsp),%rdx
    157a:       48 89 50 08             mov    %rdx,0x8(%rax)
    157e:       48 8b 44 24 48          mov    0x48(%rsp),%rax
    1583:       48 89 42 08             mov    %rax,0x8(%rdx)
    1587:       48 c7 40 08 00 00 00    movq   $0x0,0x8(%rax)
    158e:       00
    158f:       bd 05 00 00 00          mov    $0x5,%ebp
    1594:       eb 09                   jmp    159f <phase_6+0xf1>
    1596:       48 8b 5b 08             mov    0x8(%rbx),%rbx
    159a:       83 ed 01                sub    $0x1,%ebp
    159d:       74 11                   je     15b0 <phase_6+0x102>
    159f:       48 8b 43 08             mov    0x8(%rbx),%rax
    15a3:       8b 00                   mov    (%rax),%eax
    15a5:       39 03                   cmp    %eax,(%rbx)
    15a7:       7e ed                   jle    1596 <phase_6+0xe8>
    15a9:       e8 e8 03 00 00          callq  1996 <explode_bomb>
    15ae:       eb e6                   jmp    1596 <phase_6+0xe8>
    15b0:       48 8b 44 24 58          mov    0x58(%rsp),%rax
    15b5:       64 48 33 04 25 28 00    xor    %fs:0x28,%rax
    15bc:       00 00
    15be:       75 0b                   jne    15cb <phase_6+0x11d>
    15c0:       48 83 c4 68             add    $0x68,%rsp
    15c4:       5b                      pop    %rbx
    15c5:       5d                      pop    %rbp
    15c6:       41 5c                   pop    %r12
    15c8:       41 5d                   pop    %r13
    15ca:       c3                      retq
    15cb:       e8 80 f8 ff ff          callq  e50 <__stack_chk_fail@plt>