【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)

Binarybomb 实验(phase_1-6+secret_phase)

实验内容

一个“binary bombs”(二进制炸弹,下文将简称为炸弹)是一个Linux可执行C程序,包含了7个阶段(phase1~phase6和一个隐藏阶段)。炸弹运行的每个阶段要求学生输入一个特定的字符串,若的输入符合程序预期的输入,该阶段的炸弹就被“拆除”,否则炸弹“爆炸”并打印输出 "BOOM!!!"字样。实验的目标是拆除尽可能多的炸弹层次。
每个炸弹阶段考察了机器级语言程序的一个不同方面,难度逐级递增:

  • 阶段1:字符串比较
  • 阶段2:for循环
  • 阶段3:switch分支
  • 阶段4:递归函数
  • 阶段5:数组元素按序访问
  • 阶段6:链表
  • 隐藏阶段:只有在阶段4的拆解字符串后再附加一特定字符串后才会出现(作为最后一个阶段)

为了完成二进制炸弹拆除任务,需要使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。这可能需要在每一阶段的开始代码前和引爆炸弹的函数前设置断点,以便于调试。

实验材料:bomb程序与bomb.c文件。
请添加图片描述

实验目标

正常运行bomb程序,不执行程序内的explode_bomb函数。

实验过程

  1. 创建答案文本文件solution.txt,并随意填入7行字符串,对应phase_1-6 与 secret_phase 的破解字符串。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第1张图片
  2. 使用gdb对bomb程序进行调试,并打开可视化界面。
    打开gdb
    在这里插入图片描述
    打开可视化
    在这里插入图片描述
  3. 整体界面
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第2张图片

phase_1

实验步骤

  1. 在gdb设置断点
    在这里插入图片描述

  2. 运行bomb程序,并定位到爆炸点
    运行
    在这里插入图片描述
    定位爆炸点
    在这里插入图片描述

  3. 分析爆炸点
    爆炸点跳转是通过判定strings_not_equal函数的返回值进行跳转。故我们查看参数%rsi中的值。
    在这里插入图片描述

  4. 修改solution.txt中,phase_1的字符串为Border relations with Canada have never been better.
    在这里插入图片描述

  5. 重新运行,过关
    在这里插入图片描述

phase_2

实验步骤

  1. 在gdb中设置断点
    在这里插入图片描述

  2. 运行bomb程序,并定位爆炸点。
    在这里插入图片描述

  3. 分析爆炸点
    通过函数名可知,phase_2需要我们输入6个数字。

  4. 修改solution.txt,phase_2的字符串随意输入6个数字。
    在这里插入图片描述

  5. 重新运行,并定位爆炸点。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第3张图片

  6. 分析爆炸点
    炸弹爆炸直接原因是 %eax中的值 与 0x0(%rbp,%rbx,4) 的值不同,导致没有跳转,触发了下一条的explode_bomb
    根据前文mov %rsp,%rbp我们得出%rbp的值为%rsp的值。
    查看%rsp地址,发现%rsp为我们输入的6个数字,故%rbp为我们输入值的首地址。
    在这里插入图片描述
    再分析%rbx,很明显%rbx是1-5的一个遍历值,置于0x0(%rbp,%rbx,4)中,后者意义为遍历我们输入的第2-6个数字。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第4张图片
    再来看最后一项%eax,先将%ebx设置为%ebx,再加上-0x4(%rbp,%rbx,4)的值,后者为我们遍历到的数字往前4个字节,即前一个数字。所以这里意思为,把我们输入数字按顺序0-5编号,当前数字必须等于当前编号+上一个数字。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第5张图片

  7. 修改solution.txt,phase_2的字符串为0 1 3 6 10 15,即0,0+1,1+2,3+3,6+4,10+5。

  8. 重新运行,过关。
    在这里插入图片描述

phase_3

