CSAPP Lab2实验记录 ---- Bomb Lab

前引

今天是除夕 然后平时摸着摸着鱼 把CSAPP前三章看完了(浮点那里跳着看完的)

因为学习第三章之前学过大部分王爽的汇编语言(就是因为要学CSAPP才学的汇编)然后看第三章相对第一遍初略看的时候 简直不要太舒服 就至少能看懂 能做大部分CSAPP例题了 刚开始没学汇编的时候 里面是啥我都不知道 也就导致我第一次看第三章的时候 懵懵懂懂 不知所以 也就啥都没学进去

在这里插入图片描述

~聊点其他的题外话吧 反正寒假说学的有多认真 倒也不一定 感觉还是边耍边学的吧 Leetcode今天也还没有刷题 晚上也要玩游戏 打ow Apex 枪火重生 各种单机游戏 有的时候人也挺懒的 呆在床上啥也不想干 就这样过了一天 也挺好的
我好烦我喜欢的妹妹也平时不咋回我消息(qswl)
在这里插入图片描述

这段时间 我看我的文章下面有留言 emm 说什么大一上学到这个样子 看了怎么怎么样 其实我觉得我也并没有天天只在编程啊…qwq 我也要玩游戏的啊 我高三暑假也玩了一个暑假 所有的一切都是从大一开始 一步一步到现在的qwq 其实大家都是一样的啊 我可能只是在这个方面比较感兴趣 花的时间更多一点而已 就这个样子嘛

反正希望今年看到这篇博客的牛年快乐叭
大家新的一年都能被人喜欢 喜欢的人能喜欢自己哈哈哈哈哈



实验前提引子

这个引子是为了给一些这个实验还没有入门的hxd看的
因为这个实验直接拿给一个phase都还没过的人 干什么都是不知道的
这个实验入门还是挺简单的 所以大家可以对于前两个phase 可以看一下我是怎么解题的 大概流程或者操作熟悉一下
对于后面拆炸弹你可能就自己是懂得怎么解决了
过掉两个phase是不会影响这个Lab对你能力的提升的
所以对于前两个phase我会很详细的 把我怎么做的思路一步步都讲出来
对于后面3、4、5、6 四个phase我可能会稍微没有那么仔细的分析了

需要什么指令 还有需要还有什么其他的 我都会在下面详细的给出来的



实验需要指令及准备

我们首先把 Bomb-Lab 给解压了
在这里插入图片描述


得到Bomb的文件夹 打开里面有三个文件 除了 bomb.asm反汇编文件
在这里插入图片描述

在这里插入图片描述

然后我们需要什么呢 首先要安装Gdb调试器 对于Ubuntu而言
打开终端 直接输入sudo apt-get install gdb 然后截图是下面的

在这里插入图片描述


然后就进入 bomb文件夹
我们可以先看看read文件 bomb.c文件可以不看 因为你看了也没有什么用qwq 看了你也不晓得在说什么(有彩蛋的)
到最后我们都是通过gdb调试器来运行bomb文件 来进行调试
下面先给出gdb调试器的一些指令 是我们后续需要用到的
这里先给出来 不需要全部记下来 后面我会用到的 再讲用法
这些指令我都是复制过来的
基本上都是要用到的

  r  运行程序

  b <*0x某某某>    在某个地址设置断点,具体哪里,可以看反汇编的代码,可以根据那个直接复制粘贴设断点的

  d 删除所有断点

  d <断点号>    删除指定断点

  info b    查看所有断点信息

  continue 从断点处继续执行

  display <$寄存器>    跟踪寄存器,碰到断点停下时会显示出所有跟踪的寄存器的当前值,非常好用的一个命令,注意的是gdb中表示寄存器的话前面用的不是百分符号%,而是美元符号$

  x/参数 <地址>    访问地址的内存,其实就是间接访问,也是很好用的指令,关于参数,s是输出为字符串,d为输出为十进制,x为输出为十六进制,b、w、l、q控制输出字节,默认是w,四字节,s字符串不受这个控制除外。

  info r    查看所有寄存器的值
  print (可加强制转换符号)<数字>	跟C语言的基本性质一样的,理解即可

然后我们提前生成Bomb.c的反汇编文件
为什么要生成 因为后面是需要用的 到后面需要怎么用的时候再讲
我们只需要生成一次 在终端输入objdump -d bomb > bomb.asm
就能看到 在bomb文件夹多出来了一个这样子的文件

在这里插入图片描述
ok 我们进入我们的紧张刺激的拆炸弹phase环节哈哈哈哈哈 (finally gogogo!)
在这里插入图片描述



