首页 > 代码库 > CSAPP 六个重要实验 lab2

CSAPP 六个重要实验 lab2

CSAPP  &&  lab2



哈哈~ 不愧是“美国进口的六级炸弹”!爽歪歪的“升级打怪”


我把实验材料都上传到下面这个link了,0分下载(良心啊~)

http://download.csdn.net/detail/u011368821/7892649


再一个实验指导说明供大家下载:

http://download.csdn.net/detail/u011368821/7892677



对于Phase_1的分析:



0000000000400ef0 <phase_1>:
  400ef0:	48 83 ec 08          	sub    $0x8,%rsp
  400ef4:	be 18 1b 40 00       	mov    $0x401b18,%esi
  400ef9:	e8 10 04 00 00       	callq  40130e <strings_not_equal>
  400efe:	85 c0                	test   %eax,%eax
  400f00:	74 05                	je     400f07 <phase_1+0x17>
  400f02:	e8 dc 07 00 00       	callq  4016e3 <explode_bomb>
  400f07:	48 83 c4 08          	add    $0x8,%rsp
  400f0b:	c3                   	retq  


注意到这句指令.

  400ef4:be 18 1b 40 00      mov    $0x401b18,%esi


ESI/EDI 分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中

就是要培养的对寄存器很敏感的能力.上面mov $0x401b18,%esi之后立马callq string_not_equal.这是在bomb爆炸之前.我们看看string_not_equal 里面能找到什么线索


000000000040130e <strings_not_equal>:
  40130e:	41 54                	push   %r12
  401310:	55                   	push   %rbp
  401311:	53                   	push   %rbx
  401312:	48 89 fb             	mov    %rdi,%rbx
  401315:	48 89 f5             	mov    %rsi,%rbp
  401318:	e8 d4 ff ff ff       	callq  4012f1 <string_length>
  40131d:	41 89 c4             	mov    %eax,%r12d
  401320:	48 89 ef             	mov    %rbp,%rdi
  401323:	e8 c9 ff ff ff       	callq  4012f1 <string_length>
  401328:	ba 01 00 00 00       	mov    $0x1,%edx
  40132d:	41 39 c4             	cmp    %eax,%r12d
  401330:	75 3e                	jne    401370 <strings_not_equal+0x62>

  ...  ...

  401369:	eb 05                	jmp    401370 <strings_not_equal+0x62>
  40136b:	ba 01 00 00 00       	mov    $0x1,%edx
  401370:	89 d0                	mov    %edx,%eax
  401372:	5b                   	pop    %rbx
  401373:	5d                   	pop    %rbp
  401374:	41 5c                	pop    %r12
  401376:	c3                   	retq   


我们可以看到这里有连个string_length. 注意到之前的%rdi 和%rsi 分别被mov到%rbx和%rbp中

%rdi记录的是第一个参数的地址,于是当第一次调用直接第一个参数(指针)指向的字符串,

经过

mov %rsi %rbp 

mov %rbp %rdi

这样第二次传入string_length的参数就变成了string_not_equal的第二个参数(指针),

string_length 对这两个不同指针指向的字符串进行计算,返回它们的长度值,如果不一致,返回1,如果一致返回0(关于返回值的情况这里的汇编不足以解释,还要分析所有的string_not_equal反汇编才会知道)

phase_1中

 callq 40130e <strings_not_equal>
 test %eax,%eax

string_not_equal结束后立即test %eax %eax(text 指令的作用是对寄存器& bit and)

je 如果上一个test指令的结果是0就跳转,否者不跳转

这里如果返回值是0就跳转到了

add $0x8,%rsp
retq

正确返回弹栈了。

上面唧唧歪歪说了这么一对铺垫就一个目的,推理出

  400ef4:be 18 1b 40 00       mov    $0x401b18,%esi

涉及的这个0x401b18是不寻常的,它指向一个字符串,而我们输入的字符串必须和这个指针指向的字符串完全相同才能不触发bomb否者触发BOMB

那就看看0x401b18这里究竟都藏了什么!

gdb debug去


Science isn‘t about why, it‘s about why not?

输入0x401b18  指向的字符串即可过了phase 1  : -)





对于Phase_2的分析:



main函数部分截选

  400e30:	e8 bb 00 00 00       	callq  400ef0 <phase_1>
  400e35:	e8 f2 09 00 00       	callq  40182c <phase_defused>
  400e3a:	bf 08 1a 40 00       	mov    $0x401a08,%edi
  400e3f:	e8 ac fc ff ff       	callq  400af0 <puts@plt>
  400e44:	e8 fe 08 00 00       	callq  401747 <read_line>
  400e49:	48 89 c7             	mov    %rax,%rdi
  400e4c:	e8 bb 00 00 00       	callq  400f0c <phase_2>
我们可以看到搞定了phase_1这里又要进入pahse_2鸟~
这里又有个指令

mov $0x401a08,%edi

 0x401a08这个地址装着是一个普通的提示字符串不必在意(测试过了)



看看pahse_2

0000000000400f0c <phase_2>:
  400f0c:	55                   	push   %rbp
  400f0d:	53                   	push   %rbx
  400f0e:	48 83 ec 28          	sub    $0x28,%rsp
  400f12:	48 89 e6             	mov    %rsp,%rsi
  400f15:	e8 eb 07 00 00       	callq  401705 <read_six_numbers>
  400f1a:	83 3c 24 01          	cmpl   $0x1,(%rsp)
  400f1e:	74 25                	je     400f45 <phase_2+0x39>
  400f20:	e8 be 07 00 00       	callq  4016e3 <explode_bomb>
  400f25:	eb 1e                	jmp    400f45 <phase_2+0x39>
  400f27:	83 c3 01             	add    $0x1,%ebx
  400f2a:	89 d8                	mov    %ebx,%eax
  400f2c:	0f af 45 fc          	imul   -0x4(%rbp),%eax
  400f30:	39 45 00             	cmp    %eax,0x0(%rbp)
  400f33:	74 05                	je     400f3a <phase_2+0x2e>
  400f35:	e8 a9 07 00 00       	callq  4016e3 <explode_bomb>
  400f3a:	48 83 c5 04          	add    $0x4,%rbp
  400f3e:	83 fb 06             	cmp    $0x6,%ebx
  400f41:	75 e4                	jne    400f27 <phase_2+0x1b>
  400f43:	eb 0c                	jmp    400f51 <phase_2+0x45>
  400f45:	48 8d 6c 24 04       	lea    0x4(%rsp),%rbp
  400f4a:	bb 01 00 00 00       	mov    $0x1,%ebx
  400f4f:	eb d6                	jmp    400f27 <phase_2+0x1b>
  400f51:	48 83 c4 28          	add    $0x28,%rsp
  400f55:	5b                   	pop    %rbx
  400f56:	5d                   	pop    %rbp
  400f57:	c3                   	retq   


核心语句

imul -0x4(%rbp),%eax
cmp %eax,0x0(%rbp)  //如果比较结果是0,就跳转,否则BOMB
je 400f3a <phase_2+0x2e>
callq 4016e3 <explode_bomb>

既然如此,那就看看前面什么东东影响%eax 和%rbp的取值


callq 401705 <read_six_numbers>

cmpl $0x1,(%rsp)

je 400f45 <phase_2+0x39>
callq 4016e3 <explode_bomb>

这里很明显,读入的6个数字被存放在从rsp指向的地址开始向上的位置。

先比较第一个输入的数(%rsp)和1是否相等,如果是则跳转到400f45标记的位置,否者callq explode_bomb,爆炸

那么可以确定,第一个输入的数字必须是1,接着我们跳转到 400f45 <phase_2+0x39>的位置看看会发生什么


