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

CSAPP3e - x86-64 assembly code analysis - Bomb Lab: phase 5

2016-06-06 23:10 441 查看
首先来看phase_5做了什么:

0000000000401062 <phase_5>:
401062: 53 push %rbx
401063: 48 83 ec 20 sub $0x20,%rsp
401067: 48 89 fb mov %rdi,%rbx
40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
401071: 00 00
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
401082: 74 4e je 4010d2 <phase_5+0x70> # length of the string must be 6
401084: e8 b1 03 00 00 callq 40143a <explode_bomb>
401089: eb 47 jmp 4010d2 <phase_5+0x70>

这一段代码将rbx赋值成rdi,也就是我们输入的字符串所存的地址,然后在40106a处,它将rax赋值成一个特殊的量%fs:0x28,查阅资料这是一个sentinel,用于监视栈溢出
接下来rsp+24的位置被赋成这个值,然后eax被按位异或后调用string_length,这个函数后eax必须为6,这说明我们输入的字符是6个

然后短暂跳跃了一下,将eax赋成0:

4010d2: b8 00 00 00 00 mov $0x0,%eax
4010d7: eb b2 jmp 40108b <phase_5+0x29>然后是一个循环:
40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx
40108f:	88 0c 24             	mov    %cl,(%rsp)
401092:	48 8b 14 24          	mov    (%rsp),%rdx
401096:	83 e2 0f             	and    $0xf,%edx
401099:	0f b6 92 b0 24 40 00 	movzbl 0x4024b0(%rdx),%edx
4010a0:	88 54 04 10          	mov    %dl,0x10(%rsp,%rax,1)
4010a4:	48 83 c0 01          	add    $0x1,%rax
4010a8:	48 83 f8 06          	cmp    $0x6,%rax
4010ac:	75 dd                	jne    40108b <phase_5+0x29>
ecx被赋值成rbx+rax所指向的值,注意到movzbl这个命令是在短变量赋给长变量时自动填充0的,然后将ecx的低8位赋给rsp所指向的地址,然后将这个值赋给rdx,然后将edx与0xf作按位合取,然后将rdx+0x4024b0所指向的值赋给edx,然后将这个值的低8位赋值给rsp+rax+16的地址
上述过程由于eax从1到6退出,共进行6次。它做了什么呢?rbx存储着我们输入字符串的存储地址,每次eax贡献一个偏移,也就是说我们的字符串内6个字符每次都赋给rdx,然后和0xf按位合取,也就是只取了最低4位的值,接着这个值作为偏移量取了0x4024b0后的某一个地址上的变量,那个变量的低8位被赋到rsp+rax+16的位置上。

循环结束时,rsp+16 ~ rsp+21 这6个字节上存储着从0x4024b0开始的一段地址内搬运来的6个变量,计算每个地址的偏移量等于我们输入的字符的低4位所代表的数

接下来,

4010ae: c6 44 24 16 00 movb $0x0,0x16(%rsp)
4010b3: be 5e 24 40 00 mov $0x40245e,%esi
4010b8: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi
4010bd: e8 76 02 00 00 callq 401338 <strings_not_equal> # the processed string must be the same as that stored in 0x40245e
4010c2: 85 c0 test %eax,%eax
4010c4: 74 13 je 4010d9 <phase_5+0x77> # eax must be 0
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
rsp+22处被赋成0,标记着这个新串的结束。然后esi被赋成0x40245e,rdi被赋成rsp+16,也就是这个新串的开始地址
然后是strings_not_equal,我们知道它会在rsi和rdi所指向的两个字符串相等时返回0,从4010d9看这正是我们需要的。如果通过这一层,

我们就跳到4010d9,将rax赋成rsp+24所指向的值,这正是那个sentinel,然后rax与sentinel按位异或后比较是否和401078处的结果一致,我们知道正常情况下是的(代入计算的sentinel都是%fs:0x28),这样就能退出了

关键在于那个字符串是什么。我们操作得到的串需要等于0x40245e处的,查看知它是"flyers",

而4024b0处的字符串是:maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?

按照flyers中字母在这个字符串中的位置一个一个找下来,我们需要的偏移量分别是:9 15 14 5 6 7

转换成2进制:1001 1111 1100 0101 0110 0111

查ASCII码表,不难得知很多字符的低4位都能满足需要,我们只需要找一个就行,比如:"9?>567",这样就通过了phase_5
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: