【CSAPP】探究BombLab奥秘:Phase_3的解密与实战

简介: 【CSAPP】探究BombLab奥秘:Phase_3的解密与实战



🌺1. CSAPP与Bomb简介

🍀1.1 CSAPP

《CSAPP》是指计算机系统基础课程的经典教材《Computer Systems: A Programmer's Perspective》,由Randal E. Bryant和David R. O'Hallaron编写。该书的主要目标是帮助深入理解计算机系统的工作原理,包括硬件和软件的相互关系,其涵盖了计算机体系结构、汇编语言、操作系统、计算机网络等主题,旨在培养学生系统级编程和分析的能力。

🍀1.2 Bomb

"Bomb实验" 是与CSAPP教材相关的一项编程实验。它是一种反汇编和逆向工程任务,旨在教授如何分析和解决复杂的程序问题。Bomb实验的目标是解开一系列的"炸弹",每个炸弹都有不同的解锁方法,需要分析程序的汇编代码,理解其工作原理,并找到正确的输入来解除炸弹。这个实验教授了计算机系统的底层知识,包括汇编语言和程序执行的原理。

资源获取:关注文末公众号回复  CSAPP Bomb实验


🌺2. bomb

🍀2.1 实验环境

  • VMware Workstation虚拟机环境下的Ubuntu 64位。

🍀2.2 实验过程

实验准备阶段:首先需要使用ubuntu联网环境跳转到链接下载实验所需的bomblab:Bomblab源文件

下载bomblab压缩包并输入

tar –xvf bomb.tar

进行解压缩,进入该目录所有文件如下所示:

在终端输入

sudo apt-get install gdb

安装调试器。基本用法参考下图:

实验过程阶段:

“Binary bombs”是一个可在Linux系统上运行的C程序,它由6个不同的阶段(phase1~phase6)组成。在每个阶段,程序会要求输入一个特定的字符串。如果输入的字符串符合程序的预期输入,那么这个阶段的炸弹就会被“解除”,否则炸弹就会“爆炸”,并输出“BOOM!!!”的提示信息。实验的目的是尽可能多地解除这些炸弹的阶段。

每个炸弹阶段考察了机器级语言程序的一个不同方面,难度逐级递增:

* 阶段1:字符串比较

* 阶段2:循环

* 阶段3:条件/分支

* 阶段4:递归调用和栈

* 阶段5:指针

* 阶段6:链表/指针/结构

在炸弹拆除任务中,还存在一个隐藏阶段。然而,只有在第四个阶段解决后添加特定的字符串后,该隐藏阶段才会出现。为了完成任务,需要使用gdb调试器和objdump反汇编炸弹的可执行文件,然后单步跟踪每个阶段的机器代码,理解每个汇编语言的行为或作用。这将帮助“推断”出拆除炸弹所需的目标字符串。为了调试,可以在每个阶段的开始代码前和引爆炸弹的函数前设置断点。

在终端输入

objdump -d bomb > bomb.asm

得到bomb的反汇编文件bomb.asm如下所示。


🍀2.3 phase_3

phase_3需要使用逆向工程技术找到正确的密码。

vim bomb.asm

使用vim指令输入进入反汇编文件bomb.asm,

/phase_3

在未插入处输入查找phase_3的位置。

在Phase_3函数中,程序会首先使用sscanf函数从用户输入的字符串中读取一个整数,并将其存储在%eax寄存器中。接着,程序会将%eax的值与1进行按位与运算,并将结果存储到%eax寄存器中。如果%eax的值为0,则表示输入的整数为偶数;否则,表示输入的整数为奇数。 接下来,程序会调用一个名为fun3的函数,并将输入的整数和一个立即数0x7作为参数传递给这个函数。fun3函数的具体实现可以在IDA中查看。在fun3函数中,程序会将输入的整数与0x7进行按位与运算,然后将结果与一个名为“global_value”的全局变量进行比较。如果相等,则返回0;否则,返回一个非0的值。 最后,Phase_3函数会检查fun3函数的返回值是否为0,如果是,则表示密码正确;否则,表示密码错误。 为了寻找正确的密码,需要找到“global_value”的值。可以使用gdb调试工具,在程序运行时获取“global_value”的值。首先,需要在gdb中运行程序,并在输入密码之前,在第一行代码处打一个断点。接着,输入一个偶数作为密码,然后运行到断点处。在这里,可以使用命令“x/gx 0x地址”来查看“global_value”的值。 得到“global_value”的值后,需要使用Python等脚本语言,在0到1000之间枚举所有满足条件的偶数,并将其作为密码输入到程序中,以验证是否正确。如果找到了正确的密码,程序会输出“Congratulations!”;否则,程序会输出“Explosion!”。 除了上述步骤,我们可以注意到Phase_3函数中的第四行代码,程序将0x4025cf赋值给了%esi寄存器。这是一个地址常量,由于它在sscanf函数的前面,可以推测0x4025cf可能是一个格式字符串。因此使用gdb工具中的x/s命令来查看该地址常量的内容,以进一步了解输入内容的格式。

其中,第7-10行代码是关键的判断条件。在这几行代码中,程序会将输入的整数与1进行按位与运算,并将结果存储到%eax寄存器中。随后,程序会将%eax的值与1进行比较,如果小于等于1,则会引爆炸弹。 %eax寄存器一般是存储函数的返回值,在Bomblab中,sscanf函数的返回值就是成功读取的元素个数。因此可以推断出,这里输入的元素个数必须大于1才能通过验证,否则会引爆炸弹。 为了找到正确的密码,需要输入两个整数,可以通过IDA等反汇编工具来了解程序的具体实现。

在终端查看跳转表中储存的地址。

x/8xg 0x402470

仔细观察这些地址,可以发现都是函数phase_3范围内的地址。

当num1=0时,跳转到0x0000000000400f7c处执行。如果num2不等于0xcf,则触发炸弹。

当num1=1时,跳转到0x0000000000400fb9处执行。如果num2不等于0x137,则触发炸弹。

当num1=2时,跳转到0x0000000000400f83处执行。如果num2不等于0x2c3,则触发炸弹。

当num1=3时,跳转到0x0000000000400f8a处执行。如果num2不等于0x100,则触发炸弹。

当num1=4时,跳转到0x0000000000400f91处执行。如果num2不等于0x185,则触发炸弹。

当num1=5时,跳转到0x0000000000400f98处执行。如果num2不等于0xce,则触发炸弹。

当num1=6时,跳转到0x0000000000400f9f处执行。如果num2不等于0x2aa,则触发炸弹。

当num1=7时,跳转到0x0000000000400fa6处执行。如果num2不等于0x147,则触发炸弹。

所以拆弹密码有以下8种:

0 207;
1 311;
2 707;
3 256;
4 389;
5 206;
6 682;
7 327.

输入其中任意几种或者全部输均可。

在终端输入

./bomb

填入密钥0 207结果显示phase_3通关。

综上所述,解决Bomblab中的Phase_3题目需要一定的逆向工程技术和耐心,但通过对代码的分析和调试,我们可以找到正确的密码,进入下一个阶段。这是逆向工程学习中重要的一步,也可以帮助我们更深入地了解程序的运行机制。

对应C代码的实现为:

void phase_3(const char *input)
{
  //  0x8(%rsp)  0xc(%rsp)
  int num1, num2;
  //     %rdi     %rsi   %rdx   %rcx
  int result = sscnaf(input, "%d %d", &num1, &num2);
  if (result <= 1) {
    explode_bomb();
  }
  switch (num1) {
    case 0: // 0 207
      if (num2 != 0xcf) {
        explode_bomb();
      }
      break;
    case 1: // 1 311
      if (num2 != 0x137) {
        explode_bomb();
      }
      break;
    case 2: // 2 707
      if (num2 != 0x2c3) {
        explode_bomb();
      }
      break;
    case 3: // 3 256
      if (num2 != 0x100) {
        explode_bomb();
      }
      break;
    case 4: // 4 389
      if (num2 != 0x185) {
        explode_bomb();
      }
      break;
    case 5: // 5 206
      if (num2 != 0xce) {
        explode_bomb();
      }
      break;
    case 6: // 6 682
      if (num2 != 0x2aa) {
        explode_bomb();
      }
      break;
    case 7: // 7 327
      if (num2 != 0x147) {
        explode_bomb();
      }
      break;
    default:
      explode_bomb();
      break;
  }
}

Phase_3中每句代码的作用解释如下所示。

0000000000400f43 <phase_3>:
  400f43:  48 83 ec 18              sub    $0x18,%rsp     //给局部变量腾出空间
  400f47:  48 8d 4c 24 0c           lea    0xc(%rsp),%rcx  //加载地址,将0xc(%rsp)设为num2
  400f4c:  48 8d 54 24 08           lea    0x8(%rsp),%rdx  //加载地址,将0x8(%rsp)设为num1
  400f51:  be cf 25 40 00           mov    $0x4025cf,%esi  //因为后续调用了函数scanf,此处需对输入格式进行测试
                                                       //经测试,0x4025cf对应字符串"%d %d"
                                                       //因此可以猜测开头%rcx存放的为输入的第一个数据(设为num1)的地址,%rdx存放的为输入的第二个数据(设为num2)的地址
  400f56:  b8 00 00 00 00           mov    $0x0,%eax    //初始化%eax
  400f5b:  e8 90 fc ff ff           callq  400bf0 <__isoc99_sscanf@plt>  //调用scanf函数,此时%eax放scanf函数的返回值(输入数据的个数)
  400f60:  83 f8 01                 cmp    $0x1,%eax         
  400f63:  7f 05                    jg     400f6a <phase_3+0x27>  //jg:有符号大于则跳转,说明scanf输入数据的个数必须大于1
  400f65:  e8 d0 04 00 00           callq  40143a <explode_bomb>  //否则爆炸
  400f6a:  83 7c 24 08 07           cmpl   $0x7,0x8(%rsp)
  400f6f:  77 3c                    ja     400fad <phase_3+0x6a>  //ja:无符号大于则跳转,至爆炸,说明num1为无符号数,大于0且需要小于等于7,所以num1=[0,7]
  400f71:  8b 44 24 08              mov    0x8(%rsp),%eax           //将num1储存到%eax中
  400f75:  ff 24 c5 70 24 40 00     jmpq   *0x402470(,%rax,8)      //间接跳转,(此处%rax不完全等于%eax,由num1=1(%rax=1)时的跳转地址可推论)
                                                               //0x402470+%rax*8的计算结果作为地址,跳转到该地址继续执行
                                                               //根据该指令和后续的指令格式,很容易判断此处是switch语句的跳转表,跳转表的首地址为0x402470
                                                               //以 *0x402470 处的值为基地址,再加上8 * %rax 进行跳转,不同的 %rax 跳转到不同的位置。
  400f7c:  b8 cf 00 00 00           mov    $0xcf,%eax                 //case 0  %eax=0xcf=207
  400f81:  eb 3b                    jmp    400fbe <phase_3+0x7b>
  400f83:  b8 c3 02 00 00           mov    $0x2c3,%eax                //case 2  %eax=0x2c3=707
  400f88:  eb 34                    jmp    400fbe <phase_3+0x7b>
  400f8a:  b8 00 01 00 00           mov    $0x100,%eax                //case 3  %eax=0x100=256
  400f8f:  eb 2d                    jmp    400fbe <phase_3+0x7b>
  400f91:  b8 85 01 00 00           mov    $0x185,%eax                //case 4  %eax=0x185=389
  400f96:  eb 26                    jmp    400fbe <phase_3+0x7b>
  400f98:  b8 ce 00 00 00           mov    $0xce,%eax                 //case 5  %eax=0xce=206
  400f9d:  eb 1f                    jmp    400fbe <phase_3+0x7b>
  400f9f:  b8 aa 02 00 00           mov    $0x2aa,%eax                //case 6  %eax=0x2aa=682
  400fa4:  eb 18                    jmp    400fbe <phase_3+0x7b>
  400fa6:  b8 47 01 00 00           mov    $0x147,%eax                //case 7  %eax=0x147=327
  400fab:  eb 11                    jmp    400fbe <phase_3+0x7b>
  400fad:  e8 88 04 00 00           callq  40143a <explode_bomb>
  400fb2:  b8 00 00 00 00           mov    $0x0,%eax
  400fb7:  eb 05                    jmp    400fbe <phase_3+0x7b>
  400fb9:  b8 37 01 00 00           mov    $0x137,%eax                //case 1  %eax=0x137=311
  400fbe:  3b 44 24 0c              cmp    0xc(%rsp),%eax   //比较%eax的值和num2
  400fc2:  74 05                    je     400fc9 <phase_3+0x86>  //je:若相等则跳转至结束
  400fc4:  e8 71 04 00 00           callq  40143a <explode_bomb>  //否则爆炸
  400fc9:  48 83 c4 18              add    $0x18,%rsp       //释放空间
  400fcd:  c3                       retq