400f45:	48 8d 6c 24 04       	lea    0x4(%rsp),%rbp
  400f4a:	bb 01 00 00 00       	mov    $0x1,%ebx
  400f4f:	eb d6                	jmp    400f27 <phase_2+0x1b>
这里lea把rsp寄存器指向的指针+4,然后赋值给rbp,并把%edx寄存器初始化为1

最后跳转到400f27的位置


400f27:	83 c3 01             	add    $0x1,%ebx
  400f2a:	89 d8                	mov    %ebx,%eax
  400f2c:	0f af 45 fc          	imul   -0x4(%rbp),%eax
  400f30:	39 45 00             	cmp    %eax,0x0(%rbp)
  400f33:	74 05                	je     400f3a <phase_2+0x2e>
  400f35:	e8 a9 07 00 00       	callq  4016e3 <explode_bomb>
  400f3a:	48 83 c5 04          	add    $0x4,%rbp
  400f3e:	83 fb 06             	cmp    $0x6,%ebx
  400f41:	75 e4                	jne    400f27 <phase_2+0x1b>
此时add 把ebx 增 1,然后赋值给%eax,即数值2.

把-0x4(%rbp)即第一个输入的数字,imul 乘以%eax的值,然后赋值给%eax,即 %eax = 1*2

cmp把此时的%eax 和当前输入0x0(%rbp),此时为第二个输入数字,比较。如果相同就跳转到400f3a的位置,否者callq explode_bomb爆炸. 由此我们可以知道,第二个输入的数字必须是2.


如果第二个数字输入的是2,接着add 把%rbp +4, 接着cmp 比较%ebx(此时为2)和0x6比较,不相等就跳转到400f27,

于是我们又回到了400f27的位置,有点汇编经验的人一看就可以发现,这里其实是一个循环. %ebx每次+1, 循环6次。

  400f2c:	0f af 45 fc          	imul   -0x4(%rbp),%eax
  400f30:	39 45 00             	cmp    %eax,0x0(%rbp)
每次都把%eax和前一个输入数字相乘,赋值给%eax,并和当前数字0x0(%rbp)比较。


这样一步步按照汇编语句构造的循环,执行下去,可以发现要想不bomb,输入应该是

1 2 6 24 120 720



OK~ 搞定,phase_2。






对于Phase_3的分析:

当我们搞定phase_2之后,phase_3来了~

400e4c:	e8 bb 00 00 00       	callq  400f0c <phase_2>
  400e51:	e8 d6 09 00 00       	callq  40182c <phase_defused>
  400e56:	bf 67 19 40 00       	mov    $0x401967,%edi
  400e5b:	e8 90 fc ff ff       	callq  400af0 <puts@plt>
  400e60:	e8 e2 08 00 00       	callq  401747 <read_line>
  400e65:	48 89 c7             	mov    %rax,%rdi
  400e68:	e8 eb 00 00 00       	callq  400f58 <phase_3>
  400e6d:	e8 ba 09 00 00       	callq  40182c <phase_defused>



phase_3:

0000000000400f58 <phase_3>:
  400f58:	48 83 ec 18          	sub    $0x18,%rsp
  400f5c:	4c 8d 44 24 08       	lea    0x8(%rsp),%r8                //把%rsp指向的地址+0x8 赋值给%rcx ,以下的lea操作同理
  400f61:	48 8d 4c 24 07       	lea    0x7(%rsp),%rcx
  400f66:	48 8d 54 24 0c       	lea    0xc(%rsp),%rdx
  400f6b:	be 6e 1b 40 00       	mov    $0x401b6e,%esi  //把0x401b6赋值给%esi ,注意esi是字符串相关寄存器,我们看看这个地址里面是什么
  400f70:	b8 00 00 00 00       	mov    $0x0,%eax
  400f75:	e8 86 fc ff ff       	callq  400c00 <__isoc99_sscanf@plt>
  400f7a:	83 f8 02             	cmp    $0x2,%eax
  400f7d:	7f 05                	jg     400f84 <phase_3+0x2c>
  400f7f:	e8 5f 07 00 00       	callq  4016e3 <explode_bomb>
  400f84:	83 7c 24 0c 07       	cmpl   $0x7,0xc(%rsp)      //比较0xc(%rsp)处的值和7比较,如果大于7,ja跳转,接着bomb,于是我们知道0xc(%rsp)处的值要在(0~7)
  400f89:	0f 87 fc 00 00 00    	ja     40108b <phase_3+0x133>
  400f8f:	8b 44 24 0c          	mov    0xc(%rsp),%eax
  400f93:	ff 24 c5 80 1b 40 00 	jmpq   *0x401b80(,%rax,8)
  400f9a:	b8 6a 00 00 00       	mov    $0x6a,%eax                       //把0x6a赋值给%eax,这里很重要,每一个witch分支的这里都不一样,而且第二个输入参数和这个有关系
  400f9f:	81 7c 24 08 40 02 00 	cmpl   $0x240,0x8(%rsp)           //把0x8(%rsp)的值和0x240比较,如果不相等,bomb,相等就正常跳转到 401095
  400fa6:	00 
  400fa7:	0f 84 e8 00 00 00    	je     401095 <phase_3+0x13d>
  400fad:	e8 31 07 00 00       	callq  4016e3 <explode_bomb>
  400fb2:	b8 6a 00 00 00       	mov    $0x6a,%eax
  400fb7:	e9 d9 00 00 00       	jmpq   401095 <phase_3+0x13d>
  400fbc:	b8 66 00 00 00       	mov    $0x66,%eax
  400fc1:	81 7c 24 08 bc 03 00 	cmpl   $0x3bc,0x8(%rsp)
  400fc8:	00 
  400fc9:	0f 84 c6 00 00 00    	je     401095 <phase_3+0x13d>
  400fcf:	e8 0f 07 00 00       	callq  4016e3 <explode_bomb>
  400fd4:	b8 66 00 00 00       	mov    $0x66,%eax
  400fd9:	e9 b7 00 00 00       	jmpq   401095 <phase_3+0x13d>
  400fde:	b8 6a 00 00 00       	mov    $0x6a,%eax
  400fe3:	81 7c 24 08 2a 02 00 	cmpl   $0x22a,0x8(%rsp)
  400fea:	00 
  400feb:	0f 84 a4 00 00 00    	je     401095 <phase_3+0x13d>
  400ff1:	e8 ed 06 00 00       	callq  4016e3 <explode_bomb>
  400ff6:	b8 6a 00 00 00       	mov    $0x6a,%eax
  400ffb:	e9 95 00 00 00       	jmpq   401095 <phase_3+0x13d>
  401000:	b8 76 00 00 00       	mov    $0x76,%eax
  401005:	81 7c 24 08 c9 00 00 	cmpl   $0xc9,0x8(%rsp)
  40100c:	00 
  40100d:	0f 84 82 00 00 00    	je     401095 <phase_3+0x13d>
  401013:	e8 cb 06 00 00       	callq  4016e3 <explode_bomb>
  401018:	b8 76 00 00 00       	mov    $0x76,%eax
  40101d:	eb 76                	jmp    401095 <phase_3+0x13d>
  40101f:	b8 62 00 00 00       	mov    $0x62,%eax
  401024:	81 7c 24 08 07 01 00 	cmpl   $0x107,0x8(%rsp)
  40102b:	00 
  40102c:	74 67                	je     401095 <phase_3+0x13d>
  40102e:	e8 b0 06 00 00       	callq  4016e3 <explode_bomb>
  401033:	b8 62 00 00 00       	mov    $0x62,%eax
  401038:	eb 5b                	jmp    401095 <phase_3+0x13d>
  40103a:	b8 69 00 00 00       	mov    $0x69,%eax
  40103f:	81 7c 24 08 3b 03 00 	cmpl   $0x33b,0x8(%rsp)
  401046:	00 
  401047:	74 4c                	je     401095 <phase_3+0x13d>
  401049:	e8 95 06 00 00       	callq  4016e3 <explode_bomb>
  40104e:	b8 69 00 00 00       	mov    $0x69,%eax
  401053:	eb 40                	jmp    401095 <phase_3+0x13d>
  401055:	b8 71 00 00 00       	mov    $0x71,%eax
  40105a:	81 7c 24 08 c6 00 00 	cmpl   $0xc6,0x8(%rsp)
  401061:	00 
  401062:	74 31                	je     401095 <phase_3+0x13d>
  401064:	e8 7a 06 00 00       	callq  4016e3 <explode_bomb>
  401069:	b8 71 00 00 00       	mov    $0x71,%eax
  40106e:	eb 25                	jmp    401095 <phase_3+0x13d>
  401070:	b8 77 00 00 00       	mov    $0x77,%eax
  401075:	81 7c 24 08 74 01 00 	cmpl   $0x174,0x8(%rsp)
  40107c:	00 
  40107d:	74 16                	je     401095 <phase_3+0x13d>
  40107f:	e8 5f 06 00 00       	callq  4016e3 <explode_bomb>
  401084:	b8 77 00 00 00       	mov    $0x77,%eax
  401089:	eb 0a                	jmp    401095 <phase_3+0x13d>
  40108b:	e8 53 06 00 00       	callq  4016e3 <explode_bomb>
  401090:	b8 68 00 00 00       	mov    $0x68,%eax
  401095:	3a 44 24 07          	cmp    0x7(%rsp),%al               //把0x7(%rsp)和 %al(%eax低字节)比较,相等就跳转,否者,bomb
  401099:	74 05                	je     4010a0 <phase_3+0x148>
  40109b:	e8 43 06 00 00       	callq  4016e3 <explode_bomb>
  4010a0:	48 83 c4 18          	add    $0x18,%rsp
  4010a4:	c3                   	retq   


注意到开头这里

mov $0x401b6e,%esi

把0x401b6赋值给%esi ,注意esi是字符串相关寄存器,我们看看这个地址里面是什么


我们发现是一个格式化输入说明字符串

于是我们就知道我们应该输入什么类型的数据了

400f75: callq 400c00 <__isoc99_sscanf@plt>
400f7a: cmp $0x2,%eax
400f7d: jg 400f84 <phase_3+0x2c>
400f7f:  callq 4016e3 <explode_bomb>
400f84: cmpl $0x7,0xc(%rsp)

可以发现,sscanf的返回值放在%eax里,如果输入的数据大于2个(即最少是3个),就跳转到400f84,否则explode_bomb

根据前面的格式化字符串我们可以注意到

输入三个数据即正常跳转


这里又有个跳转语句

  400f93:	ff 24 c5 80 1b 40 00 	jmpq   *0x401b80(,%rax,8)
  400f9a:	b8 6a 00 00 00       	mov    $0x6a,%eax

我们看看 *0x401b80处是什么东东


是一个数,0x400f9a,这个是指令mov $0x6a,%eax 的代码段标记地址

如果%rax是0,就直接跳转到0x400f9a 否则0x400f9a + %rax * 8

这里是典型的witch 语句的汇编形式...如果不明白就去看CSAPP第三章


上面给出的phase_3汇编部分注释我已经写的很清楚了~

  400f5c:	4c 8d 44 24 08       	lea    0x8(%rsp),%r8                //把%rsp指向的地址+0x8 赋值给%rcx ,以下的lea操作同理
  400f61:	48 8d 4c 24 07       	lea    0x7(%rsp),%rcx
  400f66:	48 8d 54 24 0c       	lea    0xc(%rsp),%rdx
这里可以推知phase_3一开始就保存了0x8(%rsp),0x7(%rsp),0xc(%rsp)三处的值,这三处肯定要被接下来的程序重写利用.

而分析偏移量0x8 0x7 0xc,以及格式化字符串参数入栈顺序可知,0xc(%rsp)储存第一个参数,0x7(%rsp)储存第二个参数,0x8(%rsp)储存第三个参数.

提示: printf("%d %d",a,b); 参数是b先入栈,然后是a

综合以上分析,输入

0 j 576

即可过关

这里我偷一下懒第一个选择了0

实际上第一个数据可以是0~7内的任意数字,这也会导致跳转至不同的分支,而影响第二个第三个参数的输入情况。

以0 作为第一个输入参数的例子,

  400f9a:	b8 6a 00 00 00       	mov    $0x6a,%eax     

  401095:	3a 44 24 07          	cmp    0x7(%rsp),%al    
以上两个指令将被执行,我们可以知道0x7(%rsp)第二个输入的参数应当为0x6a对应的ascii码字符,于是这里应当输入 j

第三个参数的确定是在

  400f9f:	81 7c 24 08 40 02 00 	cmpl   $0x240,0x8(%rsp)           //把0x8(%rsp)的值和0x240比较,如果不相等,bomb,相等就正常跳转到 401095
  400fa6:	00 
  400fa7:	0f 84 e8 00 00 00    	je     401095 <phase_3+0x13d>
于是第三个参数必须为0x240,否则bomb,这里是%d的读入,于是转化为相应的十进制数为576.



OK, Phase_3 搞定 halfway there!


对于Phase_4的分析:


注意到phase_4会调用到func4

00000000004010a5 <func4>:
  4010a5:	53                   	push   %rbx
  4010a6:	89 fb                	mov    %edi,%ebx
  4010a8:	b8 01 00 00 00       	mov    $0x1,%eax
  4010ad:	83 ff 01             	cmp    $0x1,%edi
  4010b0:	7e 0b                	jle    4010bd <func4+0x18>
  4010b2:	8d 7f ff             	lea    -0x1(%rdi),%edi
  4010b5:	e8 eb ff ff ff       	callq  4010a5 <func4>
  4010ba:	0f af c3             	imul   %ebx,%eax
  4010bd:	5b                   	pop    %rbx
  4010be:	c3                   	retq   

00000000004010bf <phase_4>:
  4010bf:	48 83 ec 18          	sub    $0x18,%rsp
  4010c3:	48 8d 54 24 0c       	lea    0xc(%rsp),%rdx
  4010c8:	be 74 1b 40 00       	mov    $0x401b74,%esi
  4010cd:	b8 00 00 00 00       	mov    $0x0,%eax
  4010d2:	e8 29 fb ff ff       	callq  400c00 <__isoc99_sscanf@plt>
  4010d7:	83 f8 01             	cmp    $0x1,%eax
  4010da:	75 07                	jne    4010e3 <phase_4+0x24>
  4010dc:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp)
  4010e1:	7f 05                	jg     4010e8 <phase_4+0x29>
  4010e3:	e8 fb 05 00 00       	callq  4016e3 <explode_bomb>
  4010e8:	8b 7c 24 0c          	mov    0xc(%rsp),%edi
  4010ec:	e8 b4 ff ff ff       	callq  4010a5 <func4>
  4010f1:	3d 00 5f 37 00       	cmp    $0x375f00,%eax
  4010f6:	74 05                	je     4010fd <phase_4+0x3e>
  4010f8:	e8 e6 05 00 00       	callq  4016e3 <explode_bomb>
  4010fd:	48 83 c4 18          	add    $0x18,%rsp
  401101:	c3                   	retq   

进过前面三个炸弹的“轰炸”,这里我不想在过细致的分析,就是一步步跟着汇编看就是了

主题就是phase_4要求根据格式化字符串“%d”输入一个数字,这个数字传入func做递归乘法,相当于传入参数的阶乘.

最后

  4010f1:	3d 00 5f 37 00       	cmp    $0x375f00,%eax
返回值和0x375f00比较,如果不相等就bomb,于是我们必须找到阶乘等于0x375f00的数字.

的方法嘛.写个阶乘的C 函数去测试,什么输入参数的阶乘是0x375f00


#include <stdio.h>

int main()
{
	int ans = 1;
	int tmp = 1;

	for(tmp = 1;ans != 0x375f00;tmp++)
	{
		ans *= tmp;
	}

	printf("%d \n",tmp-1);

	return 0;
}

呵呵,原来是10.


 





对于Phase_5的分析:



0000000000401102 <phase_5>:
  401102:	53                   	push   %rbx
  401103:	48 89 fb             	mov    %rdi,%rbx
  401106:	e8 e6 01 00 00       	callq  4012f1 <string_length>
  40110b:	83 f8 06             	cmp    $0x6,%eax     //输入字符串的长度必须是6,否则bomb
  40110e:	74 05                	je     401115 <phase_5+0x13>
  401110:	e8 ce 05 00 00       	callq  4016e3 <explode_bomb>
  401115:	b8 00 00 00 00       	mov    $0x0,%eax // 把%eax %edx 寄存器赋值为0
  40111a:	ba 00 00 00 00       	mov    $0x0,%edx
  40111f:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx //%rbx + %rax*1 赋值给%ecx
  401123:	83 e1 0f             	and    $0xf,%ecx    //取%ecx低4位赋值给%ecx
  401126:	03 14 8d c0 1b 40 00 	add    0x401bc0(,%rcx,4),%edx
  40112d:	48 83 c0 01          	add    $0x1,%rax
  401131:	48 83 f8 06          	cmp    $0x6,%rax
  401135:	75 e8                	jne    40111f <phase_5+0x1d>
  401137:	83 fa 3e             	cmp    $0x3e,%edx
  40113a:	74 05                	je     401141 <phase_5+0x3f>
  40113c:	e8 a2 05 00 00       	callq  4016e3 <explode_bomb>
  401141:	5b                   	pop    %rbx
  401142:	c3                   	retq   


值得注意的是

  401126:	03 14 8d c0 1b 40 00 	add    0x401bc0(,%rcx,4),%edx
这里又有个很特殊的地址0x401bc0

我尝试打印这里的数据,怀疑这里很可能是个数组


对于phase_5,概括性的说,就是输入6个ascii字符,然后这6个字符的低4位对应这个数组的index,然后对应数字累加要等于0x3e,即62

这里我的想法是62 = 2+2+10+16+16+16

对应的偏移量是001555 

我们查看ascii码表可以发现,恰巧数字字符00155符合要求,于是输入00155







对于Phase_6的分析:


最后一关了!

0000000000401143 <fun6>:
  401143:	48 89 f8             	mov    %rdi,%rax
  401146:	4c 8b 47 08          	mov    0x8(%rdi),%r8
  40114a:	48 c7 47 08 00 00 00 	movq   $0x0,0x8(%rdi)
  401151:	00 
  401152:	4d 85 c0             	test   %r8,%r8
  401155:	75 48                	jne    40119f <fun6+0x5c>
  401157:	f3 c3                	repz retq 
  401159:	48 89 d1             	mov    %rdx,%rcx
  40115c:	48 8b 51 08          	mov    0x8(%rcx),%rdx
  401160:	48 85 d2             	test   %rdx,%rdx
  401163:	74 09                	je     40116e <fun6+0x2b>
  401165:	39 32                	cmp    %esi,(%rdx)
  401167:	7f f0                	jg     401159 <fun6+0x16>
  401169:	48 89 d6             	mov    %rdx,%rsi
  40116c:	eb 03                	jmp    401171 <fun6+0x2e>
  40116e:	48 89 d6             	mov    %rdx,%rsi
  401171:	48 39 ce             	cmp    %rcx,%rsi
  401174:	74 06                	je     40117c <fun6+0x39>
  401176:	4c 89 41 08          	mov    %r8,0x8(%rcx)
  40117a:	eb 13                	jmp    40118f <fun6+0x4c>
  40117c:	4c 89 c0             	mov    %r8,%rax
  40117f:	eb 0e                	jmp    40118f <fun6+0x4c>
  401181:	48 89 c2             	mov    %rax,%rdx
  401184:	4c 89 c0             	mov    %r8,%rax
  401187:	eb 06                	jmp    40118f <fun6+0x4c>
  401189:	48 89 c2             	mov    %rax,%rdx
  40118c:	4c 89 c0             	mov    %r8,%rax
  40118f:	49 8b 48 08          	mov    0x8(%r8),%rcx
  401193:	49 89 50 08          	mov    %rdx,0x8(%r8)
  401197:	48 85 c9             	test   %rcx,%rcx
  40119a:	74 14                	je     4011b0 <fun6+0x6d>
  40119c:	49 89 c8             	mov    %rcx,%r8
  40119f:	48 85 c0             	test   %rax,%rax
  4011a2:	74 dd                	je     401181 <fun6+0x3e>
  4011a4:	41 8b 30             	mov    (%r8),%esi
  4011a7:	39 30                	cmp    %esi,(%rax)
  4011a9:	7e de                	jle    401189 <fun6+0x46>
  4011ab:	48 89 c1             	mov    %rax,%rcx
  4011ae:	eb ac                	jmp    40115c <fun6+0x19>
  4011b0:	f3 c3                	repz retq 

