加深PLT-GOT表機制的理解


加深PLT-GOT表機制的理解

之前的一篇講libc的文章中講過有關plt-got表的延遲綁定機制,而覆蓋got表的方法也早已稱為pwn中最常用的技巧之一;但是筆者近期閑來無事對改機制進行了更詳細的逆向分析,有了一個更加清晰的圖景,借此文分享一下:

分析就得事必躬親,自行找一個有libc調用的程序,32位64位皆可,丟進IDA里面去看PLT表,快捷點的方法就是找個call <libc_func>雙擊函數名一跟,比如我們下面這個例子:

TIM截圖20181112163637

我們隨便找個函數看看,就選exit吧:

TIM截圖20181112164049

可以看到:PLT表中,exit表項其實是一條jmp指令,這可能和我們的習慣理解有出入,我們習慣思維里面一般感覺表都應該是存一些數據(如地址),但是實際上這里是一個jmp跳板。那么jmp跳到哪呢?就是cs:exit_ptr,最近學了計組才明白這是一個寄存器變址尋址,cs代表一個獨立的小代碼段(code segment)。

cs段:

往往是由單位指令長(32位/64位)整數倍的地址開始,以一系列align對齊偽命令結尾,可能是為了方便尋址吧,具體作用之后有機會再聊,現在只需要了解這兩個特點就好。

在PLT表中,每個jmp跳板其實都是一個cs段,想看的自行看IDA。

我們現在來看一下plt中jmp跳板項的HEX,以exit為例:

TIM截圖20181112165458

其中,FF 25代表的就是jmp指令,讀者不妨自行看看其他plt表項,每個plt表項的頭兩個字節都是FF 25;后面的5A 08 20 00是小端序的一個地址偏移,我們剛剛說了此處是寄存器變址尋址,我們現在不妨來看exit的got表:

TIM截圖20181112165831

可以看到got表地址的小端序是:E0 0F 20 00,與上面的5A 08 20 00的確不同(寄存器變址尋址),我們做個差,算得結果為:0x786,我們到exit的plt項再看,雙擊jmp cs:exit_ptr中的cs這個詞:

TIM截圖20181112170518

我們看到,cs段的End address正是0x786,這就是通過偏移計算出got表地址的過程(這里還是一個間址尋址)

好,現在我們去看got表在初始的時候(未綁定的時候)是個什么樣子:

TIM截圖20181112191051

未綁定時,got表的值就是0x201050,這個地址處的東西就是上面的extrn,可見:

在延遲綁定機制下,第一次調用某個libc函數時(未綁定時),就會執行到上圖的位置,進行extrn將libc中相應函數的真實地址擴展進來,擴展的過程實現了將got表項改寫為函數的真實RVA,這個過程就叫做“綁定”!

綁定以后,第二次、第三次再調用這個函數的時候,jmp到的就不是0x201050了,而是jmp到函數的真實地址了!

有關漏洞挖掘:

1.我們篡改的都是got表,而從未聽說過篡改plt表這種操作,現在了解了plt表項的實質是一個指令后就明白了,代碼段根本就不可寫。

2.可供篡改的字節有限時:考慮延遲綁定狀態!假如說我們只能獲得有限字節數的任意寫內存的機會,我們又想要覆蓋got表,在某些情形下可能就需要覆蓋某些函數的地址高位被隨機化的字節,而不是全部字節,目的就是實現當下次調用受害函數時劫持到目標地址,在這種情況下,我們需要考慮在我們進行改寫時函數的綁定狀態,因為綁定和未綁定時got表中的那個地址值是不一樣的,而我們並不是篡改每一個字節!

謝謝閱讀!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM