写在前面

在前文《CS:APP二进制炸弹phase1》中成功“破解”了phase_1,毕竟是第一个阶段,非常简单。本篇来破解第二阶段。let's go!!!

分析

反汇编调用phase_2处的代码如下:

同样的,跟phase_1一样,我们输入的字符串首地址存储在寄存器%rdi中。

反汇编phase_2:

一眼望去,phase_2明显要比phase_1要复杂一些。不过没关系,应该只是复杂一点。

先看前五行代码。先分别将寄存去%rbp%rbx压栈,之所以将这两个寄存器压栈,可以通过后面的汇编语句得知在函数phase_2中用到了它们。

sub    $0x28,%rsp 这条汇编语句是在开辟栈空间。

mov    %rsp,%rsi 将栈首地址传送到寄存器%rsi中。根据x64 ABI文档,%rsi通常用来传递函数的第二个参数。

接下来通过callq调用函数read_six_numbers,从函数名就可以知道是从我们的输入中获取6个数字。那么就可以大胆的猜测,刚才开辟栈空间的操作是在栈上分配了一个具有6个元素的数组,至于数组元素是什么类型,目前不得而知。并且可以判断函数read_six_numbers具有两个参数,第一个参数使我们的输入input,第二个参数就是数组第一个元素的首地址,即函数read_six_numbers的原型为void read_six_numbers(const char *input, TYPE *p)。我们不妨将这个数组取名为a,TYPE a[6],即在函数phase_2有个局部数组a,数组元素总共6个,类型待定。

进入函数read_six_numbers,该函数反汇编如下:

原来函数read_six_numbers是通过函数sscanf从我们的输入中获得6个数字的。这就好办了,根据函数sscanf的原型,我们来仔细看看调用函数sscanf之前,它需要的参数是如何传递进去的。

为了方便,还是从X64 ABI文档中截个图吧,描述函数参数传递时的约定,即calling convention!

第一个参数肯定是我们的输入input的首地址,它目前储存在寄存器%rdi中,那么第二个参数应该是sscanf需要的格式化字符串,从mov    $0x4025c3,%esi中知道这个格式化字符串存储在地址0x4025c3处,用x/s命令查看,原来是"%d %d %d %d %d %d",这下我们可以断定,在函数phase_2中的数组元素类型是int型,即int a[6]。

既然格式化字符串中有个6个%d,自然的sscanf函数还需要6个参数,应该分别是数组a每个元素的地址,即分别是&a[0],&a[1],&a[2],&a[3],&a[4],&a[5]。根据调用约定,前4个元素的地址应该用寄存器传递,分别是%rdx、%rcx、%r8、%r9,最后两个通过栈来传递,通过lea    0x10(%rsi),%raxmov    %rax,(%rsp)lea    0x14(%rsi),%raxmov    %rax,0x8(%rsp)分别将&a[4]和&a[5]压栈,这就完成了sscanf所有参数的传递任务。

接下来判断sscanf函数的返回值,如果返回值大于5则OK,如果小于等于5则触发炸弹。也就是说我们需要输入至少6个数字,只要前6个数字正确即可。

OK,read_six_numbers函数分析完毕,返回函数phase_2继续分析。

现在我们可以确定数组a在栈空间中的布局了,如下:

cmpl   $0x1,(%rsp),用a[0]和数字1比较

je     0x400f30 <phase_2+52> 相等,跳转到0x400f30处继续执行,否则调用explode_bomb触发炸弹。这里很显然得出a[0]的值必须为1。

从地址0x0000000000400f30处开始的两条汇编指令lea    0x4(%rsp),%rbxlea    0x18(%rsp),%rbp用到了函数一开始就压入栈的两个寄存器,使之分别指向&a[1]和&a[6]。读者可能会问,数组a只有6个元素啊,那么最后一个元素不是应该是a[5]吗? 注意,这里取的是a[6]的地址,这在标准C中是允许的,只要不取这个地址处的值都是OK的,而标准允许这样做是有原因的,这样就可以很方便在循环中来遍历数组了。

jmp    0x400f17 <phase_2+27>,jmp到地址0x0000000000400f17处继续执行。

如果仔细观察地址0x0000000000400f2c处也有个jmp到地址0x0000000000400f17处的指令,我们可以判定这里应该是个循环语句,那么循环体的内容可以根据地址0x0000000000400f17 ~ 地址0x0000000000400f29处的指令来获知。

假设第一次进入循环体,现在寄存器%rbx指向&a[1],那么mov    -0x4(%rbx),%eax就是讲a[0]的值存储寄存器%eax,add    %eax,%eax将寄存器%eax的值乘以2,cmp    %eax,(%rbx)就是将现在%eax的值与a[1]比较,也就是a[0]乘以2后的值与a[1]比较。如果不相等, 则触发炸弹,相等则%rbx指向下一个元素的地址,在这里就是&a[3]。好,原来数组a的第一个元素的值a[0]为1,而a[1]的值是根据a[0]的值算来的,公式为a[1] = a[0] x 2。更普通的为a[n] = a[n -1] x 2(n >= 1)。

根据以上推演出的公式可以很容易的得出数组a后续元素的值分别为2、4、8、16、32。

验证一下,果然正确。

C源码如下:

static void read_six_numbers(const char *input, int *a)
{//                  %rdi         %rsi           %rdx    %rcx   %r8   %r9    (%rsp)  *(%rsp)int result = sscanf(input, "%d %d %d %d %d %d", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]);if (result <= 5) {explode_bomb();}
}void phase_2(const char *input)
{int a[6];read_six_numbers(input, a);int *begin = &a[1];int *end = &a[6];for ( ; begin < end; ++begin) {int prev_value = begin[-1] * 2;if (prev_value != begin[0]) {explode_bomb();}}
}

总结:

phase_2比phase_1来说要复杂一些,不过仔细分析一下,也不难,不是吗?继续phase_3吧!

CS:APP二进制炸弹phase2相关推荐

  1. CS:APP二进制炸弹phase5

    写在前面 在阶段4中的,我不得不承认,为了搞懂func4在搞什么,我还是花费了一些功夫的,主要原因是对其中几个汇编代码生疏,还特地上网查了一下.不过还好最后得出了答案! 本篇来看看phase_5,应该 ...

  2. [祭祖作业一]二进制炸弹破解笔记2

    哨兵值 数据结构与算法随笔之------哨兵变量(编程思想与技巧) 编程技巧1_哨兵值(sentinel) 为什么"哨兵值"没有解决错误处理问题 while 循环中的变量 i 控制 ...

  3. CSAPP实验二:二进制炸弹(Bomb Lab)

    本系列文章为中国科学技术大学计算机专业学科基础课<计算机系统>布置的实验,上课所用教材和内容为黑书CSAPP,当时花费很大精力和弯路,现来总结下各个实验,本文章为第二个实验--二进制炸弹( ...

  4. 深入了解计算机系统(CS:APP)思考题

    QA1 1.简述C.ASM.ML的关系,各自优缺点? 机器语言是二进制数据表示的语言,机器可以直接识别:汇编语言是与机器指令一一对应的助记符,是一种低级语言,经过汇编和链接之后机器可以运行:C语言在低 ...

  5. 哈工大 计算机系统 二进制炸弹实验报告

    实验报告 实 验(三) 题     目 Binary Bomb 二进制炸弹 专       业 计算机学院 学    号 班    级 学       生 指 导 教 师 实 验 地 点 实 验 日 ...

  6. 计算机系统二进制炸弹实验报告,二进制拿炸弹实验报告完整版.doc

    课程名称:计算机系统原理实验 实验课时:32课时 实验项目名称:BombLab二进制炸弹 实验材料:可执行文件bomb.源代码bomb.c.说明README 实验环境:Linux操作系统(安装虚拟机和 ...

  7. 计算机系统原理实验之BombLab二进制炸弹1、2关

    实验目的: 通过二进制炸弹实验,熟悉汇编语言,反汇编工具objdump以及gdb调试工具. 实验过程: 实验包里有三个文件,分别是二进制可执行文件bomb,C语言源程序文件bomb.c以及一个READ ...

  8. 二进制拆弹实验详解linux,拆解二进制炸弹

    拆解二进制炸弹 一.实验目的 1.理解C语言程序的机器级表示. 2.初步掌握GDB调试器的用法. 3.阅读C编译器生成的x86-64机器代码,理解不同控制结构生成的基本指令模式,过程的实现. 二. 实 ...

  9. 二进制炸弹(arm)

    x86上的二进制炸弹对于反汇编的练习来说还是比较经典的,由于网上有很多该程序的讲解,所以在此我打算写一下arm平台上的二进制拆炸弹这个游戏. 环境的搭建 由于是arm平台的环境,所以需要在linux环 ...

最新文章

  1. Laravel:使用Migrations
  2. 百度竞价用户免费拥有百度指数?
  3. 《认清C++语言》---谈谈const
  4. RedisDesktopManager客户端可视化工具下载安装与使用
  5. Codeforces 989C (构造)
  6. shell常用命令之curl: -w,–write-out参数详解
  7. 【IDE插件】- XCode6代码注释之VVDocumenter
  8. java jdbc开启事务_spring jdbc 事务配置
  9. 2 年 6 个月 11 天,外包到阿里的修仙之路!| 原力计划
  10. html同时用多个css,多类选择器的运用_html/css_WEB-ITnose
  11. App山寨疯狂 爱加密Apk加密平台防破解
  12. stephen boyd著王书宁译凸优化课后题答案
  13. 【easyui】combobox 静态数据时,设置默认值时,不触发onselect事件
  14. 汉语词频统计工具java_中文分词词频统计工具_python 结巴_Java开源中文分词类库分类列表...
  15. 用FFmpeg快捷加文字水印
  16. 面板模型进行熵值法分析
  17. 计算机代表学校拿什么奖,学校荣获第十届中国大学生计算机设计大赛优秀组织奖...
  18. 异地灾备,利用华为云就可以实现
  19. Gif动态图片怎样在线生成?一招快速完成gif在线制作
  20. 手机号和座机号正则表达式

热门文章

  1. 【CocosBuilder 开发系列之一】cocos2dx使用CocosBuilder完成骨骼动画
  2. wlan和wfi的区别
  3. 手机端操作| Auto.js一键解密/一键加密工具免费分享
  4. java生成pdf分页_java itext导出PDF 分页 github
  5. 用RP如何设计出优雅的原型图
  6. vs Code常用插件和快捷键(区分 win 和 Mac)
  7. 基于java(ssm)旅游网站系统源码成品(java毕业设计)
  8. PHP合并和追加数组
  9. greensock下载_GreenSock引人注目的动画
  10. 智能辅助系统在配电室内的施工方案 安装位置