DO NOT READ THIS ARTICLE. I wrote bullshit in English.

This lab I have finished once, so this article is just for fun.

Phase-1

0000000000400ee0 <phase_1>:
400ee0: 48 83 ec 08 sub $0x8,%rsp
400ee4: be 00 24 40 00 mov $0x402400,%esi
400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal>
400eee: 85 c0 test %eax,%eax
400ef0: 74 05 je 400ef7 <phase_1+0x17>
400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>
400ef7: 48 83 c4 08 add $0x8,%rsp
400efb: c3 retq

Just scan the memory of address [0x402400] . GDB command is x /s 0x402400 .

(gdb) x /s 0x402400
0x402400: "Border relations with Canada have never been better."

We can see that the answer is Border relations with Canada have never been better. .

Phase-2

0000000000400efc <phase_2>:
400efc: 55 push %rbp
400efd: 53 push %rbx
400efe: 48 83 ec 28 sub $0x28,%rsp
400f02: 48 89 e6 mov %rsp,%rsi
400f05: e8 52 05 00 00 callq 40145c <read_six_numbers>
400f0a: 83 3c 24 01 cmpl $0x1,(%rsp)
400f0e: 74 20 je 400f30 <phase_2+0x34>
400f10: e8 25 05 00 00 callq 40143a <explode_bomb>
400f15: eb 19 jmp 400f30 <phase_2+0x34>
400f17: 8b 43 fc mov -0x4(%rbx),%eax
400f1a: 01 c0 add %eax,%eax
400f1c: 39 03 cmp %eax,(%rbx)
400f1e: 74 05 je 400f25 <phase_2+0x29>
400f20: e8 15 05 00 00 callq 40143a <explode_bomb>
400f25: 48 83 c3 04 add $0x4,%rbx
400f29: 48 39 eb cmp %rbp,%rbx
400f2c: 75 e9 jne 400f17 <phase_2+0x1b>
400f2e: eb 0c jmp 400f3c <phase_2+0x40>
400f30: 48 8d 5c 24 04 lea 0x4(%rsp),%rbx
400f35: 48 8d 6c 24 18 lea 0x18(%rsp),%rbp
400f3a: eb db jmp 400f17 <phase_2+0x1b>
400f3c: 48 83 c4 28 add $0x28,%rsp
400f40: 5b pop %rbx
400f41: 5d pop %rbp
400f42: c3 retq

From this code read_six_number , we can see that we should input six numbers. And the we can know that there is a loop, and the most important line of code is :

400f1a:	01 c0                	add    %eax,%eax

Now, we can guess that it should be a geometric series, whose ratio is 2. What is the first element of the number series? We can see:

400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)
400f0e: 74 20 je 400f30 <phase_2+0x34>
400f10: e8 25 05 00 00 callq 40143a <explode_bomb>

OK, we can see that if (%rsp) is not equal to 0x1 , it will call function explode_bomb .

Thus, the answer is : 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
400f51: be cf 25 40 00 mov $0x4025cf,%esi
400f56: b8 00 00 00 00 mov $0x0,%eax
400f5b: e8 90 fc ff ff callq 400bf0 <__isoc99_sscanf@plt>
400f60: 83 f8 01 cmp $0x1,%eax
400f63: 7f 05 jg 400f6a <phase_3+0x27>
400f65: e8 d0 04 00 00 callq 40143a <explode_bomb>
400f6a: 83 7c 24 08 07 cmpl $0x7,0x8(%rsp)
400f6f: 77 3c ja 400fad <phase_3+0x6a>
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
400f81: eb 3b jmp 400fbe <phase_3+0x7b>
400f83: b8 c3 02 00 00 mov $0x2c3,%eax
400f88: eb 34 jmp 400fbe <phase_3+0x7b>
400f8a: b8 00 01 00 00 mov $0x100,%eax
400f8f: eb 2d jmp 400fbe <phase_3+0x7b>
400f91: b8 85 01 00 00 mov $0x185,%eax
400f96: eb 26 jmp 400fbe <phase_3+0x7b>
400f98: b8 ce 00 00 00 mov $0xce,%eax
400f9d: eb 1f jmp 400fbe <phase_3+0x7b>
400f9f: b8 aa 02 00 00 mov $0x2aa,%eax
400fa4: eb 18 jmp 400fbe <phase_3+0x7b>
400fa6: b8 47 01 00 00 mov $0x147,%eax
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
400fb7: eb 05 jmp 400fbe <phase_3+0x7b>
400fb9: b8 37 01 00 00 mov $0x137,%eax
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