Phase 1

我们先通过gdb 载入bomb文件 终端输入gdb bomb 然后就会出现这样子的状态
在这里插入图片描述


我们可以先运行一下这个bomb软件 直接输入r即可
然后就出现下面炸弹 have 6 phases with which to blow ourselves up

在这里插入图片描述


我们可以试一下 输入自己想输入的 让不让我们通过
比如 dontletmebomb

在这里插入图片描述
可是事不如我们所预期的 bomb了 那我们如何躲开炸弹爆炸通过呢
我们只能查看我们的反汇编语言来寻找蛛丝马迹了

这个时候反汇编我们之前生成的bomb.asm就有用武之处了
那我们打开bomb.asm
建议复制一份到windows 因为在ubuntu是只读的
然后不好打备注 打开之后我们先来到Phase_1段落处

在这里插入图片描述


我们这个时候来仔细分析分析
在这里插入图片描述

第一行代码 把栈指针减少了8 是为了给局部变量提供空间
与最后一行addq $0x8 相对应 函数都是会回收栈指针的
第二行代码向寄存器 esi给了0x402400的数据
第三行就是调用函数 strings_not_equal
看函数名字 我们应该能判断出来 这个函数是看我们输入的字符串和这个程序的其中的哪个字符串是否相同
然后我们再往后看看第四行代码 就是test eax寄存器是否有数
根据我们之前理解到的 rax寄存器一般里面存放的是函数的返回值
eax寄存器不过就是rax的低32位表示而已

哦? 这就有意思了 我们不难分析出 当rax寄存器当值等于0的时候
即可满足第五行代码的跳转指令
跳转指令跳转到400ef7处 然后是跳过了 400ef2处的指令

我们仔细看一下400ef2的指令 调用函数 explode_bomb
xdm 看函数名懂得都懂 爆炸指令 则我们可以得到下面的信息

如果当rax寄存器值不等于0的时候
我们不会跳转 就会来到400ef2处 就会调用爆炸函数 我们就会起飞

在这里插入图片描述

唯一的方法就是 我们输入的字符串和其中存储的一个字符串相等
相等的话 string_not_equal 返回值就会是0
不相等可能会返回1
(在c语言中 0有false的意思 1也有true的意思 即满足相等 函数返回false)


说了那么多 我们仔细看一下这两行代码
在这里插入图片描述
这里是为什么会向寄存器放入这个 0x402400呢
因为显然 程序是不肯定把提前准备好的字符串藏到其他很深的地方的
那不然我们怎么拆炸弹啊哈哈哈哈哈
我们就可以调查这个地方


有两个办法 因为是字符串
首先是 第一个是直接通过gdb调试看
print (char*)0x402400
我们一个一个试一下

在这里插入图片描述
哦哟 不错哦~ 出现了一串字符串~
这个可能是正确答案 我们先记下来
Border relations with Canada have never been better.
我先把下面一个方法介绍一下 再去核对一下这个答案是否是正确的

第二种是通过设置断点在349行代码处 此时已经经过了
mov 0x402400, $esi这行指令了

我们先输入b *0x400ee9 设置断点
然后我们先重新重新运行程序 输入r
然后随便输入一串字符串abcde
当程序运行到断点处自动停止 此时我们就可以看一下esi寄存器里面的数据了然后通过指令 x/s $esi 看寄存器中存放数据 这里的s就是字符串哈

在这里插入图片描述


两种办法介绍完了 我们现在就去重新运行验证一下 字符串正确与否
在这里插入图片描述
ok 终于拿下了~ 拿下(破音) 有了phase的经验
后面的拆炸弹相比也有一定经验了

如果觉得自己经过phase_1理解了拆弹流程了
真的想自己拆弹的话 建议phase_2就可以开始自己拆了 不用再跟着实验记录
如果觉得自己还没有拆弹的感觉 怕被炸飞的
可以继续跟着实验记录走一波
反正我是看完人家的phase_1之后的 phase_2就是全自己推了

ok 那我们来到phase_2继续当拆弹专家:)
在这里插入图片描述

拆弹密码1
Border relations with Canada have never been better.



Phase 2

在这里插入图片描述
老规矩 分析一下吧
357 358行 存放寄存器状态
359行提供局部变量空间
360行把我们的栈指针状态存入到rsi寄存器中

然后继续往下看到 callq read_six_numbers 看函数名字是读取六个数字 我们这边可以先试一下输入六个数字
在这里插入图片描述


不错的昂~ 炸弹成功炸掉 扣了HP-1 可惜我们的HP为99999999
而且还是god mode 说明这个phase不仅仅只是输入6个数字那么简单
要想仔细分析一下 我们就需要去函数 read_six_numbers代码区一探究竟
发现为40145c

有个快捷键 ctrl+f 我们可以搜索关于这个的文字
啪的一下很快嗷 我们就到了这个代码区

在这里插入图片描述


在这里插入图片描述

我们可以逐行的再来分析一下这个函数
首先栈指针减少24 从中我们可以不难得出 24刚好是6个int整形数字所需要的字节数
然后后面到814行之前应该是把6个整形数字的地址放到各个寄存器中


然后我们注意814行— 817行之间
首先816行有个调用函数 scanf 我们可以稍微去看一下这个函数

在这里插入图片描述
emmm 这个函数又跳转到其他位置
然后我之后再400bf0这里设置了一个断点
然后info r看了一下 寄存器rip 跳转地址看了记得是0x600000(可能有误)
但是反正也不需要去搞懂
这个应该就是跟c语言 scanf函数一样的


然后我们返回814行代码 有没有想到c语言我们调用scanf函数
我们需要首先给出 我们输入格式 比如%d %d %d %d
联系到第一题 我们可以调查一下 我们不难联想到 这个向esi转入的数字
可能就是 我们输入格式
说干就干
在终端输入
print (char*)0x4025c3

在这里插入图片描述


不错的昂 这里也分析出了确实是6个数字
这里还有个小细节也能分析出来至少是大于5个数字的
就是817行 rax装的是scanf函数的返回值
如果小于等于5 也会引发炸弹爆炸
对于输入数字的问题 我们就解决了


在这里插入图片描述
再返回phase_2
首先可以判断 当rsp间接引用的内存地址必须要等于1
通过我的两次尝试再加上一定的理性判断 可以判断出
(%rsp)装的肯定是我们输入6个数的第一个数
那么 0x4(%rsp)就是第二个数 0x8(%rsp)是第三个数

我们输入的数第一个就必须是1 跳转到400f30
接下来的分析我就快速分析一下了 rbx装2号数 rbp装6号数
跳转 400f17 下面就类似数学小学数学问题了
我用c语言来概括一下下面的代码在干什么

int i;
int a[6];
a[0] = 1;
for(i=1;i<6;i++)
{
    
    
	a[i] = a[i-1]*2;
}

还是不难分析的 最后就能成功得到6个数字为 1 2 4 8 16 32
我们重新开始实验 测试一下是不是这个数字
在这里插入图片描述

ok 拆弹专家level is becoming higher了嗷
我这边实际写博客的时间远比我解题的时间多qwq
但是接下来的四个phase 我不会再像这个样子 一点一点分析了
但是也会记录下来我的一些想法 关键步骤

在这里插入图片描述
拆弹密码2

1 2 4 8 16 32



Phase 3

0000000000400f43 <phase_3>:

//给局部变量腾出空间 把两个数据内存地址移向两个寄存器
  400f43:	48 83 ec 18          	sub    $0x18,%rsp
  400f47:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx
  400f4c:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx

//调查输入格式because 400f5b调用了scanf函数
//print (char*)0x4025cf
//得到%d %d 即为输入两个数
  400f51:	be cf 25 40 00       	mov    $0x4025cf,%esi    
  400f56:	b8 00 00 00 00       	mov    $0x0,%eax
  

//调用scanf函数
  400f5b:	e8 90 fc ff ff       	callq  400bf0 <__isoc99_sscanf@plt>

//也可从这里印证 返回值需要大于1
  400f60:	83 f8 01             	cmp    $0x1,%eax

//跳转400f6a
  400f63:	7f 05                	jg     400f6a <phase_3+0x27>
  400f65:	e8 d0 04 00 00       	callq  40143a <explode_bomb>

//因为只有两个数 我们从开头发现有个0x8(%rsp) 还有个0xc(%rsp)内存调用进入了寄存器
//所以我们不难推测出 这个0x8(%rsp)可能是第一个数
//通过两次断点尝试 我们肯定出这个是第一个数
//不碰炸弹条件需要小于等于7 
  400f6a:	83 7c 24 08 07       	cmpl   $0x7,0x8(%rsp)

//跳转400fad 如果大了即跳转 跳转地址为调用引爆炸弹指令
  400f6f:	77 3c                	ja     400fad <phase_3+0x6a>

//这里我还是花了点时间分析的
//下面很多重复的移动 
//这里不妨可以联系到类似跳转表
//因为我知道400f75也是跳转到一个地址 我计算出来在整个反汇编文件上限都没有
//那么我想到书里面有个跳转表 是通过自己减去一部分的地址 比如0~7的
//可能计算地址为100~107 通过减去100而到相对于的地方
//这里可以通过观察得到 刚好有7个跳转重复的 我们可得到应该第一个数范围应该是0~7 但最搞笑的是 应该是0~7 可是当我代入测试数据的时候
//不知道为什么 当第一个数为1的时候 是不存在的 我认为可能是设置数据没设计好的问题
//这里存在Bug
  400f71:	8b 44 24 08          	mov    0x8(%rsp),%eax//第一个数
  400f75:	ff 24 c5 70 24 40 00 	jmpq   *0x402470(,%rax,8)
  400f7c:	b8 cf 00 00 00       	mov    $0xcf,%eax//0  0xcf = 207
  400f81:	eb 3b                	jmp    400fbe <phase_3+0x7b>
  400f83:	b8 c3 02 00 00       	mov    $0x2c3,%eax//2 0x2c3 = 707 
  400f88:	eb 34                	jmp    400fbe <phase_3+0x7b>
  400f8a:	b8 00 01 00 00       	mov    $0x100,%eax//3 0x100 = 256
  400f8f:	eb 2d                	jmp    400fbe <phase_3+0x7b>
  400f91:	b8 85 01 00 00       	mov    $0x185,%eax//4 0x185 = 389
  400f96:	eb 26                	jmp    400fbe <phase_3+0x7b>
  400f98:	b8 ce 00 00 00       	mov    $0xce,%eax//5 0xce = 206
  400f9d:	eb 1f                	jmp    400fbe <phase_3+0x7b>
  400f9f:	b8 aa 02 00 00       	mov    $0x2aa,%eax//6 0x2aa = 682
  400fa4:	eb 18                	jmp    400fbe <phase_3+0x7b>
  400fa6:	b8 47 01 00 00       	mov    $0x147,%eax//7 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
  400	fb7:	eb 05                	jmp    400fbe <phase_3+0x7b>
  400fb9:	b8 37 01 00 00       	mov    $0x137,%eax

//跳转后要求 之前移入eax的数等于我们输入的第二个数
//上面已经把所有第一个数对应第二个数 标注了出来
//这道题的结果应该是有7种  有一种数据没设计进去 随意输入一种即可通过
  400fbe:	3b 44 24 0c          	cmp    0xc(%rsp),%eax
  400fc2:	74 05                	je     400fc9 <phase_3+0x86>
  400fc4:	e8 71 04 00 00       	callq  40143a <explode_bomb>
  400fc9:	48 83 c4 18          	add    $0x18,%rsp
  400fcd:	c3                   	retq   

拆弹密码3

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



Phase 4

000000000040100c <phase_4>:
  40100c:	48 83 ec 18          	sub    $0x18,%rsp
  401010:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx
  401015:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx

// %d %d 输入格式
  40101a:	be cf 25 40 00       	mov    $0x4025cf,%esi 
  40101f:	b8 00 00 00 00       	mov    $0x0,%eax
  401024:	e8 c7 fb ff ff       	callq  400bf0 <__isoc99_sscanf@plt>
  401029:	83 f8 02             	cmp    $0x2,%eax
  40102c:	75 07                	jne    401035 <phase_4+0x29>

//第一个数小于等于14
  40102e:	83 7c 24 08 0e       	cmpl   $0xe,0x8(%rsp)
  401033:	76 05                	jbe    40103a <phase_4+0x2e>
  401035:	e8 00 04 00 00       	callq  40143a <explode_bomb>

//edx 14
  40103a:	ba 0e 00 00 00       	mov    $0xe,%edx

//esi 0
  40103f:	be 00 00 00 00       	mov    $0x0,%esi

//edi 第一个数 esi 0 edx 14 

  401044:	8b 7c 24 08          	mov    0x8(%rsp),%edi
  401048:	e8 81 ff ff ff       	callq  400fce <func4>
  40104d:	85 c0                	test   %eax,%eax

//edi 7 esi 0 edx 14 eax 0 ecx 7
  40104f:	75 07                	jne    401058 <phase_4+0x4c>

//第二个数为0
  401051:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp)
  401056:	74 05                	je     40105d <phase_4+0x51>
  401058:	e8 dd 03 00 00       	callq  40143a <explode_bomb>
  40105d:	48 83 c4 18          	add    $0x18,%rsp
  401061:	c3                   	retq   


0000000000400fce <func4>:

//edi 第一个数 esi 0 edx 14 eax 14 ecx 14
//edi 第一个数 esi 0 edx 14 eax 7 ecx 0
//edi 第一个数 esi 0 edx 14 eax 7 ecx 7
//edi 0~7 esi 0 edx 14 eax 7 ecx 7

  400fce:	48 83 ec 08          	sub    $0x8,%rsp
  400fd2:	89 d0                	mov    %edx,%eax
  400fd4:	29 f0                	sub    %esi,%eax
  400fd6:	89 c1                	mov    %eax,%ecx
  400fd8:	c1 e9 1f             	shr    $0x1f,%ecx
  400fdb:	01 c8                	add    %ecx,%eax
  400fdd:	d1 f8                	sar    %eax
  400fdf:	8d 0c 30             	lea    (%rax,%rsi,1),%ecx

//这里限制了edi 小于等于rcx
  400fe2:	39 f9                	cmp    %edi,%ecx
  400fe4:	7e 0c                	jle    400ff2 <func4+0x24>
  400fe6:	8d 51 ff             	lea    -0x1(%rcx),%edx
  400fe9:	e8 e0 ff ff ff       	callq  400fce <func4>
  400fee:	01 c0                	add    %eax,%eax
  400ff0:	eb 15                	jmp    401007 <func4+0x39>

//edi 0~7 esi 0 edx 14 eax 0 ecx 7

  400ff2:	b8 00 00 00 00       	mov    $0x0,%eax

//这里限制了edi 大于等于rcx
//得到即edi只能等于rcx 7
//edi为第一个数 即第一个数为7
  400ff7:	39 f9                	cmp    %edi,%ecx
  400ff9:	7d 0c                	jge    401007 <func4+0x39>
  400ffb:	8d 71 01             	lea    0x1(%rcx),%esi
  400ffe:	e8 cb ff ff ff       	callq  400fce <func4>
  401003:	8d 44 00 01          	lea    0x1(%rax,%rax,1),%eax
  401007:	48 83 c4 08          	add    $0x8,%rsp
  40100b:	c3                   	retq

拆弹密码4

7 0



Phase 5

我的Phase4 和我的Phase5都是
刚解出来 我就跑过来写解答了
相对于Phase4 我认为Phase5的难度是上升了一个台阶
因为我分析起来 Phase4可能就花了不到20分钟
我自认为还是没有什么难度的
而Phase5相比来说 我花了更多时间去看
相关寄存器的数据和其他的东西 去尽量搞懂每行代码在干什么
正好趁我手感火热 赶快就把博客写了

这部分我就不能仅仅把那个备注给写了 还是觉得有必要写的详细一点
一步步来吧

在这里插入图片描述


0000000000401062 <phase_5>:

  //储存rbx寄存器状态 减少栈指针为局部变量提供空间
  401062:	53                   	push   %rbx
  401063:	48 83 ec 20          	sub    $0x20,%rsp

  //没有搞懂fs:0x28是啥 但反正设置断点得到fs:0x28为0
  401067:	48 89 fb             	mov    %rdi,%rbx
  40106a:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
  401071:	00 00 
  401073:	48 89 44 24 18       	mov    %rax,0x18(%rsp)

  //异或设置rax为0
  401078:	31 c0                	xor    %eax,%eax

  //调用函数 检测字符串长度 与下面一条指令 则说明字符串需要长度为6
  40107a:	e8 9c 02 00 00       	callq  40131b <string_length>
  40107f:	83 f8 06             	cmp    $0x6,%eax
  401082:	74 4e                	je     4010d2 <phase_5+0x70>
  401084:	e8 b1 03 00 00       	callq  40143a <explode_bomb>
  401089:	eb 47                	jmp    4010d2 <phase_5+0x70>

  //rbx位置存放着第一个数字位置
  //下面四条指令的作用就是 rdx取的是字符的低四位
  40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx
  40108f:	88 0c 24             	mov    %cl,(%rsp)
  401092:	48 8b 14 24          	mov    (%rsp),%rdx
  401096:	83 e2 0f             	and    $0xf,%edx
  
  //这个时候我不知道这条指令是干嘛的
  //直接调用指令 x/s 0x4024b0 出现一串字符串
  //maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you
  //这个指令是干什么呢 也就是把这个语句中的一个字符 转移到rdx中
  //字符定位就在地址 0x4024b0再加上我们之前输入的某个字符的低四位
    401099:	0f b6 92 b0 24 40 00 	movzbl 0x4024b0(%rdx),%edx
  
  //这个语句又是把maduiersnfotvbylSo其中一个字符转移到 一个地址
  4010a0:	88 54 04 10          	mov    %dl,0x10(%rsp,%rax,1)
  
  //最刚开始rax一直为0 现在加+1
  4010a4:	48 83 c0 01          	add    $0x1,%rax
  
 
  //与6相比较 如果不等于6的话 循坏又到0x40108b位置处
  //这里的意思就像c语言中 for(i=0;i<6;i++)	
  //我们先看看如果rax为6之后又是怎么样了
  4010a8:	48 83 f8 06          	cmp    $0x6,%rax
  4010ac:	75 dd                	jne    40108b <phase_5+0x29>

  //我一看到这里 我们把这四条指令一起看
  //第四条指令调用 判断字符串是否相等 而第二条又是向寄存器存放了一个不晓得什么的东西
  //这个时候我大胆估计 这个esi装的就是我们需要匹配的字符串
  //print (char*)0x40245e 得到字符串为flyers
  //诶这里的 我们需要匹配的flyers字符串也刚好是6个字符
  //那和我们输入的6个字符又有什么联系呢
  4010ae:	c6 44 24 16 00       	movb   $0x0,0x16(%rsp)
  4010b3:	be 5e 24 40 00       	mov    $0x40245e,%esi
  4010b8:	48 8d 7c 24 10       	lea    0x10(%rsp),%rdi
  4010bd:	e8 76 02 00 00       	callq  401338 <strings_not_equal>

  //当字符串相等后 返回值为0 跳转到4010d9
  4010c2:	85 c0                	test   %eax,%eax
  4010c4:	74 13                	je     4010d9 <phase_5+0x77>
  4010c6:	e8 6f 03 00 00       	callq  40143a <explode_bomb>
  4010cb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)
  4010d0:	eb 07                	jmp    4010d9 <phase_5+0x77>

  //eax置0
  4010d2:	b8 00 00 00 00       	mov    $0x0,%eax
  4010d7:	eb b2                	jmp    40108b <phase_5+0x29>

  //这里不知道在干什么 但我们看到4010e9位置调用 stack_chk_fail函数
  //这里应该是检查堆栈是否溢出或者是也有什么地方不相同
  //反正重心应该也不会在这里
  4010d9:	48 8b 44 24 18       	mov    0x18(%rsp),%rax
  4010de:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax
  4010e5:	00 00 
  4010e7:	74 05                	je     4010ee <phase_5+0x8c>
  4010e9:	e8 42 fa ff ff       	callq  400b30 <__stack_chk_fail@plt>

 //这里调用函数结束 炸弹也就成功拆除了
  4010ee:	48 83 c4 20          	add    $0x20,%rsp
  4010f2:	5b                   	pop    %rbx
  4010f3:	c3                   	retq   

ok 这里就是连接着上面代码段 已经分析出了
maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you
这个代码了
然后我们来仔细分析一下
那个时候我是这样揣测的
因为要循坏六次 然后六次都把这个字符串的一个字符送到一个地址
后面还要进行匹配 那么 我们送到那个地址的字母
按照顺序 就应该是
f l y e r s

但是哪个字符送出去 决定权在于我们六个输入的字符的后四位

ok 我们把大概思路理清了 我们就在字符串定位即可
第一个字符 f位置在字符串地址开始 9号位 即确定后四位为9

我们的一个ASCII的字符是有一个字节长 也就是8位
后四位确定了 但是前四位没有确定 最开始的位置是符号位0
那么有三个位置不确定的 ASCII字符大小最小是32 32为空格

按照这种逻辑 我们可以列出来多个组合方式
就拿第一个举例子
32+16+9 = 57 ; 64+32+16+9 = 121 ; 32+9 = 41; 64+32+9 = 105;
64+9 = 73等等等等… 然后我们在ASCII表上找到对应的符号即可…

我这里就贴一个我满足条件的一个字符串
9?>567

最终拆弹密码可能有上百种组合
我这列出来我的一种

9?>567

去尝试一下呢 OK 拿下~
在这里插入图片描述



Phase 6

我只解决了大部分的代码qwq
到后面玩去了 就确实因为中间错了一步 有点迷糊
到最后的重构链表 和 判断我就不知道在干嘛了qwq
下面就直接贴一下人家写的特别特别清晰的解答了吧(我也还算解出来了好吗)

00000000004010f4 <phase_6>:
  4010f4:    41 56                    push   %r14
  4010f6:    41 55                    push   %r13
  4010f8:    41 54                    push   %r12
  4010fa:    55                       push   %rbp
  4010fb:    53                       push   %rbx
  4010fc:    48 83 ec 50              sub    $0x50,%rsp
  401100:    49 89 e5                 mov    %rsp,%r13
  401103:    48 89 e6                 mov    %rsp,%rsi
  401106:    e8 51 03 00 00           callq  40145c <read_six_numbers>
  40110b:    49 89 e6                 mov    %rsp,%r14 //机子上测试了下,输入的是6个4字节整数,开始地址是%rsp
  40110e:    41 bc 00 00 00 00        mov    $0x0,%r12d //%r12d = 0
  Loop 1:
  401114:    4c 89 ed                 mov    %r13,%rbp //这里跟%r13同值
  401117:    41 8b 45 00              mov    0x0(%r13),%eax //把输入的整数拿进%rax,不出意外应该是遍历操作
  40111b:    83 e8 01                 sub    $0x1,%eax //%rax -= 1
  40111e:    83 f8 05                 cmp    $0x5,%eax //%rax <= 5 ==>输入的数要小于等于6,因为无符号数,上面又-1,所以还要大于等于1
  401121:    76 05                    jbe    401128 <phase_6+0x34>
  401123:    e8 12 03 00 00           callq  40143a <explode_bomb>
  401128:    41 83 c4 01              add    $0x1,%r12d
  40112c:    41 83 fc 06              cmp    $0x6,%r12d //结合上下文,其实已经可以推出%r12d是程序计数变量了
  401130:    74 21                    je     401153 <phase_6+0x5f>
  401132:    44 89 e3                 mov    %r12d,%ebx
  Loop 2:
  401135:    48 63 c3                 movslq %ebx,%rax
  401138:    8b 04 84                 mov    (%rsp,%rax,4),%eax //程序计数变量作为数组索引,是遍历操作
  40113b:    39 45 00                 cmp    %eax,0x0(%rbp) //实际上是在把当前遍历到的数与后面的每个数作比较
  40113e:    75 05                    jne    401145 <phase_6+0x51> //可推出不能输入两个相同的数
  401140:    e8 f5 02 00 00           callq  40143a <explode_bomb>
  401145:    83 c3 01                 add    $0x1,%ebx
  401148:    83 fb 05                 cmp    $0x5,%ebx
  40114b:    7e e8                    jle    401135 <phase_6+0x41>
  Loop 2 End
  40114d:    49 83 c5 04              add    $0x4,%r13
  401151:    eb c1                    jmp    401114 <phase_6+0x20>
  Loop 1 End
  分析循环收获:一、输入的数要小于等于6并且大于等于1 二、不能输入两个相同的数
  401153:    48 8d 74 24 18           lea    0x18(%rsp),%rsi
  401158:    4c 89 f0                 mov    %r14,%rax //是输入的第一个数字
  40115b:    b9 07 00 00 00           mov    $0x7,%ecx //%rcx = 7
  Loop:
  401160:    89 ca                    mov    %ecx,%edx //看循环后面%rcx的值就没动过,可认为这里恒有%rdx=7
  401162:    2b 10                    sub    (%rax),%edx //所以是7减去每个数
  401164:    89 10                    mov    %edx,(%rax) //因为是内存引用,这里改变了数组实际的值,这个循环过后,数组里的值变成7-输入的数
  401166:    48 83 c0 04              add    $0x4,%rax //实际上还是在遍历那六个数
  40116a:    48 39 f0                 cmp    %rsi,%rax
  40116d:    75 f1                    jne    401160 <phase_6+0x6c>
  Loop End
  分析循环收获:数组的值被变成7-每个输入的数
  40116f:    be 00 00 00 00           mov    $0x0,%esi
  401174:    eb 21                    jmp    401197 <phase_6+0xa3>
  Loop 1:Loop 2:
  401176:    48 8b 52 08              mov    0x8(%rdx),%rdx //这里应该是个链表
  40117a:    83 c0 01                 add    $0x1,%eax
  40117d:    39 c8                    cmp    %ecx,%eax //%rax初始值是1,这里可看成是循环条件为%rax<7-input[i] ==>%rdx的值为node[7-input[i]]的地址(链式顺序)
  40117f:    75 f5                    jne    401176 <phase_6+0x82>
  Loop 2 End
  401181:    eb 05                    jmp    401188 <phase_6+0x94>
  Loop 3:
  401183:    ba d0 32 60 00           mov    $0x6032d0,%edx
  401188:    48 89 54 74 20           mov    %rdx,0x20(%rsp,%rsi,2) //栈中存入%rdx的值,也就是node的地址,整个循环的目的就在于这里
  40118d:    48 83 c6 04              add    $0x4,%rsi
  401191:    48 83 fe 18              cmp    $0x18,%rsi //%rsi是计数变量,看看下行跳出大循环的汇编代码,估计又是遍历了。。。
  401195:    74 14                    je     4011ab <phase_6+0xb7>
  401197:    8b 0c 34                 mov    (%rsp,%rsi,1),%ecx //7减过后的输入数字
  40119a:    83 f9 01                 cmp    $0x1,%ecx
  40119d:    7e e4                    jle    401183 <phase_6+0x8f> //小于等于1就回Loop3,意思是某个输入数字等于6就回Loop3
  Loop 3 End
  40119f:    b8 01 00 00 00           mov    $0x1,%eax //%rax要做计数变量了
  4011a4:    ba d0 32 60 00           mov    $0x6032d0,%edx //得看看这个地址装的什么,看到是node1~6,是链表结点,通过查看数据,其链式data为{332, 168, 924, 691, 477, 443},对应node{1, 2, 3, 4, 5, 6}
  4011a9:    eb cb                    jmp    401176 <phase_6+0x82>
  Loop 1 End
  分析循环收获:%rsp+0x20存了6个结点,分别为node[7-input[i]]
  4011ab:    48 8b 5c 24 20           mov    0x20(%rsp),%rbx //%rbx = node[7-input[1]]的地址
  4011b0:    48 8d 44 24 28           lea    0x28(%rsp),%rax //%rax = node栈[2]
  4011b5:    48 8d 74 24 50           lea    0x50(%rsp),%rsi //%rsi = node栈[6]
  4011ba:    48 89 d9                 mov    %rbx,%rcx //%rcx = node[7-input[1]]的地址
  Loop:
  4011bd:    48 8b 10                 mov    (%rax),%rdx //%rdx = node[7-input[i]]
  4011c0:    48 89 51 08              mov    %rdx,0x8(%rcx)
  4011c4:    48 83 c0 08              add    $0x8,%rax
  4011c8:    48 39 f0                 cmp    %rsi,%rax //%rax == node[7-input[6]]是循环退出条件,结合上边有地址偏移8取next,下边又有next赋值之类的,容易猜到这个是在重构链表
  4011cb:    74 05                    je     4011d2 <phase_6+0xde>
  4011cd:    48 89 d1                 mov    %rdx,%rcx
  4011d0:    eb eb                    jmp    4011bd <phase_6+0xc9>
  Loop End
  循环分析收获:栈中的node重构成了链
  4011d2:    48 c7 42 08 00 00 00     movq   $0x0,0x8(%rdx) //node[7-input[6]].next = NULL
  4011d9:    00 
  4011da:    bd 05 00 00 00           mov    $0x5,%ebp
  Loop:
  4011df:    48 8b 43 08              mov    0x8(%rbx),%rax
  4011e3:    8b 00                    mov    (%rax),%eax
  4011e5:    39 03                    cmp    %eax,(%rbx)
  4011e7:    7d 05                    jge    4011ee <phase_6+0xfa> //结合上边三条语句和这个循环,其实意思是:node[7-input[i]]->data >= node[7-input[i+1]]->data
  4011e9:    e8 4c 02 00 00           callq  40143a <explode_bomb>
  4011ee:    48 8b 5b 08              mov    0x8(%rbx),%rbx
  4011f2:    83 ed 01                 sub    $0x1,%ebp //这里看出%ebp是计数变量,循环实际上是for(%rbp=5; %rbp!=0 ;%rbp--)
  4011f5:    75 e8                    jne    4011df <phase_6+0xeb>
  Loop End
  循环分析收获:node[7-input[i]]->data >= node[7-input[i+1]]->data
  至此谜题已经解开
  有6个node,通过查看数据,其链式data为{
    
    332, 168, 924, 691, 477, 443},对应node{
    
    1, 2, 3, 4, 5, 6}
  7减去我们的输入所获得的node的data要符合其降序
  不考虑7减去时,输入为3, 4, 5, 6, 1, 2
  考虑7减去时,输入为4, 3, 2, 1, 6, 5。其实这个就是正确的输入
  4011f7:    48 83 c4 50              add    $0x50,%rsp
  4011fb:    5b                       pop    %rbx
  4011fc:    5d                       pop    %rbp
  4011fd:    41 5c                    pop    %r12
  4011ff:    41 5d                    pop    %r13
  401201:    41 5e                    pop    %r14
  401203:    c3                       retq   

最后再贴一下领我入门的博客吧

雾里尘埃的CSAPP Bomb Lab实验

我这个Lab也是大年初一 初二 除夕每天抽了部分时间做的
最近力扣也没有刷 不能再当懒狗了!(懒狗醒悟)!
尽管最后也是没有自己亲手做出来但是这个Lab对我而言

我的提升还是在一步一步分析中获得了
所以 Thanks for visiting this blog

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37500516/article/details/113789606
今日推荐