您的位置:首页 > 移动开发

CSAPP: Bomb Lab(3)

2016-06-18 23:53 841 查看

Bomb 5

0000000000401062 <phase_5>:
401062: 53                      push   %rbx
401063: 48 83 ec 20             sub    $0x20,%rsp
401067: 48 89 fb                mov    %rdi,%rbx   //将输入的字符串放在rbx中
40106a: 64 48 8b 04 25 28 00    mov    %fs:0x28,%rax

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      //string lengh must 6
401082: 74 4e                   je     4010d2 <phase_5+0x70>
401084: e8 b1 03 00 00          callq  40143a <explode_bomb>


根据
40107a,40107f
处代码可以得到,输入的字符串的长度为6。

根据下面代码中
<strings_not_equal>
函数,可以知道我们最后经过处理,字符串需要与
内存$0x40245e处的字符串
比较是否相等,运用
p/s (char*)$0x40245e
,获得该比较字符串为flyers。

401089: eb 47                   jmp    4010d2 <phase_5+0x70>
40108b: 0f b6 0c 03             movzbl (%rbx,%rax,1),%ecx //将输入字符串的第一个字符给ecx
40108f: 88 0c 24                mov    %cl,(%rsp)
401092: 48 8b 14 24             mov    (%rsp),%rdx
401096: 83 e2 0f                and    $0xf,%edx     //取字符的最低4位到edx,大小从0~15
401099: 0f b6 92 b0 24 40 00    movzbl 0x4024b0(%rdx),%edx   //根据rdx中的数字,从0x4024b0(%rdx)中取字符
//maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?

4010a0: 88 54 04 10             mov    %dl,0x10(%rsp,%rax,1) //存储取出的字符
4010a4: 48 83 c0 01             add    $0x1,%rax  //处理次数+1
4010a8: 48 83 f8 06             cmp    $0x6,%rax  //判断处理次数是否到6次
4010ac: 75 dd                   jne    40108b <phase_5+0x29>
4010ae: c6 44 24 16 00          movb   $0x0,0x16(%rsp)   //为新创建的字符串添加结尾符“/0”
4010b3: be 5e 24 40 00          mov    $0x40245e,%esi  // flyers
4010b8: 48 8d 7c 24 10          lea    0x10(%rsp),%rdi //比较新创建的字符串与flyers是否相等
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>
......
其他结束代码


然后在分析以上代码。可以看出大致是一个while循环,
while(处理次数< 6)
。根据上面代码块的注释,我们可以理解这个函数主要功能是根据我们输入的6位字符串,以这字符串的每个字符的后4位(0000 ~ 1111,0 ~ 15 ) 为索引,从内存
0x4024b0(%rdx)
中取出新的字符组成新6位字符串。然后比较新创建的字符串与
flyers
是否相等。
内存$0x4024b0
处的字符串数组获取命令行如下:

(gdb) p/s (char*)0x4024b0

$5 = 0x4024b0 <array> "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"


根据这个字符串,可以得到f(9),l(15),y(14),e(5),r(6),s(7)

所以只要我们输入的字符串的字符ASCII的第二位(16进制)符合这个要求就可以了。

其中一个答案为:

ionefg(0x49,0x4f,0x4E,0x45,0x46,0x47)


Bomb 6

对phase_6()函数反汇编。下面是代码的开头,可以通过注释得到,我们输入的6位数字,且都小于6

4010f4: 41 56                   push   %r14
4010f6: 41 55                   push   %r13
4010f8: 41 54                   push   %r12
4010fa: 55                      push   %rbp
4010fb: 53                      push   %rbx  //被调用者负责寄存器

4010fc: 48 83 ec 50             sub    $0x50,%rsp
401100: 49 89 e5                mov    %rsp,%r13
401103: 48 89 e6                mov    %rsp,%rsi
401106: e8 51 03 00 00          callq  40145c <read_six_numbers>  //==>读入6个数字
40110b: 49 89 e6                mov    %rsp,%r14
=====init
40110e: 41 bc 00 00 00 00       mov    $0x0,%r12d
401114: 4c 89 ed                mov    %r13,%rbp
401117: 41 8b 45 00             mov    0x0(%r13),%eax

40111b: 83 e8 01                sub    $0x1,%eax
40111e: 83 f8 05                cmp    $0x5,%eax                 //==>所有数字小于6
401121: 76 05                   jbe    401128 <phase_6+0x34>
401123: e8 12 03 00 00          callq  40143a <explode_bomb>


接下去的代码是一个while循环,r12d和ebx是一个循环计数器。该循环用于判断这6个数是否存在等于0的。可以推测得到每个数字都不为0.

401128:    41 83 c4 01             add    $0x1,%r12d     //r12d计数
40112c:    41 83 fc 06             cmp    $0x6,%r12d     //计数小于6
401130: 74 21                   je     401153 <phase_6+0x5f>

401132: 44 89 e3                mov    %r12d,%ebx
401135: 48 63 c3                movslq %ebx,%rax