Look at this line of code:

400f51:	be cf 25 40 00       	mov    $0x4025cf,%esi

Run x /s 0x4025cf in GDB, it will print: "%d %d" . Thus, we should input 2 int in this phase.

And we can see that there are many annoying jmp 0x400fb9 instructions in this assembly code, so we can infer that there is a switch-case structure.

The first 2 lines of code below shows that the first number we input (stored in [%rsp + 8]) is less equal than 7, otherwise it will call explode_bomb . The last 2 lines tell us that the program will jump to an address according to our first number.

400f6a:	83 7c 24 08 07       	cmpl   $0x7,0x8(%rsp)
400f6f: 77 3c ja 400fad <phase_3+0x6a>
400f71: 8b 44 24 08 mov 0x8(%rsp),%eax
400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)

We know that the first number (now it has been copied to %rax) can be one of number in [0,1,2,3,4,5,6,7]. So scan the address [0x402470 + %rax * 8] :

(gdb) x /x 0x402470 + 8 * 0  =>  0x402470:	0x00400f7c  => 0 0xcf
(gdb) x /x 0x402470 + 8 * 1 => 0x402478: 0x00400fb9 => 1 0x137
(gdb) x /x 0x402470 + 8 * 2 => 0x402480: 0x00400f83 => 2 0x2c3
(gdb) x /x 0x402470 + 8 * 3 => 0x402488: 0x00400f8a => 3 0x100
(gdb) x /x 0x402470 + 8 * 4 => 0x402490: 0x00400f91 => 4 0x185
(gdb) x /x 0x402470 + 8 * 5 => 0x402498: 0x00400f98 => 5 0xce
(gdb) x /x 0x402470 + 8 * 6 => 0x4024a0: 0x00400f9f => 6 0x2aa
(gdb) x /x 0x402470 + 8 * 7 => 0x4024a8: 0x00400fa6 => 7 0x147

When the first number we input is 0, the program will jump to 0x400f7c. And the code at 0x400f7c is :

400f7c:	b8 cf 00 00 00       	mov    $0xcf,%eax

So the second number is 0xcf = 207. Total answer is 0 207.

Phase-4

