**

p h a s e 1 phase_1 phase1​

**
密码:All your base are belong to us.

通过观察 p h a s e 1 phase_1 phase1​的汇编代码可以发现, s t r i n g s n o t e q u a l strings_not_equal stringsn​ote​qual函数应该为比较输入密码和标准密码的。所以前一个 l e a lea lea操作应该为将标准密码取出放到寄存器 %rsi 中。这样大致思路就为在 g d b gdb gdb中的 p h a s e 1 phase_1 phase1​位置设置一个断点,然后用 s i si si操作单步执行到 c a l l q callq callq操作时,将寄存器 %rsi 取出即为正确密码。取出值得过程可以先用 i n f o r e g i s t e r r s i info register rsi inforegisterrsi查看寄存器的地址和存储的值,再用 x / s x/s x/s 地址将寄存器中的值以字符串的形式输出出来。

通过 p h a s e 1 phase_1 phase1​已经基本熟悉了逆向的过程。
**

p h a s e 2 phase_2 phase2​

**
密码:0 1 1 2 3 5

+ 9 +9 +9行的汇编语言中,可以看出读入了一个输入的 6 6 6位密码,接下来就应当是比较的过程。
+ 14 +14 +14行中首先将 0 0 0与栈顶指针所存的数进行比较,如果不一样则炸弹爆炸,可以判断出第一位密码应当是 0 0 0。
+ 20 +20 +20接着比较了 1 1 1与栈顶的第二个元素,相同跳转,不同就会直接爆炸,所以可以推测 1 1 1是第二位的密码。
接着程序跳转到了 + 32 +32 +32,将栈顶指针保存到了4%rbx 中 , 又 操 作 了 一 步 之 后 跳 到 了 中,又操作了一步之后跳到了 中,又操作了一步之后跳到了+50$。
+ 50 +50 +50的操作是将当前栈顶的第二个元素也就是1赋给eax。
+ 53 +53 +53是将当前栈顶元素也就是 0 0 0加到 e a x eax eax上,随后再将 e a x eax eax与标准密码进行比较,之后再不断重复这个循环。
可以找到规律,初始两位密码为 0 0 0 1 1 1,随后的第i位密码就是 i − 1 i-1 i−1和 i − 2 i-2 i−2位的和,所以算出密码为:0 1 1 2 3 5
**

p h a s e 3 phase_3 phase3​

**
密码:
1 471
2 735
3 349
4 469
5 942
6 192
7 551
其中的任意一组



+ 26 +26 +26那一行可以看出访问了一个 s s c a n f sscanf sscanf函数,通过第三张截图中访问的第一个而第二个寄存器可以看出,第一个参数保存的是读入的一串字符串,第二个参数是 %d %d 可见程序希望读入两个整数,也就是第三个密码应该为两个整数。然后 %rdx %rcx 两个寄存器的值就是存这两个整数的。
+ 31 +31 +31的比较函数要求读入的返回值大于一,也就是要读入至少两个数,与上文的意思相符。
+ 36 +36 +36比较了7和读入的第一个数的大小,和下面的超过跳转,可以看出是要求第一位密码的范围应当是小于等于 7 7 7的整数。
再向下一直到 + 61 +61 +61之前一直是处理 %rax 中的值,然后就是 + 61 +61 +61的条件跳转。可以发现这个条件用到了 %rax 中的值,调用了 %rax*4 的偏移量,可以发现是根据读入的第一个数来跳转的。
接着下面有7组差不多的命令,都是先赋值以后跳到 + 136 +136 +136,可见这些加上 + 61 +61 +61的间接跳转应该是一个 s w i t c h switch switch语句。用第一个密码来选择。
+ 136 +136 +136比较了 %eax 中的值与第二位密码是否相等,而 %eax 中的值从 s w i t c h switch switch中被赋过值了,所以 s w i t c h switch switch语句中也就蕴含着与第一位密码相应的答案。共有 7 7 7组。
**

p h a s e 4 phase_4 phase4​

**
密码:3 10