🍀2.4 实验结果

以上代码均存储在bomb_idea.txt文件中,每行代表对应的关卡,各阶段密钥如下所示:

在终端输入

./bomb result.txt

显示全部通关。


🍀2.5 实验体会

  1. 解密奥秘: 在CSAPP的BombLab实验中,深入研究了Phase_3,通过逆向分析揭示了其隐藏的机制。理解了程序背后的逻辑,成功解密了Phase_3,这一过程让我对计算机系统底层运行有了更深入的认识。
  2. 实战经验: 在攻克Phase_3的实战中,运用了各种适当的技术手段,包括逆向工程和程序调试等。通过实际动手的过程,加深了对计算机系统内部运作的理解,提升了解决实际问题的能力。
  3. 学术收获: 通过解密与实战,不仅提高了我的计算机系统安全意识,还培养了问题解决和分析的能力。CSAPP的BombLab实验为我打开了计算机科学领域的一扇大门,让我更加热衷于深入研究底层原理与系统编程。

📝 总结

计算机系统的世界,如同一座未被揭示奥秘的古老迷宫,引领你勇敢踏入计算机科学的神秘领域。CSAPP的Bomblab实验便是这场独特的学习冒险,从基本概念到底层实现,逐步揭示更深层次的计算机系统内核、汇编语言和数据结构的奥秘。


相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
6月前
|
存储 安全 Ubuntu
【CSAPP】探秘AttackLab奥秘:level 1的解密与实战
【CSAPP】探秘AttackLab奥秘:level 1的解密与实战
72 0
|
6月前
|
存储 前端开发 rax
【CSAPP】探秘AttackLab奥秘:level 5的解密与实战
【CSAPP】探秘AttackLab奥秘:level 5的解密与实战
96 0
|
6月前
|
存储 安全 Ubuntu
【CSAPP】探秘AttackLab奥秘:level 3的解密与实战
【CSAPP】探秘AttackLab奥秘:level 3的解密与实战
72 0
|
6月前
|
存储 安全 Ubuntu
【CSAPP】探秘AttackLab奥秘:level 2的解密与实战
【CSAPP】探秘AttackLab奥秘:level 2的解密与实战
88 0
|
6月前
|
安全 程序员 C++
【C++ 基本知识】现代C++内存管理:探究std::make_系列函数的力量
【C++ 基本知识】现代C++内存管理:探究std::make_系列函数的力量
200 0
|
6月前
|
存储 NoSQL Ubuntu
【CSAPP】探究BombLab奥秘:Phase_1的解密与实战
【CSAPP】探究BombLab奥秘:Phase_1的解密与实战
60 0
|
6月前
|
存储 NoSQL 安全
【CSAPP】探究BombLab奥秘:Phase_5的解密与实战
【CSAPP】探究BombLab奥秘:Phase_5的解密与实战
87 0
|
6月前
|
存储 NoSQL Ubuntu
【CSAPP】探究BombLab奥秘:Phase_2的解密与实战
【CSAPP】探究BombLab奥秘:Phase_2的解密与实战
58 0
|
6月前
|
存储 机器学习/深度学习 安全
【CSAPP】探究BombLab奥秘:Phase_4的解密与实战
【CSAPP】探究BombLab奥秘:Phase_4的解密与实战
71 0
|
6月前
|
存储 NoSQL Ubuntu
【CSAPP】探究BombLab奥秘:Phase_6的解密与实战
【CSAPP】探究BombLab奥秘:Phase_6的解密与实战
96 0