前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【CSAPP】探究BombLab奥秘:Phase_3的解密与实战

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

作者头像
SarPro
发布2024-02-20 13:52:50
860
发布2024-02-20 13:52:50
举报
文章被收录于专栏:【计网】Cisco【计网】Cisco

🌺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种:

代码语言:javascript
复制
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代码的实现为:

代码语言:javascript
复制
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中每句代码的作用解释如下所示。

代码语言:javascript
复制
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实验便是这场独特的学习冒险,从基本概念到底层实现,逐步揭示更深层次的计算机系统内核、汇编语言和数据结构的奥秘。

渴望挑战计算机系统中的安全学习路径和掌握底层系统编程的技术?不妨点击下方链接,一同探讨更多计算机科学的奇迹吧。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-01-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🌺1. CSAPP与Bomb简介
    • 🍀1.1 CSAPP
      • 🍀1.2 Bomb
      • 🌺2. bomb
        • 🍀2.1 实验环境
          • 🍀2.2 实验过程
            • 🍀2.3 phase_3
              • 🍀2.4 实验结果
                • 🍀2.5 实验体会
                • 📝 总结
                相关产品与服务
                对象存储
                对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档