; first call is func4(edx=a, esi=b, edi=x)
0000000000400fce <func4>:
400fce: 48 83 ec 08 sub $0x8,%rsp
400fd2: 89 d0 mov %edx,%eax ; eax = a
400fd4: 29 f0 sub %esi,%eax ; eax = eax - esi = a - b = t1
400fd6: 89 c1 mov %eax,%ecx ; ecx = eax = a - b
400fd8: c1 e9 1f shr $0x1f,%ecx ; ecx = ecx >> 31 = t1 >> 31 = t2
400fdb: 01 c8 add %ecx,%eax ; eax = eax + ecx = t1 + t2
400fdd: d1 f8 sar %eax ; eax = eax >> 1 = (t1+t2)>>1, t1=(t1+t2)>>1
400fdf: 8d 0c 30 lea (%rax,%rsi,1),%ecx ; ecx = eax + esi = t1 + b, t2=t1+b
400fe2: 39 f9 cmp %edi,%ecx ; ecx <= x ? () : (2 * func4())
400fe4: 7e 0c jle 400ff2 <func4+0x24> ;
400fe6: 8d 51 ff lea -0x1(%rcx),%edx ; edx = ecx - 1 = t2 - 1
400fe9: e8 e0 ff ff ff callq 400fce <func4> ; func4(edx=t2-1, b, x)
400fee: 01 c0 add %eax,%eax ; return 2 * func4()
400ff0: eb 15 jmp 401007 <func4+0x39>
400ff2: b8 00 00 00 00 mov $0x0,%eax ; eax = 0
400ff7: 39 f9 cmp %edi,%ecx ; ecx >= edi ? (return 0) : ()
400ff9: 7d 0c jge 401007 <func4+0x39>
400ffb: 8d 71 01 lea 0x1(%rcx),%esi ; esi = ecx + 1
400ffe: e8 cb ff ff ff callq 400fce <func4> ; func4()
401003: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax ; return 2 * func4() + 1
401007: 48 83 c4 08 add $0x8,%rsp
40100b: c3 retq 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
40101a: be cf 25 40 00 mov $0x4025cf,%esi
; scan the address 0x4025cf
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>
40102e: 83 7c 24 08 0e cmpl $0xe,0x8(%rsp)
; the 1st number x should be x <= 15, otherwise explode
401033: 76 05 jbe 40103a <phase_4+0x2e>
401035: e8 00 04 00 00 callq 40143a <explode_bomb>
40103a: ba 0e 00 00 00 mov $0xe,%edx
40103f: be 00 00 00 00 mov $0x0,%esi
401044: 8b 7c 24 08 mov 0x8(%rsp),%edi
401048: e8 81 ff ff ff callq 400fce <func4>
; func4(edx=0xe, esi=0x0, edi=x)
40104d: 85 c0 test %eax,%eax
; the returned val of func4 shouble 0
40104f: 75 07 jne 401058 <phase_4+0x4c>
401051: 83 7c 24 0c 00 cmpl $0x0,0xc(%rsp)
; the 2nd number y should be 0, otherwise explode
; so the total condition is func(0xe,0x0,x) == 0 and y = 0
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

phase_4 call a function func4, which is a recursion. Scan the address 0x4025cf, GDB will print "%d %d", which means we should input 2 int numbers. Assume that our input is x y. The x will be stored in %rsp + 0x8 and y in %rsp + 0xc. Then phase_4 would call func4(edx=0xe, esi=0x0, edi=x), and this function call passes parameters by register. Read the comment above.

The conditions for passing phase_4 is input x y to let func(0xe, 0x0, x) return 0 and x should be less equal than 15 and y must be 0.

Read the code of func4, we can change it into C code:

int func4(int a, int b, int x)
{
x; // edi
int t1 = a - b; // eax
int t2 = ((unsigned int)t1) >> 31; // ecx
t1 = (t1 + t2) >> 1;
t2 = t1 + b;
if (t2 <= x)
{
t1 = 0;
if (t2 < x)
return 2 * func4(a, t2 + 1, x) + 1;
return t1;
}
else
return 2 * func4(t2 - 1, b, x);
}

What we need to pay attention to is this instruction: 400fd8: shr $0x1f,%ecx. The shr implies that it will operation on a unsigned type (read the C code above) .

Therefore, we can find x by enumeration.

int main()
{
int x = 0;
for (x = 0; x <= 15; x++)
{
int t = func4(0xe, 0x0, x);
if (t == 0)
printf("%d ", x);
}
}

The result is:

(x,y) = (0,0), (1,0), (3,0), (7,0)

Phase-5

0000000000401062 <phase_5>:
401062: 53 push %rbx
401063: 48 83 ec 20 sub $0x20,%rsp
; 32 bytes stack for temporary variable
401067: 48 89 fb mov %rdi,%rbx
; rdi is the address of strings we input
40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
401071: 00 00
; I don't understand here
401073: 48 89 44 24 18 mov %rax,0x18(%rsp)
401078: 31 c0 xor %eax,%eax
40107a: e8 9c 02 00 00 callq 40131b <string_length>
40107f: 83 f8 06 cmp $0x6,%eax
; we should input a string, whose len is 6
; do while loop begin, eax=0 is the counter
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>
40108b: 0f b6 0c 03 movzbl (%rbx,%rax,1),%ecx
; t = str[i]
40108f: 88 0c 24 mov %cl,(%rsp)
401092: 48 8b 14 24 mov (%rsp),%rdx
401096: 83 e2 0f and $0xf,%edx
; t = str[i] & 0xf
401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx
4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1)
; array[rsp+0x10+rax] = str2[t]
4010a4: 48 83 c0 01 add $0x1,%rax
4010a8: 48 83 f8 06 cmp $0x6,%rax
; eax++ until out of str.length
4010ac: 75 dd jne 40108b <phase_5+0x29>
4010ae: c6 44 24 16 00 movb $0x0,0x16(%rsp)
4010b3: be 5e 24 40 00 mov $0x40245e,%esi
; "flyers"
4010b8: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi
4010bd: e8 76 02 00 00 callq 401338 <strings_not_equal>
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>
4010d2: b8 00 00 00 00 mov $0x0,%eax
4010d7: eb b2 jmp 40108b <phase_5+0x29>
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

This phase_5 want us to input a string str (its length is 6), which is a simple phase.

There is a hash table in the program:

hex index: 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
hash str : m a d u i e r s n f o t v b y l

phase_5 construct a hash function is: f(x) = hash_str[x & 0xf].

We aim to let f(str) = "flyers".

flyers is equal to character 9, F, E, 4, 5, 6 in the hash table, thus, str[i] & 0xf (i=0,...,5) should be 9, F, E, 4, 5, 6. We can check the ASCII table to get characters:

0x39  0x3F  0x3E  0x34  0x35  0x36
'9' '?' '>' '4' '5' '6'

The string "9?>456" is the key to pass this phase.

If you still do not understand, see the C code:

void phase5(const char *input)
{
const char *hash_str = "maduiersnfotvbyl";
char array[7];
int i = 0;
for (i = 0; i < 6; i++)
array[i] = hash_str[input[i] & 0xf];
if (sting_not_equal(array, "flyers"))
explode();
}

Evaluation

All the answers in a text files sin.ans:

unix > cat sin.ans
Border relations with Canada have never been better.
1 2 4 8 16 32
0 207
7 0 DrEvil
9?>456
4 3 2 1 6 5
20

Execute the bomb binary file:

unix > ./bomb  sin.ans
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Phase 1 defused. How about the next one?
That's number 2. Keep going!
Halfway there!
So you got that one. Try this one.
Good work! On to the next...
Curses, you've found the secret phase!
But finding it and solving it are quite different...
Wow! You've defused the secret stage!
Congratulations! You've defused the bomb!

Summary

好无聊,希望早点开学

CSAPP-bomblab的更多相关文章

  1. CSAPP 之 BombLab 详解

    前言 本篇博客将会展示 CSAPP 之 BombLab 的拆弹过程,粉碎 Dr.Evil 的邪恶阴谋.Dr.Evil 的替身,杀手皇后,总共设置了 6 个炸弹,每个炸弹对应一串字符串,如果字符串错误, ...

  2. CSAPP:bomblab

    BOMBLAB实验总结 CSAPP实验BOMB,很头疼,看不懂,勉强做完了. 答案是这样的: Border relations with Canada have never been better. ...

  3. 终于要开始做大名鼎鼎的BombLab了!

    首先是一些准备工作 lab下载地址:http://csapp.cs.cmu.edu/3e/labs.html 第二个的Bomblab的 self-study handout就是 在做这个lab前,首先 ...

  4. 在Ubuntu下使用 csapp.h 和 csapp.c

    它山之石可以攻玉. 对于<深入理解计算机系统>这本神人写就的神书, 我等凡人就不评论什么啦. 这本书的 第二,三 部分, 真的真的对我理解操作系统有很大的帮助. (当然, 如果你不看第一部 ...

  5. CSAPP读书随笔之一:为什么汇编器会将call指令中的引用的初始值设置为-4

    CSAPP,即<深入理解计算机系统:程序员视角>第三版,是一本好书,但读起来确需要具备相当的基本功.而且,有的表述(中译文)还不太直白. 比如,第463页提到,(对于32位系统)为什么汇编 ...

  6. 深入理解计算机中的 csapp.h和csapp.c

    csapp.h其实就是一堆头文件的打包,在http://csapp.cs.cmu.edu/public/code.html 这里可以下载.这是<深入理解计算机系统>配套网站. 在头文件的# ...

  7. CSAPP(前言)

    很久之前就听过有过CSAPP这本书的传闻了,今天终于决定上手这本神作:既然是神作,就要仔细拜读一下,今天看了一下前言部分还真的令人耳目一新,单单是前言部分就让我学习到几个新的知识点: 1.c和Java ...

  8. CSAPP缓冲区溢出攻击实验(上)

    CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...

  9. 读完了csapp(中文名:深入理解计算机系统)

    上个星期最终把csapp看完了. 我买的是中文版的,由于除了貌似评价不错以外,由于涉及到些自己不了解的底层东西,怕是看英文会云里雾里.如今看来,大概不能算是个长处,可是的确可以加快我的看书速度,否则一 ...

  10. CSAPP Lab2: Binary Bomb

    著名的CSAPP实验:二进制炸弹 就是通过gdb和反汇编猜测程序意图,共有6关和一个隐藏关卡 只有输入正确的字符串才能过关,否则会程序会bomb终止运行 隐藏关卡需要输入特定字符串方会开启 实验材料下 ...

随机推荐

  1. 代工黑马,纬创如何强吞iPhone?

    ​ 现在,智能手机市场非常得意兴阑珊,以苹果为首的最强大脑似乎再也想不出什么好的创意,iPhone7也只不过是旧机种的翻新款式,看上去跟一块板砖.一块镜子差不多:软体方面则出现了大批的"过度 ...

  2. DDL库和表的管理

    库和表的管理 一. 库的管理 /* 语法: create database [if not exists]库名; */ #.创建库Books CREATE DATABASE IF NOT EXISTS ...

  3. 基于FPGA的RGB图像转灰度图像算法实现

    一.前言 最近学习牟新刚编著<基于FPGA的数字图像处理原理及应用>的第六章直方图操作,由于需要将捕获的图像转换为灰度图像,因此在之前代码的基础上加入了RGB图像转灰度图像的算法实现. 2 ...

  4. 泰拉瑞亚Linux主机打造指南

    最近玩了泰拉瑞亚,一个2D版的我的世界,但苦于steam的联机太过不靠谱,经常会出现和朋友之间联机失败的问题,所以我把服务器放到了部署我博客的服务器,这样就可以通过IP直接让好友加入游戏了! 首先是购 ...

  5. Java入门教程三(流程控制)

    概述 程序有 3 种结构:顺序结构.选择结构和循环结构.分别为:if elseswitch case,while与do while,for, foreach,return,break ,continu ...

  6. linux安装国产数据库(金仓数据库,达梦数据库,南大通用数据库)

    今天在公司做的任务是,在Linux的环境下安装三种数据库,结果一种数据库也没有安装好,首先遇到的问题是安装南大通用数据库遇到安装的第五步,就出现问题了,问题是Gbase SDK没有安装成功,以及Gba ...

  7. Java面试必问之Hashmap底层实现原理(JDK1.7)

    1. 前言 Hashmap可以说是Java面试必问的,一般的面试题会问: Hashmap有哪些特性? Hashmap底层实现原理(get\put\resize) Hashmap怎么解决hash冲突? ...

  8. Python 中的集合 --set

    前言 在Python中,我们用[]来表示列表list,用()来表示元组tuple,那{}呢?{}不光可用来定义字典dict,还可以用来表示集合set. 集合 set 集合(set)是一个无序的不重复元 ...

  9. 基础JavaScript练习(一)总结

    任务目的 在上一任务基础上继续JavaScript的体验 接触一下JavaScript中的高级选择器 学习JavaScript中的数组对象遍历.读写.排序等操作 学习简单的字符串处理操作 任务描述 参 ...

  10. 必备技能六、Vue框架引入JS库的正确姿势

    在Vue.js应用中,可能需要引入Lodash,Moment,Axios,Async等非常好用的JavaScript库.当项目变得复杂庞大,通常会将代码进行模块化拆分.可能还需要跑在不同的环境下,比如 ...