根据 p h a s e 3 phase_3 phase3​的做法,先输出 s s c a n f sscanf sscanf的 %rsi ,发现 p h a s e 4 phase_4 phase4​的密码也是要输入两个整数。接下来就分别用 x , y x,y x,y表示两位密码。
+ 34 +34 +34和 + 41 +41 +41可以看出x应该是一个小于等于 14 14 14的整数。
+ 62 +62 +62行中代码进入到了了个函数中,同时分别将 ( x , 0 , 14 ) (x,0,14) (x,0,14)作为参数传入到了函数当中。
第二个截图为 f u n c 4 func4 func4函数的指令。接下来用 ( a , b , c ) (a,b,c) (a,b,c)分别表示传入的三个参数。
+ 1 +1 +1和 + 3 +3 +3将 c − b c-b c−b保存到了 %eax 中。 + 5 +5 +5将 %eax 的数存到了 %ebx 中。
+ 7 +7 +7这个操作将 %ebx 中的数逻辑右移了 31 31 31位。这个操作在 %ebx 中的数位正数的情况下,就等价与清零操作,可以先将其看作清零操作。
接下来就是将 %eax 的值赋给 %ebx ,然后将 %ebx 中的值除以 2 2 2,再加上 b b b。
接下来将 %ebx 中的值与 a a a进行比较,如果大于 a a a,就将 c c c赋成 %ebx 中的数 − 1 -1 −1,继续执行 f u n c 4 func4 func4函数进行递归。如果小于 a a a就将 b b b赋成 %ebx 中的数 + 1 +1 +1继续进行 f u n c 4 func4 func4函数进行递归。递归结束后将 %ebx 的数加上递归的返回值然后作为这一层的返回值。如果 a a a等于 %ebx 中的值,就直接返回 %ebx 中的值。
递归完之后回到 p h a s e 4 phase_4 phase4​中去, + 67 +67 +67要求返回值为 10 10 10, + 72 +72 +72要求 y y y与返回值 10 10 10相等,所以可以得到第二个密码值为 10 10 10,而第一个密码为递归函数中的第一个参数,根据描述,写出相应的递归程序后如下:


通过试验测得,当 d f s dfs dfs的第一个参数为 3 3 3时,返回值为 10 10 10,所以密码为 3 3 3 10 10 10.
**

p h a s e 5 phase_5 phase5​

**
密码: j d o e f g jdoefg jdoefg

+ 13 +13 +13这一行可以看出读入的面貌是一个 6 6 6位字符串。 + 18 +18 +18将 %eax 清零。
然后通过观察整段程序,发现程序可以分成两个部分,第一部分是 + 30 +30 +30到 + 53 +53 +53之间,是一个循环。第二段是 + 55 +55 +55到 + 72 +72 +72是判断部分。
由于第一部分比较复杂,所以先看第二部分,第二部分是将地址为 0 x 9 ( 0x9(%rsp) 0x9(开始的字符串与 %rsi 中的进行比较。可以看到 %rsi 中的字符串为如下的 6 6 6位字符。鱼就是目标字符串为 o i l e r s oilers oilers

接下来看循环中的部分。
+ 23 +23 +23首先将一个常数赋给了 %rcx ,通过和面的地址可以看到 %rcx 中存的:

+ 45 +45 +45到 + 53 +53 +53可以看出来这个循环是变量 %rax 从 0 0 0到 5 5 5的一个循环。
+ 30 +30 +30和 + 34 +34 +34这两行进行的操作为将 %rbx 的数加上 %rax 的和作为地址,读取其中的数赋给 %edx 。而 %rbx 是我们读入的字符串, %rbx 中存的地址就是字符串开头字母的地址,又因为 %rax 是从 0 0 0到 5 5 5的,所以在每次循环中分别取出了输入字符串的第 0 0 0到 5 5 5位赋给了 %eax 。然后 + 34 +34 +34取出了 %eax 的后四位。
+ 37 +37 +37行访问了 %rcx 和 %rdx 保存的地址的和作为地址的地址。因为 %rcx 中存储的也为字符串,所以可以看成是以 %rcx 存储的字符串的首字符作为基地址, %rdx 存的量为偏移量来访问后面的第 %rdx 个字符。
+ 41 +41 +41行将 %dl 中的值存储到对应的 + 60 +60 +60行要比较的字符串的第 %rax 位。
通过上面的分析可以看出,第i次循环要得到 o i l e r s oilers oilers中的第 i i i个字符,而这个字符是通过访问 %rcx 字符串中的字符找到的,可以计算出,每次循环 + 37 +37 +37行访问时的偏移量分别为 a , 4 , f , 5 , 6 , 7 a,4,f,5,6,7 a,4,f,5,6,7这样分别代表了 m m m后面的第 a a a个字符 o o o,第 4 4 4个 i i i以此类推。

而第 i i i个偏移量的获得是通过度日的字符串的第 i i i位对应的 A S C I I ASCII ASCII码取后四位得到的。所以可以得到输入的 6 6 6位字符串的后四位分别为 a , 4 , f , 5 , 6 , 7 a,4,f,5,6,7 a,4,f,5,6,7。然后在补上高位 6 6 6,即获得了正确密码。
p h a s e 6 phase_6 phase6​
密码:5 6 2 1 4 3



+ 0 +0 +0到 + 18 +18 +18是读入部分,通过输出 %r12 中存的数可以发现, 0 x 30 ( 0x30(%rsp) 0x30(中保存的是读入的第一个数的地址。输入的六位密码就用a[i]来表示。
接下来程序可以分为以下几个部分: + 29 +29 +29到 + 82 +82 +82; + 84 +84 +84到 + 152 +152 +152; + 154 +154 +154到最后。
首先 + 29 +29 +29到 + 82 +82 +82是一个单层循环, %r13d 中使循环变量,从 1 1 1到 6 6 6遍历了读入的六个元素,判断每个元素的是是否都小于等于 6 6 6且互不相等。这也就要求了这个六位密码是 1 − 6 1-6 1−6的全排列中的一个。
+ 84 +84 +84到 + 152 +152 +152是一个两层循环, %rsi 中存的是一个外层循环的循环变量,这一层循环从 1 1 1到 6 6 6遍历了一遍读入的六个数据。 %eax 中保存了第 2 2 2重循环的循环变量。可以发现第二层循环的次数位第i位密码的值。而第二陈循环中主要涉及了 %rdx 和 %rsp 这两个寄存器。首先来看一下 %rdx 。

这个是 %rdx 的初始化,是从内存中读取了一个常数。接下来对于外层的第i次循环,内层的循环进行了¥a[i] 次 如 下 操 作 : ! [ 在 这 里 插 入 图 片 描 述 ] ( h t t p s : / / i m g − b l o g . c s d n i m g . c n / 20181111201712424. p n g ) 因 为 次如下操作: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20181111201712424.png) 因为 次如下操作:![在这里插入图片描述](https://img−blog.csdnimg.cn/20181111201712424.png)因为%rdx 中 存 的 是 一 个 地 址 , 所 以 可 以 看 到 中存的是一个地址,所以可以看到 中存的是一个地址,所以可以看到%rdx 向 后 偏 移 了 向后偏移了 向后偏移了a[i]$次,也就是说程序中保存了 6 6 6个常数,对于第i次外层循环,内层循环取出了第 a [ i ] a[i] a[i]个常数。

这条语句依次将取出的元素保存在了栈中。
然后是最后一个部分,首先进行了一个这样的操作:

这段代码将栈上一部分保存在栈中的元素建立了一个链表,顺序就是,第一个放入的元素指向下一个放入的元素(这一段开始比较难以理解)。

这是程序的最后阶段了,这一段在刚刚建好的链表中从前到后的比较了量表中相邻两个元素的大小。也就是第一个元素小于第二个元素想,第二个小于第三个,以此类推,也就是这六个元素要是从小到大排列好的。

现在这个程序的作用也就比较清晰了,程序按照我们输入的六个数的顺序依次取出了系统中保存的六个常数,要求取出的这六个常数要按照从小到大的顺序排好,也就是说我们输入的六位密码的第i位代表的应该是,六个常数中排名第 i i i小的元素是第几个。那只需要看一下这六个元素依次是什么,这个问题就解决了。


输出程序中的六个常数的大小,即可得到密码:5 6 2 1 4 3
**

s e c r e t − p h a s e secret-phase secret−phase

**
密码:22

程序中只有phase_defused这个函数还没有看过内容,所以隐藏关可能就宝运载整函数中。函数中开始就有一个比较,通过在程序中跟踪比较的那个地址发现,那个地址就是破解的炸弹的个数,也就是说,只有破解了六个炸弹后才能进入下面的隐藏部分。

通过这个值发现,要输入两个整数和一个字符串来进入隐藏关,而 + 37 +37 +37中首先传入了一个参数,通过输出发现正好是第四个炸弹的密码,所以字符串应该是跟在第四个炸弹后面的。
+ 88 +88 +88中调用了字符串是否相等的函数,那么根据传入的那个字符串的地址,就可以知道进入隐藏关的密码了。

进入到隐藏关后,发现隐藏关的密码是通过read_line读入的,也就是一个字符串。 + 19 +19 +19中调用了一个系统函数 s t r t o l strtol strtol,通过查询,发现这个代码的功能是将字符串转换成相应的数字。所以 + 24 +24 +24的 %rax 总就保存的将读入字符串传化为数字后的值。接下来的两行限制了这个数字的大小。 + 24 +24 +24到 + 35 +35 +35这段代码限制了隐藏关的密码要小于 0 x 3 e 8 0x3e8 0x3e8。
再向下看发现 + 46 +46 +46中调用了函数 f u n 7 fun7 fun7,假设传入的两个变量为 ( x , y ) (x,y) (x,y), y y y就是我们读入的隐藏关的密码, x x x是一个指针,通过访问内存地址,发现 x x x的值为:

通过 f u n 7 fun7 fun7的代码,发现 f u n 7 fun7 fun7是一个递归函数。
首先当 x = 0 x=0 x=0的时候,函数返回 − 1 -1 −1。然后递归函数先在 + 11 +11 +11分成了两个部分,第一个部分是 x &gt; y x&gt;y x>y的情况,第二个是 x &lt; = y x&lt;=y x<=y的情况。
当 x &gt; y x&gt;y x>y时,跳转到了 + 29 +29 +29,将下一次递归的指针x指向的地址加了 0 x 8 0x8 0x8后进入到了下一层递归,然后将返回值乘 2 2 2作为这一层递归的返回值。
当 x &lt; = y x&lt;=y x<=y的时候,又分成了两个部分, x = y x=y x=y和 x &lt; y x&lt;y x<y。
当 x = y x=y x=y的时候,程序不再进行下一层递归,直接返回 0 0 0。
当 x &lt; y x&lt;y x<y的时候,跳转到了 + 42 +42 +42,将下一次递归的指针 x x x指向的地址增加了 0 x 10 0x10 0x10后进入到下一层递归,然后将返回值乘 2 2 2加 1 1 1作为这一层的返回值。
观察secre_phase的 + 51 +51 +51和 + 54 +54 +54发现,隐藏关要求函数 f u n 7 fun7 fun7的返回值为 2 2 2,所以回想整个递归过程,最深层的递归返回值一定为 0 0 0,如果想得到 2 2 2,需要将 0 0 0先乘 2 2 2加 1 1 1变成 1 1 1,再乘 2 2 2变成 2 2 2,也就是说最开始应该先执行 x &gt; y x&gt;y x>y,在下一层执行 x &lt; y x&lt;y x<y,最深的一层为 x = y x=y x=y,这样就可以让 f u n 7 fun7 fun7的返回值为 2 2 2。那么我们输入的密码就应该和第二层的 x x x值相等,通过访问内存地址,就可以得到隐藏关的密码:
也就是 22 22 22。

二进制炸弹(ICS作业)相关推荐

  1. 作业_二进制炸弹_手把手教学讲解

    简单的前言 最近的作业有个二进制炸弹问题,具体点说就是使用汇编语言完成一些小问题,形式比较有趣,一起看看吧. 题目描述 实验目的 通过对一个二进制可执行程序(称为"二进制炸弹")的 ...

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

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

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

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

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

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

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

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

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

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

  7. 二进制炸弹(arm)

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

  8. CS:APP二进制炸弹phase2

    写在前面 在前文<CS:APP二进制炸弹phase1>中成功"破解"了phase_1,毕竟是第一个阶段,非常简单.本篇来破解第二阶段.let's go!!! 分析 反汇 ...

  9. 【计组】二进制炸弹bomblab Phase1-6

    实验目的 通过二进制炸弹实验,熟悉汇编语言 熟悉GDB调试工具 算法思路 编译环境 gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) GNU gdb (U ...

最新文章

  1. 4.3.6无分类编址CIDR(构成超网)
  2. 信息安全技术网络安全等级保护定级指南_行业标准 |报业网络安全等级保护定级参考指南V2.0发布,明确保护对象、定级要求...
  3. IDEA:生成javadoc/断点调试/缓存和索引的清理
  4. web测试常用的用例及知识
  5. 《Android开发秘籍(第2版)》——第1.4节Android设备间的硬件差异
  6. 社区发现(三)--CMP
  7. ASP .NET CORE MVC 部署Windows 系统上 IIS具体步骤---.Net Core 部署到 IIS位系统中的步骤...
  8. DevExpress Xaf入门——关于树形结构对象的配置(DC模式)
  9. 《HRNet-OCR:Object-Contextual Representations for Semantic Segmentation》论文笔记
  10. PDF 报告生成器:用 reportlab 和 pdfrw 生成自定义 PDF 报告
  11. 基于Java的简单WebAPI接口调用(中国气象数据网接口调用示例)
  12. 怎样解题:写题解思考问题的原则
  13. jquery datatable 前端分页和后端分页例子
  14. walking与Matlab入门教程-介绍示例模型
  15. python读HDF数据
  16. 周易六十四卦——风山渐卦
  17. 自动化测试框架rf(Robot Framework)的安装
  18. 小米5(mi5)开启-全面屏手势-详细步骤
  19. springsecurity自定义短信验证码认证登录流程
  20. 基于因果推断的根因分析

热门文章

  1. 数字中国:智慧城市中的的大格局与大视野
  2. 从程序员到项目经理:如何管理自己的时间
  3. (二十二)波、波、波(2)
  4. 小众品牌,为何在时尚圈混得风生水起?
  5. html mysql 转义_HTML/Mysql/XML 转义字符,备查
  6. High-Performance and Energy-Efficient Mobile Web Browsing on Big/Little Systems
  7. Windows Server 2012 如何实现多个用户远程桌面登陆
  8. 如何裁剪动图的尺寸?怎样快速裁剪gif动图?
  9. 电脑字体模糊解决方法
  10. AI遇资本市场寒流,前期大规模涌入到如今的九成企业亏损