ROP



ROP的全称为Return-oriented programming(返回导向式编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防御(NX,ASLR)。
ROP是一种攻击技术,其中攻击者使用堆栈的控制来在现有程序代码中的子程序中的返回指令之前,立即间接地执行精心挑选的指令或机器指令组。
因为所有执行的指令来自原始程序内的可执行存储器区域,所以这避免了直接代码注入的麻烦,并绕过了用来阻止来自用户控制的存储器的指令的执行的大多数安全措施。
因此,ROP技术是可以用来绕过现有的程序内部内存的保护机制的。

原理

ROP技术的原理google上的相关资源非常多,就不再赘述了,新手可以从蒸米大神在wooyun上的文章一步一步ROP开始学起,打好基础,笔者就是从这个系列文章入坑的
一步一步学ROP之linux_x86篇 – 蒸米
一步一步学ROP之linux_x64篇 – 蒸米
一步一步学ROP之gadgets和2free篇 – 蒸米
此外还有一些相关的利用技术,常见的Ret2libc,Ret2vuln等等,都可以在网络上找到相关教程,这里不在赘述

例题

接下来是几个简单的CTF的题目,用来练手rop是不错的选择
一般来说,如果题目是动态编译的,我们一般选择最基本的ret2libc,如果题目是静态编译的,我们选择execve(“/bin/sh”)
因为静态编译的文件中不一定会有能够直接利用的system函数,需要利用陷入,syscall来getshell

DEFCON CTF Quals 2015: r0pbaby

IDA分析函数发现:

savedregs 在ebp,我们直接可以绕过所有的保护,写ebp,根据题目提示,也应该是一个简单的ROP
首先,输入1 给出libc.so.6的基地址(我他妈真不知道这个libc是那个,这个给出的libc基地址不知所云)

输入2,给出函数的地址,这个是正确的
输入3 ,写入ebp

所以自然我们就return to libc
难点在于找”‘/bin/sh”的地址和pop rdi ,ret这个Godget
由于我不知道1给出的libc是哪个libc,通过符号偏移去查libc版本也失败了,所以我只能通过gdb调试来确定搜索内存确定这些位置相对libc_base的偏移

确定了之后就可以愉快的ret2libc啦

AliCTF_2016 vss

这是一个典型的静态文件Rop,利用execve(“/bin/sh”)来getshell

首先ida找到main部分

由于没有file符号表,所以在IDA中函数都是地址表示,很不直观,经过简单分析,代码解析如上,main中通过syscall 0 号调用即read读取1024个字节到main的栈上,之后在sub_40108E中发生溢出

在该函数中,sub_400330((__int64)&v2, a1, 80LL)拷贝到v2 ebp-0x40处的位置造成栈溢出,但是需要注意有两个地方
第一个是我们是在main函数中read了1024个字节(Payload)到栈中,在sub_40108E发生栈溢出时,仅仅拷贝了Payload 的前80个字节到栈中,所以我们payload时需要stack pivot绕过这段payload
二是在上述代码中,我们需要让payload前两个字节为’p’‘y’来绕过这段代码,我并不知道它是做什么用的,但是通过调试发现,他会让我们的栈溢出利用失败,所以payload填入’py’将之绕过

我们通过Ropgadets可以构造一个大概大概的Ropchain如图所示:

我没有用这个ropchain,不过思路是一致的,首先将”/bin/sh”写入bss段中,然后令rdi=bss地址,rsi=rdx=0(不是NULL会syscall会失败,刚开始没有注意,失败后发现的),rax=59(execve的系统调用号),之后syscall即可

plaidctf-2013 ropasaurusrex

Rop裸题,考察ret2libc
首先定位溢出点:

可以溢出24个字节,因为也是个32bit的程序足够我们做rop了,程序还给出了libc,所以思路如下:
write(1,got_read,0x8)打印出read的地址->ret2vuln->system(“/bin/sh”)
通过read的地址计算libc偏移在libc中找到system的地址与”/bin/sh”的地址,ret2libc

总结

Rop技术是目前最基本的漏洞利用技术
技术本身并不困难,但是想要使用地灵活,高效,巧妙需要大量的实践
在目前的CTF比赛中,ROP并不会单独考察,它会与其他的利用技术结合,所以打好ROP的基础是未来学习的关键

发表评论