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. 正则表达式之RegExp对象

    1.定义 RegExp对象是原生JavaScript中表示正则表达式的对象:是正则表达式(regular expression)的简写.有一点需要明确知道,正则表达式只能对字符串进行操作. 2.语法 ...

  2. 一起了解 .Net Foundation 项目 No.8

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. IdentityModel ...

  3. 《自拍教程36》段位三_Python面向对象类

    函数只能面向过程,来回互相调用后顺序执行, 简单的编码项目,还能应付的过来, 复杂的大型项目,调用多了,就会乱. 如何才能不乱呢,可尝试下, 面向对象类的概念, 将现实世界的事物抽象成对象,将现实世界 ...

  4. Mysql8以上需要指定时区serverTimezone

    JDBC连接Mysql8以下 com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test?useUnicode=true&charac ...

  5. .NET异步程序设计之async&await

    目录 0.背景引入 1.async和await基本语法 2.异步方法的执行顺序 3.取消一个异步操作 4.同步和异步等待任务 5.异步操作中的异常处理 6.多线程和异步的区分 7. 在 .NET MV ...

  6. 为什么要使用webpack?

    在网页中会引用到哪些常见的静态资源? js (.js  .jsx  .coffee  .ts) css (.css  .less  .sass  .scss scss是sass的plus版) imag ...

  7. MacOS麦克风输入监听的方法

    Windows上很多人都知道,然而实际上并没什么用——延迟太大,根本没法用. MacOS上有两种方法: QuickTime Player新建音频录制(不需要真的录音),如下图: 这个方法和Window ...

  8. html5插件完成滚屏幕效果

    首先想要完成这样的效果要用到jquery-fullpage插件我们需要他的js文件和css样式文件如图  因为是jquery的插件所以我们还要导入jquery-min.js 在页面引入这些样式和插件 ...

  9. rest framework serializer

    串行器 扩大串行的用处是什么,我们想地址.然而,这不是一个简单的问题,它会采取一些严重的设计工作. -罗素基思-马吉,Django的用户组 串行器允许诸如查询集和模型实例复杂的数据转换为原生的Pyth ...

  10. 7种你应该知道的JavaScript常见的错误

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://blog.bitsrc.io/types-of-native-errors-in- ...