深入理解计算机系统-CSAPP:Bomb Lab必要前置知识整理与详细解读

提示用户输入正确的字符串来拆掉炸弹,如果任何一个不正确,炸弹就会“爆炸”,你必须通过逆向工程来解除炸弹,这会让你理解汇编语言,学习如何使用GDB来调试程序,设计得很有意思。

实验相关材料:

GDB快速入门材手册

Writeup

助教讲解视频

本实验需要经常查阅的内容见CSAPP

这里贴出来需要用的基础知识。

汇编基础

数据格式

数据格式
![image](https://img2022.cnblogs.com/blog/2594326/202203/2594326-20220313174636297-1617205880.png)
整数寄存器
![image](https://img2022.cnblogs.com/blog/2594326/202203/2594326-20220313175038966-139006212.png)
操作数格式
![算术操作](https://img2022.cnblogs.com/blog/2594326/202203/2594326-20220313164113315-1417841056.png)
算术操作
![条件码](https://img2022.cnblogs.com/blog/2594326/202203/2594326-20220313164246107-1109369136.png)
条件码
![跳转](https://img2022.cnblogs.com/blog/2594326/202203/2594326-20220313164351842-133691778.png)
跳转
![传参寄存器](https://img2022.cnblogs.com/blog/2594326/202203/2594326-20220313165234092-64668474.png)
传参寄存器

GDB调试快速入门

GDB调试快速入门

其他重要内容

objdump -t dump 打印符号表
objdump -d 反汇编
strings bomb 打印所有可输出的字符串
使用xxd bomb生成16进制的转换,便于查看字符串信息

1. 第一关:

通过在string_length处打断点,在%rax寄存器得到了第一个字符串和第二个字符串(答案)的长度(52),然后找答案的起始位置。
然后通过在string_not_equal打断点知道起始位置, 402400
后来定位到42 6f 72
然后使用xdd bomb > bomb.hex查看16进制的汇编 搜索426f找到字符串,然后字符串肯定以00结尾,并且我们知道长度是52
两个字节是一个字符。

2. 第二关:

对文正的esi:
esi是第二参数,即format。 查询$0x4025c3对应的源码,在汇编中对应

25642025,在bomb.hex中搜索,25642025 对应

字符串以00结尾。地址使用低32位。
可见是输入了int类型,且为6个。
__isoc99_sscanf@plt 的参数第一个是字符,第二个一个format格式

对phase_2的汇编代码进行解析

Dump of assembler code for function phase_2:
   0x0000000000400efc <+0>:     push   %rbp
   0x0000000000400efd <+1>:     push   %rbx
   0x0000000000400efe <+2>:     sub    $0x28,%rsp
   0x0000000000400f02 <+6>:     mov    %rsp,%rsi
   0x0000000000400f05 <+9>:     callq  0x40145c <read_six_numbers>  
   //读取六个int类型 详情可以研读read_six_num的代码,读取到的int从栈顶(%rsp)num[1]开始,rsp+4是num[1],%rsp+20是最后一个即num[6]
   0x0000000000400f0a <+14>:    cmpl   $0x1,(%rsp) //可见num[0]=1
   0x0000000000400f0e <+18>:    je     0x400f30 <phase_2+52>
   0x0000000000400f10 <+20>:    callq  0x40143a <explode_bomb>
   0x0000000000400f15 <+25>:    jmp    0x400f30 <phase_2+52>
   0x0000000000400f17 <+27>:    mov    -0x4(%rbx),%eax 
   0x0000000000400f1a <+30>:    add    %eax,%eax
   0x0000000000400f1c <+32>:    cmp    %eax,(%rbx) //可见num[i]= 2*num[i-1]
   0x0000000000400f1e <+34>:    je     0x400f25 <phase_2+41>
   0x0000000000400f20 <+36>:    callq  0x40143a <explode_bomb>
   0x0000000000400f25 <+41>:    add    $0x4,%rbx
   0x0000000000400f29 <+45>:    cmp    %rbp,%rbx
=> 0x0000000000400f2c <+48>:    jne    0x400f17 <phase_2+27>
   0x0000000000400f2e <+50>:    jmp    0x400f3c <phase_2+64>
   0x0000000000400f30 <+52>:    lea    0x4(%rsp),%rbx
   0x0000000000400f35 <+57>:    lea    0x18(%rsp),%rbp
   0x0000000000400f3a <+62>:    jmp    0x400f17 <phase_2+27>
   0x0000000000400f3c <+64>:    add    $0x28,%rsp
   0x0000000000400f40 <+68>:    pop    %rbx
   0x0000000000400f41 <+69>:    pop    %rbp

有phase可见,第二关密码为 1 2 4 8 16 32

3. 第三关: 这里有个坑是大小端的转化, 还有地址之间高位的不同,需要在hex文件中搜索低位地址才能搜索到

与第二关,同理,在phase_3中找到了format,对应到地址后开始找到str的结尾,

对25c进行搜索,因为40地址在hex代码中是不会对应上的(因为高位在不同的文件中不一样),精确到f也很难 我们可以找到25c 本行最后一个字符就是25cf 也即dump出来的4025cf

搜索2470对应的地址

很明显这里里存放的是地址, 并且 每一行,对应28字节 64位 。每一行2个地址 4行,8个地址,对应0-7 但是intel架构的地址是小端,也就是与人的感觉相反,把找到的地址翻转 0000 0000 0040 0f7c正好对应到原来的下一行。
对phase_3的汇编代码进行解析

Dump of assembler code for function phase_3:
=> 0x0000000000400f43 <+0>:     sub    $0x18,%rsp
   0x0000000000400f47 <+4>:     lea    0xc(%rsp),%rcx //rcx=num[1] B
   0x0000000000400f4c <+9>:     lea    0x8(%rsp),%rdx  //rdx=num[0] A
   0x0000000000400f51 <+14>:    mov    $0x4025cf,%esi  //对应到地址发现format是是个int类型,
   0x0000000000400f56 <+19>:    mov    $0x0,%eax
   0x0000000000400f5b <+24>:    callq  0x400bf0 <__isoc99_sscanf@plt> 
   //rdx是第三个参数num[0],开始位置是0x8(%rsp) 没有r8r9只使用了两个参数
   0x0000000000400f60 <+29>:    cmp    $0x1,%eax //读取到的个数不大于1 爆炸
   0x0000000000400f63 <+32>:    jg     0x400f6a <phase_3+39>
   0x0000000000400f65 <+34>:    callq  0x40143a <explode_bomb>
   0x0000000000400f6a <+39>:    cmpl   $0x7,0x8(%rsp) //A无符号无能大于7 a ->[0,7]
   0x0000000000400f6f <+44>:    ja     0x400fad <phase_3+106>  //num1超过(无符号)7 爆炸 
   0x0000000000400f71 <+46>:    mov    0x8(%rsp),%eax
   0x0000000000400f75 <+50>:    jmpq   *0x402470(,%rax,8) 
   //间接跳转 8*rax(读取到的个数4) +0x402470    这里一个大坑是,需要把大段转化成inter的小端地址
   //小端->数据的高字节,保存在内存的高地址中;数据的低字节,保存在内存的低地址中。  正好与人的直觉想法,需要吧找到的地址反过来
   //搜索2470对应的内存地址  做大小端转换 正好是400f7c 也就是下一行。  我们去A=0 则B就正好等于0xcf=207
   0x0000000000400f7c <+57>:    mov    $0xcf,%eax
   0x0000000000400f81 <+62>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f83 <+64>:    mov    $0x2c3,%eax
   0x0000000000400f88 <+69>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f8a <+71>:    mov    $0x100,%eax
   0x0000000000400f8f <+76>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f91 <+78>:    mov    $0x185,%eax
   0x0000000000400f96 <+83>:    jmp    0x400fbe <phase_3+123>
--Type <RET> for more, q to quit, c to continue without paging--m
   0x0000000000400f98 <+85>:    mov    $0xce,%eax
   0x0000000000400f9d <+90>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f9f <+92>:    mov    $0x2aa,%eax
   0x0000000000400fa4 <+97>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400fa6 <+99>:    mov    $0x147,%eax
   0x0000000000400fab <+104>:   jmp    0x400fbe <phase_3+123>
   0x0000000000400fad <+106>:   callq  0x40143a <explode_bomb>
   0x0000000000400fb2 <+111>:   mov    $0x0,%eax
   0x0000000000400fb7 <+116>:   jmp    0x400fbe <phase_3+123>
   0x0000000000400fb9 <+118>:   mov    $0x137,%eax
   0x0000000000400fbe <+123>:   cmp    0xc(%rsp),%eax
   0x0000000000400fc2 <+127>:   je     0x400fc9 <phase_3+134>
   0x0000000000400fc4 <+129>:   callq  0x40143a <explode_bomb>
   0x0000000000400fc9 <+134>:   add    $0x18,%rsp
   0x0000000000400fcd <+138>:   retq   

这里有多种答案,我们只选中其中的0 207

4. 第四关

输入与上一关类似 int A B, 其中B=0, A需要经过fun4 满足0xe // 2 == A 即A=7
对phase_4的汇编代码进行解析

   Dump of assembler code for function phase_4:
=> 0x000000000040100c <+0>:     sub    $0x18,%rsp
   0x0000000000401010 <+4>:     lea    0xc(%rsp),%rcx //B
   0x0000000000401015 <+9>:     lea    0x8(%rsp),%rdx  //A
   0x000000000040101a <+14>:    mov    $0x4025cf,%esi //读入2个int 与上一题相同, 同样也是设计了AB两个参数,在rdx于rcx中
   0x000000000040101f <+19>:    mov    $0x0,%eax
   0x0000000000401024 <+24>:    callq  0x400bf0 <__isoc99_sscanf@plt>
   0x0000000000401029 <+29>:    cmp    $0x2,%eax //读入数不是2的话爆炸
   0x000000000040102c <+32>:    jne    0x401035 <phase_4+41>
   0x000000000040102e <+34>:    cmpl   $0xe,0x8(%rsp)   //A低4字<=0xe
   0x0000000000401033 <+39>:    jbe    0x40103a <phase_4+46> //低于等于
   0x0000000000401035 <+41>:    callq  0x40143a <explode_bomb>
   0x000000000040103a <+46>:    mov    $0xe,%edx
   0x000000000040103f <+51>:    mov    $0x0,%esi   
   0x0000000000401044 <+56>:    mov    0x8(%rsp),%edi
   0x0000000000401048 <+60>:    callq  0x400fce <func4> //返回0才不爆炸, 进去看一下内容
   0x000000000040104d <+65>:    test   %eax,%eax
   0x000000000040104f <+67>:    jne    0x401058 <phase_4+76> 
   0x0000000000401051 <+69>:    cmpl   $0x0,0xc(%rsp) //B=0
   0x0000000000401056 <+74>:    je     0x40105d <phase_4+81>
   0x0000000000401058 <+76>:    callq  0x40143a <explode_bomb>
   0x000000000040105d <+81>:    add    $0x18,%rsp
--Type <RET> for more, q to quit, c to continue without paging--m
   0x0000000000401061 <+85>:    retq 

   0000000000400fce <func4>:
A,0 14  代码的含义是14/2 == A  需要满足A=7是才返回0
  400fce:	48 83 ec 08          	sub    $0x8,%rsp
  400fd2:	89 d0                	mov    %edx,%eax  ax=0xe = 14
  400fd4:	29 f0                	sub    %esi,%eax   ax-= 0 = 14
  400fd6:	89 c1                	mov    %eax,%ecx   cx = 14 = 1110
  400fd8:	c1 e9 1f             	shr    $0x1f,%ecx 右移  ecx= 7 = 111
  400fdb:	01 c8                	add    %ecx,%eax
  400fdd:	d1 f8                	sar    %eax
  400fdf:	8d 0c 30             	lea    (%rax,%rsi,1),%ecx
  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>
  400ff2:	b8 00 00 00 00       	mov    $0x0,%eax
  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   

答案 7 0

完成前4题

posted @ 2022-03-13 18:10  Llon_Cheng  阅读(632)  评论(0编辑  收藏  举报