CSAPP--BombLab
BombLab
一、 Lab介绍
官网地址
在这里首先给出BombLab的官网地址:http://csapp.cs.cmu.edu/3e/labs.html
进入官网后即可看到BombLab的介绍:
简单翻译一下:BombLab其实就是只提供给你一个可执行文件,让你利用对可执行文件进行逆向,分析逆向出来的汇编代码,以提高机器级编程的能力。BombLab总共有六关,难度也是越来越高,但一个个分析出来的话,成就感是非常高的!!!前置知识
1、 了解Linux操作系统的基本使用,能熟练使用Linux的基本指令。
2、 熟练掌握x86汇编语言(如果不熟悉x86汇编语言,可以去CSAPP第三章学习)
3、 熟练掌握gdb
二、 环境准备
下载相关资源
我们用到的资源也就两个:Writeup和Self-Study Handout- Writeup里面放置着Lab的介绍
- Self-StudyHandout里面即是资源文件(一个c文件、一个可执行文件、一个README文档)。
Self-Study Handout下载下来解压完成之后如下:
Linux环境搭建
因为该Lab必须基于Linux操作系统,所以我建议完全不了解Linux的小伙伴先去补一下Linux的基础知识,再返回来做这个Lab。在这里推荐一下韩顺平老师的Linux课程,在B站有视频。
Linux环境有了之后,之后就是检查Linux系统是否有我们开发所需的工具。
最关键的两个工具分别是objdump和gdb。这里我们就只演示gdb,objdump也是一样的道理。
首先需要判断本机是否有gdb。使用命令which gdb
。
如果下面显示出gdb的路径来:如usr/bin/gdb
,则说明本机已有gdb。如果不是,则使用命令yum install gdb
命令下载gdb。
好的,以上所有关于环境的问题,我们就都解决了,下面我们就可以正式开启BombLab了!!!
三、 具体内容
Level 1
首先,将资源文件放入Linux系统后,我们需要做的一件事便是查看各个资源文件:
README文件如下:
C文件如下:
/**************************************************************************** Dr. Evil's Insidious Bomb, Version 1.1* Copyright 2011, Dr. Evil Incorporated. All rights reserved.** LICENSE:** Dr. Evil Incorporated (the PERPETRATOR) hereby grants you (the* VICTIM) explicit permission to use this bomb (the BOMB). This is a* time limited license, which expires on the death of the VICTIM.* The PERPETRATOR takes no responsibility for damage, frustration,* insanity, bug-eyes, carpal-tunnel syndrome, loss of sleep, or other* harm to the VICTIM. Unless the PERPETRATOR wants to take credit,* that is. The VICTIM may not distribute this bomb source code to* any enemies of the PERPETRATOR. No VICTIM may debug,* reverse-engineer, run "strings" on, decompile, decrypt, or use any* other technique to gain knowledge of and defuse the BOMB. BOMB* proof clothing may not be worn when handling this program. The* PERPETRATOR will not apologize for the PERPETRATOR's poor sense of* humor. This license is null and void where the BOMB is prohibited* by law.***************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include "support.h"
#include "phases.h"/* * Note to self: Remember to erase this file so my victims will have no* idea what is going on, and so they will all blow up in a* spectaculary fiendish explosion. -- Dr. Evil */FILE *infile;int main(int argc, char *argv[])
{char *input;/* Note to self: remember to port this bomb to Windows and put a * fantastic GUI on it. *//* When run with no arguments, the bomb reads its input lines * from standard input. */if (argc == 1) { infile = stdin;} /* When run with one argument <file>, the bomb reads from <file> * until EOF, and then switches to standard input. Thus, as you * defuse each phase, you can add its defusing string to <file> and* avoid having to retype it. */else if (argc == 2) {if (!(infile = fopen(argv[1], "r"))) {printf("%s: Error: Couldn't open %s\n", argv[0], argv[1]);exit(8);}}/* You can't call the bomb with more than 1 command line argument. */else {printf("Usage: %s [<input_file>]\n", argv[0]);exit(8);}/* Do all sorts of secret stuff that makes the bomb harder to defuse. */initialize_bomb();printf("Welcome to my fiendish little bomb. You have 6 phases with\n");printf("which to blow yourself up. Have a nice day!\n");/* Hmm... Six phases must be more secure than one phase! */input = read_line(); /* Get input */phase_1(input); /* Run the phase */phase_defused(); /* Drat! They figured it out!* Let me know how they did it. */printf("Phase 1 defused. How about the next one?\n");/* The second phase is harder. No one will ever figure out* how to defuse this... */input = read_line();phase_2(input);phase_defused();printf("That's number 2. Keep going!\n");/* I guess this is too easy so far. Some more complex code will* confuse people. */input = read_line();phase_3(input);phase_defused();printf("Halfway there!\n");/* Oh yeah? Well, how good is your math? Try on this saucy problem! */input = read_line();phase_4(input);phase_defused();printf("So you got that one. Try this one.\n");/* Round and 'round in memory we go, where we stop, the bomb blows! */input = read_line();phase_5(input);phase_defused();printf("Good work! On to the next...\n");/* This phase will never be used, since no one will get past the* earlier ones. But just in case, make this one extra hard. */input = read_line();phase_6(input);phase_defused();/* Wow, they got it! But isn't something... missing? Perhaps* something they overlooked? Mua ha ha ha ha! */return 0;
}
通过分析C文件我们可以发现,分别调用6个函数,分别代表六关,每一关都需要我们输入一个字符串,然后将该字符串的首地址传入函数,如果传入的字符串正确,函数正常返回,进入下一关。如果不正确,则闯关失败!
可执行文件不可直接查看,我们将其反汇编并写入bomb.txt中。
使用命令:objdump -S -d bomb > bomb.txt
即可完成上面的操作。
查看bomb.txt就可以发现可执行文件所需的所有函数的反汇编代码都可以看到,当然我们只需要对我们有用的就够了。由于代码太多,我这里就不全放过来了。
部分代码如下:
接下来,我们就可以分析第一关的反汇编代码了。
400ee0:即对栈帧进行初始化。
400ee4:将$0x402400传入%esi中
400ee9:调用strings_not_equal函数,将%rdi和%rsi传入,%rdi即为我们输入的字符串的首地址,%rsi即为$0x402400
400eee:将strings_not_equal函数的返回值%eax与0进行比较
400ef0:若%eax为0跳转到400ef7,成功返回函数
400ef2:若%eax不为0,执行这句,调用explode_bomb,即引爆炸弹,闯关失败。
通过以上分析,我们可以得出:只需满足$0x402400里存放的字符串与我们输入的字符串相等即可。
我们通过gdb运行程序bomb,在0x400ee9处打上断点。暂时随便输入一个字符串,查看0x402400处存放的字符串。
可以看到,0x402400处存放的字符串为:“Border relations with Canada have never been better.”
所以第一关的答案就是"Border relations with Canada have never been better."
我们输入答案,可以看到进入第二关了!!!
- Level 2
首先,我们分析第二关的反汇编代码:
400efc~400efe:对栈帧进行初始化
400f02:将栈指针放入%rsi中
400f05:调用read_six_numbers函数,将%rdi和%rsi传入,%rdi即为我们输入的字符串首地址,%rsi即为栈指针
400f0a:比较栈指针指向的数据是否等于1,若等于1,跳转到400f30,若不等于1,接着执行400f10,即引爆炸弹,闯关失败。
400f30:%rsp + 0x4 赋值给 %rbx
400f35:%rsp + 0x18 赋值给 %rbp
400f3a:无条件跳转到400f17
400f17:将(%rbx - 0x4)处的值赋值给%eax
400f1a:将%eax的值乘2
400f1c:比较%eax和(%rbx)处的值比较,若相等,则跳转到400f25,若不相等,则继续执行400f20,即引爆炸弹,闯关失败。
400f25:将%rbx的值+4
400f29:比较%rbp和%rbx的值,如果不相等,则继续跳转到400f17,如果相等则跳转到400f3c,即成功返回函数。
通过以上分析,我们得出结论,我们需要输入一个包含6个数字的字符串,而read_six_numbers函数会将我们字符串的六个数字保存在栈中,这六个数字需要满足的条件是:1、第一个数字为1。2、 之后每个是之前的2倍。所以得出第二关的答案:1 2 4 8 16 32
我们输入答案,可以看到进入第三关了!!!
Level 3
首先,我们分析第三关的反汇编代码:
400f43:栈帧的初始化
400f47:将 %rsp + 0xc 赋值给%rcx
400f4c:将 %rsp + 0x8 赋值给%rdx
400f51:将 0x4025cf 赋值给%esi
400f56:将 0x0 赋值给%eax
400f5b:调用函数__isoc99_sscanf@plt
400f60:比较0x1和%eax的大小,若大于1,跳转到400f6a,反之,引爆炸弹,闯关失败。
400f6a:比较0x7和(0x8 + %rsp)的大小,若大于7,则引爆炸弹,闯关失败,若不大于7,继续执行400f71。
400f71:将(%rsp + 0x8)赋值给%eax
400f75:跳转到(0x402070 + 0x8 * %rax)处保存的地址处,即(0x402070 + 0x8 * %rax)是一个地址,我们要去的地方的地址,存在这个地址的数据处。
400f7c~400fab:这部分即上一步要跳转的地址,将特定数据赋值给%eax,然后跳转到400fbe
400fbe:比较(0xc + %rsp)中的值和%eax,若等于,则跳转到400fc9,即函数正常结束。若不等于,则继续执行400fc4,即引爆炸弹,闯关失败。
通过以上分析,我们可以得出:我们输入的字符串需要两个整数,(0x8 + %rsp)中存放的便是第一个数字,(0xc + %rsp)中存放的便是第二个数字。第一个数字的取值不可大于7,故取值范围为:0~7。第一个数字的每个对应的第二个数字都在400f7c – 400fab处告诉我们了。所以第三关的答案不止一个。
下面列出所有答案:
0 207
1 311
2 707
3 256
4 389
5 206
6 682
7 327
我们输入答案,可以看到进入第四关了!!!
Level 4
首先,我们分析第四关的反汇编代码:
40100c:栈帧的从初始化
401010:将 %rsp + 0xc 赋值给%rcx
401015:将 %rsp + 0x8 赋值给%rdx
40101a:将 0x4025cf 赋值给%esi
40101f:将 0 赋值给%eax
401024:调用函数__isoc99_sscanf@plt
401029:比较函数返回值%eax和0x2的大小,若不等于2,则跳转到401035,即引爆炸弹,闯关失败。若等于2,则继续执行40102e
40102e:比较(0x8 + %rsp)处的值和 0xe 的大小,若小于等于,则跳转到40103a。反之,则继续执行,即引爆炸弹,闯关失败。
40103a:将0xe赋值给%edx
40103f:将0x0赋值给%esi
401044:将(0x8 + %rsp)赋值给%edi
401048:跳转到400fce,调用func4函数,参数分别为%rdi,%rsi,%rdx
400fce:func4函数栈帧的初始化
400fd2:将%edx赋值给%eax
400fd4:%eax减去%esi
400fd6:将%eax赋值给%ecx
400fd8:将%ecx逻辑右移0x1f位
400fdb:将 %eax + %ecx 赋值给 %eax
400fdd:将 %eax 算术右移一位
400fdf: 将 %rax + %rsi * 1 赋值给%ecx
400fe2:比较%ecx和%edi,若%ecx小于等于%edi,则跳转到400ff2。反之,将%rcx - 0x1赋值给%edx,继续递归调用func4函数。
400ff2: 将0x0赋值给%eax
400ff7: 比较%ecx和%edi的值,若%ecx大于等于%edi,则跳转到401007,函数正常返回,转而执行40104d。反之,将%rcx + 0x1赋值给%esi,继续递归调用func4函数。
40104d:比较0x0与返回值%eax的大小,若不等于,则调用401058,即引爆炸弹,闯关失败。反之继续执行401051
401051:比较(0xc + %rsp)的值与0x0的大小,若相等,函数正常结束,若不相等,引爆炸弹,闯关失败。
通过以上分析,我们可以得出:这一关我们输入的字符串须是两个数字,并且第二个数字必须是0,第一个数字必须小于等于0xe。通过分析func4中的代码,我们可以发现当第一个数字为0x7时,func4函数可以正常返回0。故第四关的答案为:7 0
我们输入答案,可以看到进入第五关了!!!
- Level 5
首先,我们分析第五关的反汇编代码:
401062~40106a:栈帧的初始化
401073:将%rax存入到(%rsp + 0x18)
401078:将%rax置零
40107a:调用string_length函数,将%rdi(我们输入的字符串的首地址)传入
40107f: 比较%eax与0x6的大小,若相等,则跳转到4010d2,若不相等,则引爆炸弹,闯关失败。
4010d2:将0x0赋值给%eax
4010d7:无条件跳转到40108b
40108b:使用零拓展数据传送指令,将(%rbx + %rax * 1)的值赋值给%ecx
40108f:将%cl中的值赋值给(%rsp)
401092:将(%rsp)中的值赋值给%rdx
401096:将寄存器 %edx 与 0xf 做与运算的值赋值给 %edx
401099:使用零拓展数据传送指令,将(%rdx + 0x4024b0)的值赋值给%edx
4010a0:将 %dl 中的值赋值给(0x10 + %rsp + %rax * 1)
4010a4:将 %rax 的值+1
4010a8:比较 %rax 的值与0x6,若相等,则继续执行4010ae,若不等,则返回40108b。
4010ae:将0x0赋值给(0x16 + %rsp)
4010b3:将0x40245e赋值给%esi
4010b8:将 0x10 + %rsp 赋值给%rdi
4010bd:调用函数string_not_equal,第一个参数为我们输入的字符串经修改后的地址,第二个参数为正确答案所在的字符串的地址
4010c2:测试%eax是否等于0,若等于0,则跳转到4010d9,即函数正常返回,若不等于0,则引爆炸弹,闯关失败。
通过以上分析,我们可以得出,我们输入的字符串的长度必须为6,并且经过变换之后可以得到目标字符串:“flyers”,经计算,最后得出第五关的答案为:ionefg
我们输入答案,可以看到进入第六关了!!!
Level 6
第六关的反汇编代码:
00000000004010f4 <phase_6>:4010f4: 41 56 push %r144010f6: 41 55 push %r134010f8: 41 54 push %r124010fa: 55 push %rbp4010fb: 53 push %rbx4010fc: 48 83 ec 50 sub $0x50,%rsp401100: 49 89 e5 mov %rsp,%r13401103: 48 89 e6 mov %rsp,%rsi401106: e8 51 03 00 00 callq 40145c <read_six_numbers>40110b: 49 89 e6 mov %rsp,%r1440110e: 41 bc 00 00 00 00 mov $0x0,%r12d401114: 4c 89 ed mov %r13,%rbp401117: 41 8b 45 00 mov 0x0(%r13),%eax40111b: 83 e8 01 sub $0x1,%eax40111e: 83 f8 05 cmp $0x5,%eax401121: 76 05 jbe 401128 <phase_6+0x34>401123: e8 12 03 00 00 callq 40143a <explode_bomb>401128: 41 83 c4 01 add $0x1,%r12d40112c: 41 83 fc 06 cmp $0x6,%r12d401130: 74 21 je 401153 <phase_6+0x5f>401132: 44 89 e3 mov %r12d,%ebx401135: 48 63 c3 movslq %ebx,%rax401138: 8b 04 84 mov (%rsp,%rax,4),%eax40113b: 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,%ebx401148: 83 fb 05 cmp $0x5,%ebx40114b: 7e e8 jle 401135 <phase_6+0x41>40114d: 49 83 c5 04 add $0x4,%r13401151: eb c1 jmp 401114 <phase_6+0x20>401153: 48 8d 74 24 18 lea 0x18(%rsp),%rsi401158: 4c 89 f0 mov %r14,%rax40115b: b9 07 00 00 00 mov $0x7,%ecx401160: 89 ca mov %ecx,%edx401162: 2b 10 sub (%rax),%edx401164: 89 10 mov %edx,(%rax)401166: 48 83 c0 04 add $0x4,%rax40116a: 48 39 f0 cmp %rsi,%rax40116d: 75 f1 jne 401160 <phase_6+0x6c>40116f: be 00 00 00 00 mov $0x0,%esi401174: eb 21 jmp 401197 <phase_6+0xa3>401176: 48 8b 52 08 mov 0x8(%rdx),%rdx40117a: 83 c0 01 add $0x1,%eax40117d: 39 c8 cmp %ecx,%eax40117f: 75 f5 jne 401176 <phase_6+0x82>401181: eb 05 jmp 401188 <phase_6+0x94>401183: ba d0 32 60 00 mov $0x6032d0,%edx401188: 48 89 54 74 20 mov %rdx,0x20(%rsp,%rsi,2)40118d: 48 83 c6 04 add $0x4,%rsi401191: 48 83 fe 18 cmp $0x18,%rsi401195: 74 14 je 4011ab <phase_6+0xb7>401197: 8b 0c 34 mov (%rsp,%rsi,1),%ecx40119a: 83 f9 01 cmp $0x1,%ecx40119d: 7e e4 jle 401183 <phase_6+0x8f>40119f: b8 01 00 00 00 mov $0x1,%eax4011a4: ba d0 32 60 00 mov $0x6032d0,%edx4011a9: eb cb jmp 401176 <phase_6+0x82>4011ab: 48 8b 5c 24 20 mov 0x20(%rsp),%rbx4011b0: 48 8d 44 24 28 lea 0x28(%rsp),%rax4011b5: 48 8d 74 24 50 lea 0x50(%rsp),%rsi4011ba: 48 89 d9 mov %rbx,%rcx4011bd: 48 8b 10 mov (%rax),%rdx4011c0: 48 89 51 08 mov %rdx,0x8(%rcx)4011c4: 48 83 c0 08 add $0x8,%rax4011c8: 48 39 f0 cmp %rsi,%rax4011cb: 74 05 je 4011d2 <phase_6+0xde>4011cd: 48 89 d1 mov %rdx,%rcx4011d0: eb eb jmp 4011bd <phase_6+0xc9>4011d2: 48 c7 42 08 00 00 00 movq $0x0,0x8(%rdx)4011d9: 00 4011da: bd 05 00 00 00 mov $0x5,%ebp4011df: 48 8b 43 08 mov 0x8(%rbx),%rax4011e3: 8b 00 mov (%rax),%eax4011e5: 39 03 cmp %eax,(%rbx)4011e7: 7d 05 jge 4011ee <phase_6+0xfa>4011e9: e8 4c 02 00 00 callq 40143a <explode_bomb>4011ee: 48 8b 5b 08 mov 0x8(%rbx),%rbx4011f2: 83 ed 01 sub $0x1,%ebp4011f5: 75 e8 jne 4011df <phase_6+0xeb>4011f7: 48 83 c4 50 add $0x50,%rsp4011fb: 5b pop %rbx4011fc: 5d pop %rbp4011fd: 41 5c pop %r124011ff: 41 5d pop %r13401201: 41 5e pop %r14401203: c3 retq
第六关略显复杂,若要一步一步仔细讲解,会花费大量篇幅,而且也不一定能讲明白(因为太过复杂ε(┬┬﹏┬┬)3)。这里直接给出第六关的答案:4 3 2 1 6 5
。小伙伴们如果觉得第六关过于复杂,可以看情况跳过,把前五个弄明白就可以了,当然想挑战自己的小伙伴也可以尝试一下,并不难,只是特麻烦,多花点时间也不是问题。
四、 结尾语
以上就是BombLab的全部内容了。通过这个Lab我们可以更加深入的理解了机器级编程,对计算机底层有了更深的认识。希望本人写的这篇文章对您有所帮助,谢谢!!!
CSAPP--BombLab相关推荐
- CSAPP bomblab
bomblab 准备工作 首先我们将目标程序转换成汇编代码写入到bomb.txt方便查看 然后打开这个文件查看内容 phase_1 这里我们直接转换成伪c代码: // 先将栈区减少8 esi = 0x ...
- CSAPP lab2 经典的bomblab二次学习
csapp上的实验一直收到广泛好评,其中第二个实验bomblab则是一个学习C语言及其转化汇编指令的非常好的小项目,前段时间刚刚借鉴了很多教程完成了整个lab的6个小实验(还有一个secret pha ...
- CSAPP深入理解计算机——bomblab(2018)
准备工作 1. 做该实验,务必已经看完了深入理解计算机系统的第三章节.了解常见c语言结构对应的汇编代码的常见形式. 2. 同时,请务必去卡梅隆大学课程官网,查看说明文件.下载gdb,一般ubuntu自 ...
- 堆栈图解CSAPP Bomb Lab实验解析
CSAPP Bomb Lab 实验解析 Bomblab是csapp的第二个配套实验,该实验提供了一个bomb二进制文件和一个bomb.c源文件,我们的目标是运行bomb并按照提示一步步输入字符串,直到 ...
- CSAPP Lab2 实验记录 ---- Bomb Lab(Phase 1 - Phase 6详细解答 + Secret Phase彩蛋解析)
文章目录 Lab 总结博客链接 实验前提引子 实验需要指令及准备 Phase 1 Phase 2 Phase 3 Phase 4 Phase 5 Phase 6 Phase Secret(彩蛋Phas ...
- 国外计算机课程lab,计算机系统实验之bomblab
今天刚刚验收CSAPP实验3,趁着余温,记录一下这个实验,顺便回顾下CSAPP课程的相关知识. 实验目的 1.使用gdb工具反汇编出汇编代码,结合c语言文件找到每个关卡的入口函数.然后分析汇编代码,分 ...
- csapp炸弹实验_bomb_lab详解
个人博客:sekyoro.top 之前图床挂了(没错是gitee),现在更新一下 文章目录 开始的准备 objdump与gdb常用命令 objdump gdb readelf 正式开始 initial ...
- csapp 、sicp 、深入理解计算机系统、 计算机程序的构造和解释
CSAPP 第一版的英文版 深入理解计算机系统第一版中文版 这个是csdn账号 这里上传文件大小在10M以内 这个pdf是19+M的 深入理解计算机系统第二版的中文版下载 第一版英文版的介绍原书 ...
- CSAPP第五章就在“扯淡”!
"你的时间有限,所以不要为别人而活.不要被教条所限,不要活在别人的观念里.不要让别人的意见左右自己内心的声音.最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实 ...
- csapp:无符号数可能造成的程序bug
出自csapp练习2.26 size_t strlen(const char *s); int strloner(char *s,char *t) {return strlen(s)-strlen(t ...
最新文章
- 电商的本质是“商”还是“用户”?
- WPF下如何去除WebBrowser的滚动条和捕获关闭事件
- java mcrypt encrypt_PHP mcrypt_encrypt加密,使用java解密
- 模拟实现顺序表ArrayList1(三级)
- superset可视化-桑基图(sankey diagram)
- 服务器e系列和l的区别,i.e.和 e.g.的区别和使用方法
- 【tensorflow】static_rnn与dynamic_rnn的区别
- DeepFM调参总结
- 输入一个三位整数,求出该数字各个位的数字之和
- 力扣160.相交链表
- eclipse-sql server 2008连接
- 追本溯源:字符串及编码
- 山东建筑大学计算机期末试题,2018年山东建筑大学计算机科学与技术学院900计算机专业综合之计算机操作系统考研基础五套测试题...
- 【已解决】Could not get lock /var/lib/dpkg/lock-frontend
- Query with 0 value even no record found
- 做XH2.54杜邦线材料-导线
- js去空格 回车 制表符 换页符
- 可视化 | 人物画像的设计方法
- 小米手机android目录在哪里设置字体,[小米手机]小米手机MIUI自己制作.MTZ字体包方法 无需ROOT权限...
- 机器人视觉硬件方案设计对比
热门文章
- [PMLR 2017] On calibration of modern neural networks
- QTP破解方法,插件延长使用时间方法,及mgn-mqt82.exe下载
- 数据中台架构体系理解
- 华农计算机科学转专业,转专业门槛有多高? 每8名新生就有一个想转专业
- Linux 内核clk 硬件相关层
- Unity中的异步编程【1】—— Unity与async 、 await
- 专业计算机术语中英文对照(二)
- 车路协同、车联网、智慧交通、智能网联车、自动驾驶、无人驾驶、高精度地图
- 计算机网络常见面试题(自答版)
- LSI SAS9311-8i阵列卡更新固件、刷新IT模式过程详解