00000000004011b2 <phase_6>:
  4011b2:	48 83 ec 08          	sub    $0x8,%rsp
  4011b6:	ba 0a 00 00 00       	mov    $0xa,%edx
  4011bb:	be 00 00 00 00       	mov    $0x0,%esi
  4011c0:	e8 1b fa ff ff       	callq  400be0 <strtol@plt>
  4011c5:	89 05 55 21 20 00    	mov    %eax,0x202155(%rip)        # 603320 <node0>
  4011cb:	bf 20 33 60 00       	mov    $0x603320,%edi
  4011d0:	e8 6e ff ff ff       	callq  401143 <fun6>
  4011d5:	48 8b 40 08          	mov    0x8(%rax),%rax
  4011d9:	8b 0d 41 21 20 00    	mov    0x202141(%rip),%ecx        # 603320 <node0>
  4011df:	39 08                	cmp    %ecx,(%rax)
  4011e1:	74 05                	je     4011e8 <phase_6+0x36>
  4011e3:	e8 fb 04 00 00       	callq  4016e3 <explode_bomb>
  4011e8:	48 83 c4 08          	add    $0x8,%rsp
  4011ec:	c3                   	retq   

这步不要陷入到func6了,逐步的去gdb stepi nexti 调试就是了. 具体的调试方法不讲了

值得一提的就是这里

  4011c5:	89 05 55 21 20 00    	mov    %eax,0x202155(%rip)        # 603320 <node0>
 
  4011d9:	8b 0d 41 21 20 00    	mov    0x202141(%rip),%ecx        # 603320 <node0>
这里0x202155(%rip) 0x202141(%rip)都是指向同一个地址,这个地址储存着输入数据

cmp    %ecx,(%rax)
最后这里比较的时候,直接gdb查看%rax指向的地址存的什么东东,

打印出来


826!于是我们就应该输入826





其实应该还有个彩蛋——secrete phase

我目前~没心思看了,过两天继续更新

*****************************************************************************************************************************

参考资料——向所有前辈致敬, sharing,step together! open source!


逆向工程——二进制炸弹(CSAPP Project) 

http://www.cnblogs.com/remlostime/archive/2011/05/21/2052708.html


<csapp> bomb lab (《深入理解计算机系统》lab2)Stone

http://blog.csdn.net/u013648407/article/details/24845129


CSAPP:二进制炸弹实验    lycos的六度空间

http://blog.csdn.net/caoxu1987728/article/details/6056947


最后感谢


呵呵,国内的某些大学学着点别人的风度.

***************************************************************************************************************************




CSAPP 六个重要实验 lab2