一道简单的ROP,引申出的多种解法-Alkaid

首先这道题目是2017 Redhat广东省信息安全竞赛的签到pwn,在使用大佬的快速搭建pwn题框架里发现了一道pwn,这篇文章主要为了提醒自己,以后做题的时候要拓宽思路。。。。

 

下面是题目下载地址:

题目下载链接

大佬的github地址:

https://github.com/giantbranch/pwn_deploy_chroot

 

先看下程序开启的保护:

一道简单的ROP,引申出的多种解法-Alkaid

第一种解法:

构造简单ROP解决,这种题一般是以下几步:

  1. 寻找溢出漏洞位置(源程序)
  2. 寻找system函数(源程序,libc)
  3. 寻找/bin/sh位置(源程序,libc)

 

找到scanf这里有溢出漏洞:

一道简单的ROP,引申出的多种解法-Alkaid

 

在函数列表找到了system函数:

一道简单的ROP,引申出的多种解法-Alkaid

 

在源程序里没有/bin/sh字符串,可以利用栈溢出控制eip跳到scanf函数,写入/bin/sh字符串,再重新进入函数,跳转到system函数的位置,利用之前写好的/bin/sh来getshell,利用IDA中的ctrl+s打开区段表,查看下RWX三种属性。显然,如果某一页内存没有可写(W)属性,我们就无法向里面写入代码,如果没有可执行(X)属性,写入到内存页中的shellcode就无法执行。

一道简单的ROP,引申出的多种解法-Alkaid

如上图可以在bss段上写入/bin/sh

利用代码如下所示:

详细过程请看

https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=42530&extra=page%3D1&page=1

 

第二种解法

既然没有/bin/sh,那么有其他的字符串可以代替它帮我们拿到shell呢?

答案是有的,一个sh就可以帮我们getshell,测试如下:

首先写一个程序测试下只用sh能不能进入:

一道简单的ROP,引申出的多种解法-Alkaid

用gcc编译并运行:

一道简单的ROP,引申出的多种解法-Alkaid

结果成功

那么我们现在只需要找到sh这个字符串,直接在程序里搜索:

一道简单的ROP,引申出的多种解法-Alkaid

找到了,其实如果源程序使用了flush这个函数,那么就一定有sh这个字符串

那么现在就很省事了,直接system+4*无用字节+sh地址就可以了,脚本如下所示:

 

第三种解法

既然源程序里没有/bin/sh,那么用libc里的不就完事了,但是程序没有给libc,但这也难不倒我们,只需要泄露当前函数的真实偏移地址的就可以找到对应的libc版本,从而下载到libc,找到libc的/bin/sh所在位置,根据write_addr - system_addr == write_addr_libc - system_addr_libc从而计算出真实位置而利用

 

可以使用的在线查找libc网站

https://libc.blukat.me/