1. dl_runtime_resolve
1.1 函數流程
作用:對動態鏈接的函數進行重定位,延遲綁定機制中調用。
_dl_runtime_resolve(link_map_obj, reloc_index) 的兩個參數分別是link_map 指針和 got 表中關於 plt 重定位的索引值。主要流程是遍歷所有的link_map,往下取出當前 link_map 的符號表 ELF Symbol Table和字符串表ELF String Table,據此找到對應的符號/函數名。最後往got表寫入查找到的函數地址。具體步驟如下:
(1)link_map 訪問 .dynamic,取出 .dynstr、.dynsym、.rel.plt的地址。
(2)當前函數的重定位表項指針 rel = .rel.plt + reloc_index。
(3)當前函數的符號表項指針 sym = .dynsym [(rel->r_info) >>8]。
(4)符號名位置 = .dynstr + sym->stname。
(5)在動態鏈接庫中依據符號名查找函數地址,寫回 *rel->r_offset(got表)。
(6)調用該函數。
1.2 利用場景
無法泄露地址、plt/got/可寫空間/符號表等已知的情況下可使用,實際上就像是修改了got的索引,尋址可控。
reloc_index 可控的情況下,.dynstr 也變得可控。
2. 題目:undlcv
2.1 程式分析
x86–64架構,只開了NX和Canary保護,沒有給出libc。
運行時發現程式完全無輸出,可能是關閉了標準輸出文件。
程式主邏輯如下:
add 函數進行了堆塊的申請,沒有限制個數,每個 id 對應的 chunk 被 delete過后才能重新 add 回來。delete 函數沒有 uaf 漏洞。
漏洞點是 edit 函數中的 off by null。而且無論輸入什麽,都會發生 off by null:
2.2 漏洞利用
目前沒有找到標準輸入輸出文件相關的函數,不能進行重定向。也就是無法確定程式沒有輸出的原因和解決方法。如果只是標準輸出文件被重定向過,也許可以再重定向回來,但這裏明顯不是。
沒有輸出意味著不能泄露,IO_FILE攻擊也沒有用。
程式的 RELRO 保護沒開,能修改got表。這裏可以利用 dl_runtime_resolve函數依據符號表查找函數地址的過程,無需泄露就能將free_got改成system函數地址。
先找到原本字符串表string table的位置:0x4032a0
利用unlink,在chunk_list空間(可寫區域)寫入fake dynstr:
同時把chunklist[0]的位置覆蓋成原本字符串表的位置。這樣再次edit 0時,能直接改表裏的内容,覆蓋成前面fake dynstr的地址就可以。
最後往free_got中寫入free_plt。之後再free一個寫了“/bin/sh\x00”的chunk的時候,使用的就是system函數的地址。