ROP简介
面向返回编程(英语:Return-Oriented Programming,缩写:ROP)是计算机安全漏洞利用技术,该技术允许攻击者在安全防御(主要为NX, 堆栈不可执行保护)的情况下执行代码,如不可执行的内存和代码签名。攻击者控制堆栈调用以劫持程序控制流并执行针对性的机器语言指令序列(称为Gadgets)。 每一段gadget通常结束于return指令,并位于共享库代码中的子程序。
若程序满足可以控制返回地址和可以找到符合要求的gadgets以及gadgets地址,就进行ROP。我们选择的gadgets大多是pop register;ret;
或者mov register xx;ret;
之类的(我遇到的大多数情况是这样的,错了请到了打脸)对寄存器赋值。
- 以下例子都默认开启了栈不可执行保护
静态链接
原理
有的程序编译时候使用的是静态链接,所以库里所有函数的plt就有了。
例子
hackme的ROP
ret2text
原理
通过程序已有的代码构造ROP链。
例子
ctf-wilki的ret2text,程序中就存在system("/bin/sh")
,我们可以利用system("/bin/sh")
进行getshell。
1 | void secure() |
再看看IDA中main函数的伪代码。
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
gets函数没有限制输入长度,是一个典型的堆栈溢出。我们利用gdb的插件peda的功能,pattc和patts就可以计算出填充数据的大小112。而system("/bin/sh")
的地址是)0x8048648。最后祭上神器pwntools。
1 | from pwn import * |
ret2shellcode
原理
若程序栈不可执行,但我们可以控制其他可执行的段,如bss段(存储全局变量),那么我们就可以将shellcode写入其中,再控制程序返回地址跳转到这里执行shellcode。
例子
以ctf-wiki的ret2shellcode为例。
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
与前面的ret2text相似,但这里已经没有system("/bin/sh")
,取而代之的是strncpy。虽然strncpy不存在栈溢出漏洞,但这里的buf2是在bss段上,我们能将shellcode复制到bss段里,再控制程序跳转到bss段执行shellcode。
1 | #-*-coding:utf-8-*- |
ret2syscall
原理
syscall即系统调用,通过调用号调用系统函数。