401138: 8b 04 84                mov    (%rsp,%rax,4),%eax
40113b: 39 45 00                cmp    %eax,0x0(%rbp) //==>判断每个数字都不等于 0
40113e: 75 05                   jne    401145 <phase_6+0x51>
401140: e8 f5 02 00 00          callq  40143a <explode_bomb>
401145: 83 c3 01                add    $0x1,%ebx
401148: 83 fb 05                cmp    $0x5,%ebx
40114b: 7e e8                   jle     401135 <phase_6+0x41>


接下去的代码是用来对输入的数字进行修改,input[i] = 7 - input[i]。

401153: 48 8d 74 24 18          lea    0x18(%rsp),%rsi
401158: 4c 89 f0                mov    %r14,%rax
40115b: b9 07 00 00 00          mov    $0x7,%ecx
401160: 89 ca                   mov    %ecx,%edx
401162: 2b 10                   sub    (%rax),%edx
401164: 89 10                   mov    %edx,(%rax)   //input[i] = 7 - input[i]
401166: 48 83 c0 04             add    $0x4,%rax     //下一个元素,相当于i++
40116a: 48 39 f0                cmp    %rsi,%rax     //是否越界
40116d: 75 f1                   jne    401160 <phase_6+0x6c>


下面的代码是讲
内存$6032d0
位置处的内容,按照我们输入的数字的标号在指定位置排序(如5 4 3,则
内存$6032d0
第5个元素处的元素排在第1个,第4个排在第2个,第3个排在第3个)。

40116f: be 00 00 00 00          mov    $0x0,%esi
401174: eb 21                   jmp    401197 <phase_6+0xa3>

401176: 48 8b 52 08             mov    0x8(%rdx),%rdx //到40117f 。为了找到第ecx个node
40117a: 83 c0 01                add    $0x1,%eax
40117d: 39 c8                   cmp    %ecx,%eax
40117f: 75 f5                   jne    401176 <phase_6+0x82>

401181: eb 05                   jmp    401188 <phase_6+0x94>
401183: ba d0 32 60 00          mov    $0x6032d0,%edx
401188: 48 89 54 74 20          mov    %rdx,0x20(%rsp,%rsi,2) //将相应Node放入指定位置
40118d: 48 83 c6 04             add    $0x4,%rsi    //input数组下一个元素
401191: 48 83 fe 18             cmp    $0x18,%rsi   //检查是否越界(input数组)
401195: 74 14                   je     4011ab <phase_6+0xb7>

401197: 8b 0c 34                mov    (%rsp,%rsi,1),%ecx       //a[rsi/4]
40119a: 83 f9 01                cmp    $0x1,%ecx     //if  a[i]<= 1
40119d: 7e e4                   jle    401183 <phase_6+0x8f>

40119f: b8 01 00 00 00          mov    $0x1,%eax
4011a4: ba d0 32 60 00          mov    $0x6032d0,%edx
4011a9: eb cb                   jmp    401176 <phase_6+0x82>


对于$0x6032d0处的内容,我们要仔细看一下。运用
x *0x6032d0
,可以看到显示是一个node。

通过不断的查看可以看到该node的内容如下图:



下面代码段用来将node之间建立链表连接指针

4011ab: 48 8b 5c 24 20          mov    0x20(%rsp),%rbx
4011b0: 48 8d 44 24 28          lea    0x28(%rsp),%rax
4011b5: 48 8d 74 24 50          lea    0x50(%rsp),%rsi
4011ba: 48 89 d9                mov    %rbx,%rcx
4011bd: 48 8b 10                mov    (%rax),%rdx
4011c0: 48 89 51 08             mov    %rdx,0x8(%rcx) //将下一个NOde的地址赋值给前一个
4011c4: 48 83 c0 08             add    $0x8,%rax
4011c8: 48 39 f0                cmp    %rsi,%rax
4011cb: 74 05                   je     4011d2 <phase_6+0xde>
4011cd: 48 89 d1                mov    %rdx,%rcx
4011d0: eb eb                   jmp    4011bd <phase_6+0xc9>
4011d2: 48 c7 42 08 00 00 00    movq   $0x0,0x8(%rdx) //最后的指针值为NULL


下面代码用来判断该链表是否递增,如果递减,则不爆,否则爆炸。

4011da: bd 05 00 00 00          mov    $0x5,%ebp  //计步
4011df: 48 8b 43 08             mov    0x8(%rbx),%rax
4011e3: 8b 00                   mov    (%rax),%eax
4011e5: 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),%rbx
4011f2: 83 ed 01                sub    $0x1,%ebp
4011f5: 75 e8                   jne    4011df <phase_6+0xeb>


所以根据上面所有的分析得到,我们输入的数字串,是为链表排序的,输入的编号数字的位置,决定了相应编号节点的位置。

所以我们输入的应该使得链表递减的顺序。

根据之前查看的链表内容

$61 = {332, 1, 6304480, 0, 168, 2, 6304496, 0, 924, 3, 6304512, 0,

691, 4, 6304528, 0, 477, 5, 6304544, 0, 443, 6, 0, 0}

应该是924>692>477>443>332>168 ==>3 4 5 6 1 2

由因为之前知道input[i] = 7-input[i];

所以最初输入应该为 4 3 2 1 6 5

经过验证为正确答案。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: