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. 【Java】macOS下编译JDK8

    安装mercurial brew install mercurial 下载源码 1234 hg clone http://hg.openjdk.java.net/jdk8/jdk8 java-sour ...

  2. LSTM 句子相似度分析

    使用句子中出现单词的Vector加权平均进行文本相似度分析虽然简单,但也有比较明显的缺点:没有考虑词序且词向量区别不明确.如下面两个句子: "北京的首都是中国"与"中国的 ...

  3. Java入门教程七(数组)

    数组是最常见的一种数据结构,它是相同类型的用一个标识符封装到一起的基本类型数据序列或者对象序列.数组使用一个统一的数组名和不同的下标来唯一确定数组中的元素.实质上,数组是一个简单的线性序列,因此访问速 ...

  4. Swift和Objective-C中的协议(protocol)有什么异同

    Swift和Objective-C中的protocol的相同点在于:两者可以被用作代理.Objective-C中的protocol类似于Java中的Interface,在实际开发中主要用与适配器模式( ...

  5. Python学习笔记--装饰器的实验

    装饰器既然可以增加原来函数的功能,那能不能改变传给原函数的参数呢? 我们实验一下,先上代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date ...

  6. Apple App签名机制

    概览 数字签名 签名机制与验证过程 操作流程 数字签名 摘要算法 将任意长度文本通过一个算法得到一个固定长度的文本. 源文本不同,计算结果必然不同 无法从结果反推源 例如,MD5和SHA算法 非对称加 ...

  7. Flutter01-学习准备

    1. 简介: Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面. Flutter可以与现有的代码一起工作.在全世界,Flutter正在被越来越多的开发者和 ...

  8. DIV的失去焦点(blur)实现

    用防抖实现DIV鼠标移出消失   由于div标签本身不支持onblur事件,所以对于点击一个按钮弹出的div,我们想要当这个div失去焦点的时候,让它消失不能使用的onblur来实现.  但是可以利用 ...

  9. Python——工厂模式

    目录 前言 一.简单工厂 二.工厂方法 抽象工厂 结论 参考 前言 工厂模式,顾名思义就是我们可以通过一个指定的"工厂"获得需要的"产品". 在设计模式中主要用 ...

  10. Python之接口测试(一)

    前言 之前我们已经学会了利用JMeter工具进行接口测试,今天我们学习一下如何利用python进行接口测试. 一:发送get请求 import requests,json url = 'http:// ...