延遲繫結與retdlresolve

CH13hh發表於2024-04-24

延遲繫結與retdlresolve

我們以前在ret2libc的時候,我們洩露的libc地址是透過延遲繫結實現的,我們知道,在呼叫libc裡面的函式時候,它會先透過plt表和gor表繫結到,函式真實地址上,那麼在第二次呼叫的時候就可以用了,不用再次繫結

那麼它是怎麼樣實現的呢,我們還是透過一個題目一步步去看一下除錯過程,我們這裡看一下write函式

我們斷點下到call write,可以看見首先jmp到write的plt表裡面push了一個0x20,然後繼續jmp,我們把這個push的0x20叫做reloc_arg,也是dl_runtime_resolve的第一個引數

繼續步入,我們可以看見又push了一個東西,叫做link_map是dl_runtime_resolve的第二個引數

看一下它裡面存的值

這裡面的第三個就是.dynamic的地址,那麼就可以透過link_map找到.dynamic的地址,而.dynamic裡面存的有.dynstr,.dynsym和.rel.plt的地址,它們分別在.dynamic+0x44 .dynamic+0x4c .dynamic+0x84的位置我們來看一下

那麼.rel.plt真實的地址就是.rel.plt +reloc_arg,叫做ELF32.Rel的指標,叫rel,我們在ida裡面也可以發現確實是這樣

接下來我們可以透過剛剛的rel找到r_offest(got表)和r_info

我們在ida裡面驗證一下r_offest是不是got表

是沒有問題的,那麼r_info有什麼用呢,我們把r_info >> 8得到的一個數也就是6,它是剛剛.dynsym裡面的下標,我們來看一下,透過這個下標我們得到函式名的偏移

我們剛剛得到的下標是6,那麼函式名偏移就是0x4c,我們再加上.dynstr,就可以找到函式名所在地址

ida裡面也是這樣

那麼就找到對應的函式名了(st_name),在動態連結庫裡面找這個函式的地址,賦值給 *rel->r_offset,也就是 GOT 表就完成了一次函式的動態連結,那麼繫結就完成了,而ret2dlresolve就是透過在這之間偽造來進行getshellde

在32位NO RELRO情況下我們可以直接修改.dynamic,這裡我們可以用工具來gethsell,exp在這裡


這裡使用pwntools裡面的rop模組建立了一個rop物件,rop.raw()可以往rop鏈裡面填充資料,rop.read(),可以呼叫read函式,rop.chain()可以傳送完整的shellcode我們把.dynamic的地址改成我們bss段上的假地址,然後再呼叫read的第二條plt指令觸發dl_runtime_resolve,然後在特定位置給上引數/bin/sh

對於32位Partial RELRO的型別pwntools仍然給我們的強大的工具構造payload

但是最好還是弄清楚原理在使用工具,善於利用工具可以少走很多彎路,但是有利有弊,好處就是可以快速的做出題,並且能節省下很多時
間;壞處也顯而易見,就是隻知道這樣可以做出來,但是為什麼這樣做出來的完全不懂。可以在CTFwiki上面找到具體的手工構造payload的方法[https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/ret2dlresolve]

相關文章