CSAPP-bomblab
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的更多相关文章
- CSAPP 之 BombLab 详解
		
前言 本篇博客将会展示 CSAPP 之 BombLab 的拆弹过程,粉碎 Dr.Evil 的邪恶阴谋.Dr.Evil 的替身,杀手皇后,总共设置了 6 个炸弹,每个炸弹对应一串字符串,如果字符串错误, ...
 - CSAPP:bomblab
		
BOMBLAB实验总结 CSAPP实验BOMB,很头疼,看不懂,勉强做完了. 答案是这样的: Border relations with Canada have never been better. ...
 - 终于要开始做大名鼎鼎的BombLab了!
		
首先是一些准备工作 lab下载地址:http://csapp.cs.cmu.edu/3e/labs.html 第二个的Bomblab的 self-study handout就是 在做这个lab前,首先 ...
 - 在Ubuntu下使用 csapp.h 和 csapp.c
		
它山之石可以攻玉. 对于<深入理解计算机系统>这本神人写就的神书, 我等凡人就不评论什么啦. 这本书的 第二,三 部分, 真的真的对我理解操作系统有很大的帮助. (当然, 如果你不看第一部 ...
 - CSAPP读书随笔之一:为什么汇编器会将call指令中的引用的初始值设置为-4
		
CSAPP,即<深入理解计算机系统:程序员视角>第三版,是一本好书,但读起来确需要具备相当的基本功.而且,有的表述(中译文)还不太直白. 比如,第463页提到,(对于32位系统)为什么汇编 ...
 - 深入理解计算机中的 csapp.h和csapp.c
		
csapp.h其实就是一堆头文件的打包,在http://csapp.cs.cmu.edu/public/code.html 这里可以下载.这是<深入理解计算机系统>配套网站. 在头文件的# ...
 - CSAPP(前言)
		
很久之前就听过有过CSAPP这本书的传闻了,今天终于决定上手这本神作:既然是神作,就要仔细拜读一下,今天看了一下前言部分还真的令人耳目一新,单单是前言部分就让我学习到几个新的知识点: 1.c和Java ...
 - CSAPP缓冲区溢出攻击实验(上)
		
CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...
 - 读完了csapp(中文名:深入理解计算机系统)
		
上个星期最终把csapp看完了. 我买的是中文版的,由于除了貌似评价不错以外,由于涉及到些自己不了解的底层东西,怕是看英文会云里雾里.如今看来,大概不能算是个长处,可是的确可以加快我的看书速度,否则一 ...
 - CSAPP Lab2: Binary Bomb
		
著名的CSAPP实验:二进制炸弹 就是通过gdb和反汇编猜测程序意图,共有6关和一个隐藏关卡 只有输入正确的字符串才能过关,否则会程序会bomb终止运行 隐藏关卡需要输入特定字符串方会开启 实验材料下 ...
 
随机推荐
- Java中的成员内部类
			
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.java * 作者:常轩 * 微信公众号:Worldh ...
 - C++走向远洋——53(项目一1、分数类的重载、加减乘除、比较)
			
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
 - 如何用Postman做接口自动化测试
			
目录 前言 什么是自动化测试 自动测试测试分类 为什么需要自动化测试 Postman自动化测试演示 1.新建集合 2.新建接口 3.填写自动化测试脚本 4.录入所有接口 5.执行自动化测试 前言 什么 ...
 - JAVA 中的反射(reflact)
			
获取反射加载类(获取类的字节码)的3种方式: Class class1=Class.forName("lession_svc.lession_svc.reflact.Person" ...
 - 从头认识js-js的发展历史
			
JavaScript简介 JavaScript诞生于1995年,当时,它的主要目的是处理以前有服务端语言(如Perl)负责的一些输入验证操作. JavaScript简史 1995年2月当时就职于Net ...
 - redis01
			
1.redis 1)cookie与session session本质上也是cookie,cookie携带session返回给服务端 redis是一个存储数据库 redis读写快速,使用简单,常用于存储 ...
 - .Net 特性分析与妙用
			
一.特性是什么 1.想象很多小伙伴们都看过在一个类上方.或者在控制器见过类似的东东,加上之后就可以标识这个类或者方法就具备了某些特点 ,那我们就进入它的内心一探究竟吧. 2.我们进入某个特性之后,可以 ...
 - Ubuntu 系统下如何安装pip3工具
			
一.[导读]Ubuntu 系统内置了 Python2 和 Python3 两个版本的开发环境,却没有内置相应的 pip3 管理工具,本文将介绍如何在Ubuntu下如何快速安装 pip3 工具,并升级到 ...
 - python装饰器之函数作用域
			
1.函数作用域LEGB L:local函数内部作用域 E:enclosing函数内部与内嵌函数之间 G:global全局作用域 B:build-in内置作用域 passline = 60 def fu ...
 - ApplicationContextInitializer的理解和使用
			
一.ApplicationContextInitializer 介绍 1.1 作用 ApplicationContextInitializer 接口用于在 Spring 容器刷新之前执行的一个回调函数 ...