Pwn学习笔记:Rop Primer靶机实战
前言ROP靶机是一个用于训练CTF中的Pwn的平台,该靶机设计在Linux 32位系统中,一共分为3个等级。
ROP全称为Return-oriented Programming(面向返回的编程)是一种新型的基于代码复用技术的攻击,攻击者从已有的库或可执行文件中提取指令片段,构建恶意代码
靶机安装
靶机ROP下载地址:https://pan.baidu.com/s/1rYDOK-EDZDEfEYk2_IfRMg
靶机IP:192.168.238.128(会根据DHCP自动分配)
nmap扫描ip
Level0
通过nmap探测可以看到该靶机开了3个端口,我们访问http看一下
这里给出来了,该等级的c语言代码和一些需要我们关注的信息,比如该等级靶机让我们锻炼ret2libc技术,还给出了一个ssh的账号密码为:level0: warmup ,通过上面的源码可以看到这里有很明显的栈溢出漏洞,下一步我们就登陆该等级ssh,查看调试一下
登陆成功,在目录下面有一个flag文件,我们现在的权限说没办法读取的
下一步我们运行一下该level0,看看是怎么样的
可以看到程序接收用户的输入,如果经常挖漏洞的小伙伴一看就知道这样的方式很有可能是出现溢出漏洞的(假如没有源码的情况下),下面我们来调试一下这个level0看看
通过查看main可以看到比较敏感的函数:gets
下一步使用checksec来检测一下开启了那些防护
如上图可以看到只开启了NX,满足可以使用ret2libc技术,下一步我们来确认偏移地址,我们使用pattern来完成,gdb peda插件已经内置,因为我们有源码所有我就不把偏移指设的那么多
生成完后,我们继续运行一下该程序,在gdb里直接输入 “r” 即可,然后输入生成的值执行
通过上图可以看到程序如我们预想的那样奔溃,EIP变成了 0x41414641
接下来我们通过pattern_offset来判断溢出点为44
下一步我们来确认一下溢出点是否正确
EIP已经被控制
通过上面的调试已经确认该溢出点是正确的,eip也可控,存在栈溢出漏洞,下一步我们使用vmmap查看内存映射,寻找选择可读可写和可执行的内存块
找到两个函数
下一步我们找pop3ret,我们使用 ropgadget 来帮我们完成,pade插件里已经有了
我们找到了一个,是否正确呢,我们去http://ropshell.com 上验证一下,这里就把这个level0 下载到本机然后上传到该站分析
确无误后,下一步我们就来编写这个exp
0xbffdf000 为 堆栈地址
0x21000 为 堆栈的空间地址
最后的 0x666 为发送的shellcode字节,最后我们运行该exp,拿flag
已成功拿到shell和flag
Level1
首先,根据题目提示,以账号level1和密码shodan登录靶机,查看到文件flag和level1相关信息。
level1 为动态链接的32位程序,开启了NX保护
上来直接运行 level 程序,发现一直提示 error bind()ing ,ltrace看一下发现 bind 一直返回 -1,说明地址绑定不成功
查看一下本地的端口和进程信息,发现8888端口一直处于监听状态,且属于level2用户
直接nc过去,猜测该端口上运行着一个属于 level2 用户的 level1 程序
再来看题目本身,通过题目的说明,根据程序源代码找到漏洞点:漏洞产生的原因为对 char filename 执行了以下操作,而变量 filesize 由用户输入,因此会造成溢出
出题者提示通过 level1 二进制文件中的 open/read/write 函数来拿到flag。顺藤摸瓜,这里很自然想到处理流程为
1.计算偏移量,溢出
2.执行open,打开flag文件
3.read读取flag文件内容
4.write将flag写出
试一下能不能拿到flag
main函数下断点
可以在运行后跟踪子进程,看看尝试使用'read'获取flag时会发生什么
调用检查输入中“flag”字符串的出现次数,在检查发生之前没有解析符号链接,因此创建指向该标志的符号链接应该允许我们读取它
这个确实是flag,但是根本就没有用到ROP,主要目的是学习ROP
要用到store,这是操作的相关代码
读取文件名时发生缓冲区溢出。如下所示,分配了32个字节。但是,将读取字节,这是之前提供的文件大小。如果此值大于32,则它将覆盖堆栈上的其他值
我无法使用level1权限调试正在运行的setuid二进制文件,因此我们必须将其复制到本地计算机来分析
gdb`在一个终端中打开并将follow-fork-mode设置为child
然后打开另一个终端并发送一个100字节的文件
子进程崩溃,EIP指向0x41414141
重新生成一些字符串,算一下偏移
需要在覆盖返回地址之前写入64个字符
首先找到 level1 plt 表中的 open/read/write 的地址
然后,找到 level1 中的 flag字符串
最后,收集 level1 中的 gadget,需要一些pop2ret和pop3ret
完成rop准备工作,各变量如下:
编写EXP
运行exp拿到flag
Level2
以 level2 和 tryharder 登录靶机,查看文件信息,level2 为静态链接文件,开了NX保护
查看题目说明,显然 strcpy 操作会导致变量 name 溢出
gdb调试查看溢出偏移为 44 个字节
没有进行任何边界检查,strcpy复制argv到缓冲区就会发生溢出,需要提供多少字节才能覆盖ret地址?
算一下偏移
所以就是45-46-47-48字节会覆盖ret
由于是 strcpy 函数,在拷贝时会以 0x00 字节为结束符。这就提示我们,当我们打入的 payload 中间含有 0x00 字符时,其后的 payload 则不会顺利拷贝,从而导致无法正常执行获取shell
参考level1,我们必须使用mprotect和read系统调用
1.修改数据段权限
2.读入精心构造的shell,
3.跳转到shell处执行。
注意,由于 0x00 的约束,level0直接调用函数的解题方式无法奏效,因此此题采用系统调用(int 0x80)的方式来实现第一步和第二步的操作。根据提示,我们可以通过 ropshell网站 来搜索二进制文件内我们所需的gadget
使用地址0x080ca000来存储shellcode,它是映射二进制文件的地址空间的一部分,可以使用vmmap里面的命令获取此信息
标记内存区域后,我们需要从标准输入中读取shellcode,为了执行,需要按如下方式布置寄存器。
我们需要使用gadget 来执行每个系统调用
上传level2文件到,它提供了一个可搜索的界面,可以根据使用的寄存器或指令类型过滤gadget
sys_mprotect 修改 .data 权限
要执行mprotect(0x080ca000, 128, PROT_READ|PROT_WRITE|PROT_EXEC),因此寄存器需要包含以下值
实现的思想:在栈上放 0xffffffff,而后 ,再通过8次 即可。
网站查询到所需的gadget如下:
实现的payload布局如下:
实现的思想同上即可。所需的gadget信息如下:
实现的payload布局如下:
为实现的操作,上述gadget已完成 0x80ca001 pop -> ebx ,只需再执行一次下面的gadget即可:
跳转到shellcode 执行拿flag,上述两步执行完成后,读取shellcode存储在 0x80ca000 处,即 sys_read 执行完的 ecx 地址处,因此在 payload 的最后,加上如下gadget即可。
执行exp,拿到shell
总结
至此,ROPPwn靶机的三个level已经全部解决,三个题目都是溢出后使用rop技术构造exp,这里ropshell.com这个网站非常好用,方便我们找到ropgadget,这个靶机很适合学习Pwn的新手同学,想学习的同学可以参考学习,里面的坑我基本上都填平了,希望能帮到大家,一起进步。
排版重新整理了一下,原来md的代码粘过来会乱,贴图贴到手酸。
参考信息
https://blog.the-playground.dk/2015/08/rop-primer-v02-level-2.html
https://www.anquanke.com/post/id/168988#h3-2
本文由看雪论坛 hackerbirder 原创
原文链接:[原创][新手向]Pwn学习笔记:Rop Primer靶机实战
支持学逆向论坛,资源不错! 支持学逆向论坛,资源不错!
页:
[1]