深入理解计算机系统-CSAPP:Bomb Lab必要前置知识整理与详细解读
提示用户输入正确的字符串来拆掉炸弹,如果任何一个不正确,炸弹就会“爆炸”,你必须通过逆向工程来解除炸弹,这会让你理解汇编语言,学习如何使用GDB来调试程序,设计得很有意思。
实验相关材料:
GDB快速入门材手册
Writeup
助教讲解视频
本实验需要经常查阅的内容见CSAPP
这里贴出来需要用的基础知识。
汇编基础
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题