实验步骤

  1. 在gdb中设置断点
    在这里插入图片描述
  2. 运行程序,并定位到爆炸点。
    在这里插入图片描述
  3. 分析爆炸点
    爆炸原因为,__isoc99_sscanf 函数的返回值%eax小于等于1。我们查询百度得知 __isoc99_sscanf 函数的返回值为输入参数的数量。我们查看标注的地址0x5555554029cf,得知我们需要输入两个整数。
    在这里插入图片描述
  4. 修改solution.txt,phase_3的字符串随意输入两个整数。
    在这里插入图片描述
  5. 重新运行,并定位到爆炸点。
    在这里插入图片描述
  6. 分析爆炸点
    爆炸的直接原因为%rsp中的值大于7,分析%rsp,查看%rsp的值,发现%rsp为我们输入数字的首地址。所以我们输入的第一个数应该不大于7。
    在这里插入图片描述
  7. 修改solution.txt,phase_3第一个参数修改为小于等于7的任意值。
    在这里插入图片描述
  8. 重新运行,并定位到爆炸点。
    在这里插入图片描述
  9. 分析爆炸点
    爆炸直接原因为%eax 和 0x4(%rsp) 的值不相等。根据前文mov $0x1c1,%eax可知%eax的值为0x1c1。再分析%rsp,查看%rsp的值,发现%rsp为我们输入数字的首地址,而0x4(%rsp)为输入的第二个数。故把第二个数修改为449(0x1c1)。
    在这里插入图片描述
  10. 修改solution.txt,phase_3的字符串的第二个数为449。
    在这里插入图片描述
  11. 重新运行,过关。
    在这里插入图片描述

phase_4

实验步骤

  1. 在gdb设置断点
    在这里插入图片描述

  2. 运行程序,定位到爆炸点
    在这里插入图片描述

  3. 分析爆炸点
    同phase_3,需要输入两个整数。

  4. 修改solution.txt,phase_4的字符串为随意两个整数
    在这里插入图片描述

  5. 重新运行程序,定位到爆炸点
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第6张图片

  6. 分析爆炸点
    爆炸直接原因为%eax的值不等于0xa。而%eax为func4函数的返回值。故我们需要func4返回10,即0xa。

  7. 分析func4
    根据前文,func4有三个参数%edx,%esi,%edi。值分别为0xe,0x0,(%rsp)。
    在这里插入图片描述
    查看%rsp,发现%rsp为我们输入的两个整数的地址。
    进入func4函数
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第7张图片
    我们首先查看返回
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第8张图片
    从中我们了解递归的终止条件为%edi和%ebx相等,返回值为%ebx的值。
    我们查看有关%ebx的代码。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第9张图片
    我们将代码分模块,分别为操作模块和跳转模块
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第10张图片
    操作模块1,分析此段代码执行的操作如下。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第11张图片
    跳转模块1,当%ebx大于%edi时跳转。执行操作为将%rbx-1赋给%edx执行func4,将结果累加到%ebx中,并返回。
    在这里插入图片描述
    跳转模块2,当%ebx小于%edi时跳转。执行操作为将%rbx+1赋给%esi执行func4,将结果累加到%ebx中,并返回。
    在这里插入图片描述
    我们需要返回值累加为10,%edx初始为14即0xe,%esi初始为0,%edi为我们输入的参数。故我们执行两次跳转模块1即可得到返回值10,7+3 = 10。所以%rdi应该为3。

  8. 修改solution.txt,phase_4字符串的第一个参数应为3。
    在这里插入图片描述

  9. 重新运行程序,并定位爆炸点。
    在这里插入图片描述

  10. 分析爆炸点
    爆炸原因为0x4(%rsp)的值不等于0xa,而%rsp为我们输入的参数的首地址。而0x4(%rsp)为我们输入的第二个参数,故需修改第二个参数为10,即0xa。

  11. 修改solution.txt,phase_4的字符串第二个参数为10。
    在这里插入图片描述

  12. 重新运行程序,过关。
    在这里插入图片描述

phase_5

实验步骤

  1. 在gdb设置断点
    在这里插入图片描述

  2. 运行程序,并定位爆炸点。
    在这里插入图片描述

  3. 分析爆炸点
    同phase_4,需要输入两个整数。

  4. 修改solution.txt,phase_5的字符串为随意两个整数。
    在这里插入图片描述

  5. 重新运行程序,并定位爆炸点。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第12张图片

  6. 分析爆炸点
    爆炸的直接原因是%edx不等于15,即0xf。我们查看有关%edx的代码。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第13张图片
    从中可以看出%edx是一个计数器,我们需要执行15次add $0x1,%edx。我们查看可以跳转到目标的代码:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第14张图片
    其中跳转条件为%eax不等于15,即0xf,所以我们需要%eax不等于15,15次。我们查看其中有关%eax的代码。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第15张图片
    其中查看%rsp发现是我们输入的参数地址,所以上部分的操作为将我们输入的第一个参数赋给%eax,并取出低4位。且%eax的值不等于15,否则进入爆炸点。而下部分为取出(%rsi,%rax,4)中的值给%eax。我们查看%rsi中的值:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第16张图片
    所以我们需要执行15次mov (%rsi,%rax,4),%eax,最后一次结果为15。我们从15反推,15->6(24/4)->14(56/4)->2(8/4)->1(4/4)->10(40/4)->0(0/4)->8(32/4)->4(16/4)->9(36/4)->13(52/4)->11(44/4)->7(28/4)->3(12/4)->12(48/4)->5(20/4)。所以%rax第一次应该为5。

  7. 修改solution.txt,phase_5的字符串第一个参数为5。
    在这里插入图片描述

  8. 重新运行,定位到爆炸点。
    在这里插入图片描述

  9. 分析爆炸点
    爆炸直接原因为%ecx和0x4(%rsp)的值不相等,没有跳转而触发下一条的炸弹。%rsp为我们输入参数的地址,所以0x4(%rsp)为我们输入的第二个参数。我们直接查看%ecx的值:
    在这里插入图片描述
    所以我们第二个参数应该为115。

  10. 修改solution.txt,phase_5的字符串第二个参数为115。
    在这里插入图片描述

  11. 重新运行程序,过关。
    在这里插入图片描述

phase_6

实验步骤

  1. 在gdb设置断点
    在这里插入图片描述

  2. 运行程序,定位到爆炸点。
    在这里插入图片描述

  3. 分析爆炸点
    同phase_2,我们需要输入6个数字。

  4. 修改solution.txt,phase_6的字符串为随意6个数字。
    在这里插入图片描述

  5. 重新运行程序,定位到爆炸点。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第17张图片

  6. 分析爆炸点
    爆炸的直接原因是无符号%eax大于5,而%eax的值是%r12的值-1。我们查看%r12的值:
    在这里插入图片描述
    发现%r12是我们输入参数的首地址。add $0x4,%r12代表%r12往后移4字节,即我们输入的下一个数。我们查看有关的跳转代码:
    在这里插入图片描述
    此处发现是对%ebx进行计数,当%ebx超过5便走一次,我们再查看有关%ebx的代码:
    在这里插入图片描述
    从此处可以看出%ebx与%r13d有关,我们再查看有关%r13d的代码:
    在这里插入图片描述
    发现%r13d也是一个计数,跳出条件为%r13d的值等于6。在前文查找%r13d的初始值:
    在这里插入图片描述
    所以%r13为1->5的遍历,每次遍历都会传值给%ebx进行%ebx->5的遍历,所以会执行5次add $0x4,%r12,即比较我们输入每个数字-1的结果无符号的小于等于5,即我们输入的每个数字必须是1-6。

  7. 修改solution.txt,phase_6的字符串为6个1-6间的数字。
    在这里插入图片描述

  8. 重新运行,并定位到爆炸点。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第18张图片

  9. 分析爆炸点
    爆炸的直接原因是%eax与0x0(%rbp)的值相等,没有跳转,所以触发了下一条的炸弹。其中根据前文%rbp与%r12的值相同,而%eax的值为(%rsp,%rax,4)。其中%rax和%ebx的值相同,我们查看%rsp的值:
    在这里插入图片描述
    发现%rsp为我们输入参数的地址。根据前文的分析,可知当%rbp指向我们输入的第一个参数时,%rax会遍历1-5,即第一个数与其后面的所有数进行对比,不能相同。当%rbp指向我们输入的第二个参数时,%rax会遍历2-5,即第二个数与其后面的所有数进行对比,不能相同。总结,此段代码限制输入不能有重复元素。故我们需要输入1-6,并且不重复。

  10. 修改solution.txt,phase_6的字符串为6个1-6间的数字,并且不重复。
    在这里插入图片描述

  11. 重新运行,并定位到爆炸点。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第19张图片

  12. 分析爆炸点
    爆炸的直接原因是%rbx的值大于%eax的值没有触发跳转,而执行了下一句的炸弹。查看有关%rbx的代码:
    在这里插入图片描述
    从此看出%rbx与0x20(%rsp)有关,查看与后者有关的代码:
    在这里插入图片描述
    而0x20(%rsp)与%rdx有关,再次查看有关代码:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第20张图片
    从这可以看出%rdx是经过操作得到,查看node1中的值:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第21张图片
    的值是0x555555604220即的地址,看出这里存储了链表的6个节点,节点内存储的是数据和节点的编号。初始链接顺序为:
    在这里插入图片描述
    我们把代码分模块:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第22张图片
    模块4,将%esi设置为0,并执行模块3
    模块3,%rsp是我们输入参数的首地址,mov (%rsp,%rsi,4),%ecx为取第%rsi+1个参数放到%ecx中,并将%eax设为1,将%rdx设为链表节点1的地址,若%ecx大于1执行模块1,否则执行模块2。
    模块1,我们了解%rdx是链表的结点,所以0x8(%rdx)的值是链表下一节点的地址。%eax是计数,当%eax不等于%ecx就继续执行mov 0x8(%rdx),%rdx。即找到编号为%ecx的链表节点,然后执行模块2。
    模块2,将取出的节点地址放到0x20(%rsp,%rsi,8)的位置,然后%rsi计数+1,当%rsi等于6时,跳出模块,否则按顺序执行模块3。
    总结,此段代码执行的功能为,将6个链表的结点,按我们输入参数的编号存储到0x20(%rsp)的位置。验证:
    在这里插入图片描述
    继续查看有关0x20(%rsp)的代码:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第23张图片
    发现此段代码是根据我们输入的节点顺序,重新排列链表。%rbx为重排后链表的头结点。重排后的链接顺序为:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第24张图片
    而%eax为当前节点的下一个节点地址。我们需要的链表是节点值从小到大排序的链表。所以我们应该输入的6个参数为5,2,6,3,1,4。

  13. 修改solution.txt,phase_6的字符串为5 6 2 3 1 4。
    在这里插入图片描述

  14. 重新运行程序,过关。
    在这里插入图片描述

secret_phase

secret_phase是隐藏了入口的,所以我们需要查看入口所在的地址,再拆除炸弹。

实验步骤

  1. 查看bomb汇编代码,查找调用secret_phase函数的代码。
    执行objdump -d bomb > bomb.s再打开bomb.s文件,搜索secret_phase。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第25张图片
    所以入口在phase_defused函数中,我们返回gdb,对phase_defused函数进行调试。

  2. 在gdb中设置断点
    在这里插入图片描述

  3. 运行程序,并定位到转折点。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第26张图片

  4. 分析转折点
    当我们执行到第6次phase_defused函数,我们不会直接按顺序ret,而是会跳转执行另一段代码。此处的转折点是%eax的值不等于3,我们没有跳转,而顺序执行下文的跳转到,而+29的位置顺序执行就为函数结束位置。所以我们需要%eax等于3,以便能抵达secret_phase的位置。
    我们查看%rsi与%rdi两个参数:
    在这里插入图片描述
    发现3 10是phase_4的破解字符串:
    在这里插入图片描述
    而%d %d %s说明需要输入两个整数一个字符串。所以我们需要在phase_4的答案后面加上一个字符串。

  5. 修改solution.txt,phase_4字符串后面添加随意字符串。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第27张图片

  6. 重新运行程序,并定位转折点。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第28张图片

  7. 分析转折点
    跳转的原因是strings_not_equal函数的返回值不是0,即参数%rdi与参数%rsi不相同。我们查看%rdi与%rsi的值:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第29张图片
    发现,%rdi是我们添加在phase_4答案后的字符串,所以我们修改该字符串为DrEvil。

  8. 修改solution.txt,phase_4的第三个参数改为DrEvil。
    在这里插入图片描述

  9. 重新运行程序,成功进入secret_phase。
    在这里插入图片描述

  10. 在gdb设置断点,开始破解
    在这里插入图片描述

  11. 运行程序,并定位到爆炸点。
    在这里插入图片描述

  12. 分析爆炸点
    爆炸原因为%eax无符号值大于1000,即0x3e8。而%eax是%rax的值-1,我们查看+24行的%rax,发现%rax的值为我们的输入值。所以这里限制我们只能输入1-1000。

  13. 修改solution.txt,secret_phase的字符串为随意1-1000的值。
    在这里插入图片描述

  14. 重新运行程序,并定位到爆炸点。
    在这里插入图片描述

  15. 分析爆炸点。
    爆炸的直接原因是fun7函数的返回值%eax不等于2,没有跳转,而触发了下文的炸弹。我们查看fun7函数:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第30张图片
    我们首先了解fun7的参数%esi和%rdi,查看%esi:
    在这里插入图片描述
    发现%esi是我们输入的数字。查看%rdi:
    在这里插入图片描述
    发现%rdi是一个结构,其中储存了一个数据,和两个地址,这是二叉树的结构。我们再来分析fun7函数的终止条件:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第31张图片
    我们从中可以看出,函数的终止有两处。一是红色方框内容,判断%rdi节点是否为空,为空就将0xffffffff赋给%eax,然后结束函数。我们需要%eax的值为2,所以我们不能走红色的终止;二是蓝色方框内容,我们要避开两个跳转,一个为%edx大于%esi,一个为%edx不等于%esi。所以我们需要的终止条件为,%edx等于%esi,而%edx的值为%rdi节点存储的数据,所以我们输入的值%esi应该为二叉树某个节点的数据。
    我们将代码分块:
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第32张图片
    模块1,当%edx大于%esi,就执行mov 0x8(%rdi),%rdi,并执行fun7,最后将%eax * 2。我的理解为,若节点数据大于我们的输入值,则进入左子树,继续执行func7。
    模块2,首先将%eax置零,当%edx不等于%esi,联系上文即%edx小于%esi,就执行mov 0x10(%rdi),%rdi并执行fun7,最后将%eax * 2 +1。所以我们需要执行一次模块2,将%eax从0->1。再执行一次模块1,将%eax从1->2,然后结束函数即可得到返回值%eax为2。
    我们查询节点数值,因为函数递归调用,所以我们先执行模块1(左子树),再执行模块2(右子树)。
    【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第33张图片
    所以我们应该输入的值为22,即0x16。

  16. 修改solution.txt,修改secret_phase字符串为22。
    在这里插入图片描述

  17. 重新运行程序,过关。
    在这里插入图片描述

实验总结

过关答案截图:
【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)_第34张图片

你可能感兴趣的:(CSAPP,数据结构,Linux,linux,数据结构)