<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/binary/16700

            0x00 寫在前面


            [email protected] 發表關于《來pwn我一下好嗎》的write up已經過去一段時間了,這篇write up對于我這樣的Linux漏洞攻防新手來說很多地方都是很難理解的,后來結合這篇write up,我又調試了一下這個pwn me的題目,發現無論是從error出的題目,還是z神寫的write up,都特別精彩,有很多值得學習的地方。

            這個漏洞writeup從各個角度看,涵蓋了很多Linux下的攻防技巧,于是我把我分析思考的過程,進行了一個總結,拿出來跟大家一起分享,或者說,我把這個漏洞撥繭抽絲,提取一些最有意思的部分,來和大家一起享受這個精彩的pwn me之旅。

            在開頭的最后,必須再次感謝一下出題人 Error 以及 writeup的作者 Explorer,真的學習到了很多東西。

            這篇文章需要結合z神的writeup來看,傳送門在此http://drops.wooyun.org/binary/16257

            文中若有不到位或者描述有誤之處,請大牛們批評指正,多多交流,也希望能對大家有所幫助!(抱拳!)

            0x01 思考與問題


            在閱讀這篇writeup的時候產生了很多疑問,其實主要還是對于Linux下堆管理機制,以及一些Linux攻防技巧不熟的原因導致的,其實漏洞并不難處理,關鍵在于如何大開腦洞來利用,下面我拋出我在做這個pwn me調試時產生的問題,并且通過動態調試的過程來解決這些疑問。

            這三個問題其實都只是引子,在動態調試的過程中,發現了很多有趣的地方。在開始調試前,我想再啰嗦一下為什么會產生這三個問題。

            首先第一個問題,fastbin這種malloc機制比較好理解,單向鏈表,也就是說只有一個指向下一個chunk的指針,但是如何利用這個指針達到任意地址寫的呢?

            第二個問題,從z神的writeup利用中提到了兩種leak方法,那么它們的工作機制是怎樣的呢?

            第三個問題,writeup中提到的通過改寫free hook達到執行/bin/sh的目的,那么這個過程又是什么樣的呢?

            下面帶著這三個問題,開始最精彩的旅行~

            0x02 關于z神提到的幾個坑


            在writeup中z神提到了幾個坑,其中一個是check函數的,作者error后來也在文末提到了,兩種方法,一種是利用任意地址寫來修改全局變量a000的大小,另一種是直接無視掉,因為確實有時候會出現check函數檢測沒有通過的情況。

            另外一個坑是關于FULL RELRO保護,其實通過gdb-peda可以直接查看保護開啟情況。

            這個保護主要是針對got表,這個got表存放著很多函數指針,針對got表攻防的概念有點像Windows下虛函數的攻擊,關于got表的攻擊有一篇文章講的挺好的,傳送門在此http://drops.wooyun.org/binary/6521

            這里不再贅述,主要是z神在這個pwn題目中利用方法也很有意思。

            0x03 從leak addr到任意地址寫


            說到leak addr就要從fastbin chunk說起,fastbin chunk是Linux下堆的一種分配方式,比較簡單,采用的是單向鏈表的方式,只有一個fd指針指向下一個未分配的chunk,利用這種方法,可以泄露出堆的地址,這和后面的任意地址寫有很重要的關系。

            對于fastbin chunk,網上的說明有很多了,其實簡化版的圖是這樣的。

            在這個pwn題目中,對Vul結構的構造,rank恰好處于fd指針的位置,那么接下來在delete函數中調用free的時候,這個rank的位置會泄露堆地址,這是fastbin chunk的機制。

            在這個漏洞中,要分別malloc申請兩個fastbin chunk,然后對這兩個chunk進行free操作,首先來看一下申請過程。

            在6040a0地址位置是rank存放的位置,也就是fd的位置,下面要關注這個地址,其他chunk的申請過程我不再展示了,直接來看看free chunk之后構成fastbin chunk鏈表的過程。

            下面對這個chunk執行free操作。

            這里要提的一點是兩個free,在pwn題目中,一個free是對detail指針的free,另一處是free整個memory,觀察地址00604110位置,其實這里就是之前vul結構中detail指針malloc地址的位置,這里作為006040a0之前的chunk釋放,而detail指針位置恰好是fd的位置,因此這里指向了00604070,也就是下一個未使用chunk的地址。

            接下來觀察eip處于memory free的函數調用處,接下來單步步過,觀察006040a0地址。

            可以看到,這時006040a0位置已經泄露了堆地址,而這個位置正好之前提到的rank的地址,而在writeup中已經提到了,在rank賦值時有一處if語句判斷,如果rank大于0則賦值,因此,只要控制rank小于等于0,則不會賦值,通過這種方法,再通過程序的show函數,就可以通過rank打印出堆地址。

            那么其實這個過程,就是在二進制漏洞攻防中,常用于bypass ASLR的利用方式,而上述的這個調試情景,就是一個最簡單的過程

            那么接下來,又是如何達到任意地址寫的過程的呢?這就要提到pwn題目中edit函數存在的use after free釋放后重利用,這個其實是uaf中一個非常簡單的情況,在chunk釋放后,沒有對其進行標記,從而導致在釋放后仍然能對該chunk進行操作,通過這種方式,可以修改fd的值,這就是一個典型的fake chunk的利用場景了,這樣如果再次malloc,可以講地址跳到任意地址,從而達到任意地址寫的目的。

            關于fake chunk,freebuf上有一篇不錯的文章,傳送門在此http://www.freebuf.com/news/88660.html

            接下來我們來看一下這個uaf漏洞是如何通過uaf漏洞造成fake chunk的,這里我要說一下,在調試的過程中,虛擬機很不給力的掛了兩次,導致調試時堆地址發生了改變,但整個過程和描述是不變的。(忘了用快照的悲劇。。。)

            首先是free之后在edit中可以對rank進行賦值,而此時實際上rank所處的chunk已經被釋放了。

            可以看到,盡管該chunk已經被釋放,但是title標記仍然存在,也就是說,在memcmp的過程中仍然可以匹配到title的值,從而可以繼續接下來的賦值,就是這樣的過程,令我門可以控制rank的位置,而之前也提到這里可以創造fake chunk,接下來重新申請。

            這里地址改變的原因之前已經提到,在這里的fake chunk地址是我隨便輸入的,證明fake chunk在fastbin chunk申請過程中對chunk地址的影響。

            0x04 fast bin與normal bin中的leak libc


            在開頭的三個問題中,我提到了一個泄露libc基址的問題,其實在上面一個小節中,已經提到了泄露堆基址的方法,以及任意內存讀寫的方法,那么其實在z神的writeup中,提到了leak libc的兩種方法,第一種是他在文中提到的泄露libc基址的方法,在我調試的過程中,確實發現了在chunk內某個偏移位置存在一個libc的地址,那么利用任意地址讀的方法就可以找到這個libc的地址,以此計算出libc的基址。

            其實這里我想說的是z神提到的另一種方法normal bin,normal bin和fast bin差別比較大,首先,normal bin chunk采用的是雙向鏈表,在后面動態調試中可以看到,而在normal bin雙向鏈表表頭地址是在libc中,當時我的疑問也是在于,釋放chunk后會產生libc的指針到底是怎么一回事

            帶著這個疑問來調試這個原理,位置仍然是在add函數中,首先對vul結構第一個malloc位置沒法控制,但是對于detail指針卻是可以控制的,通過控制detail長度,我們就可以讓fastbin chunk變成normalbin chunk,我們申請一個大小為4000的chunk,這時候,linux就會采用normal bin的機制。

            我們需要申請兩個chunk,在釋放時構成雙向鏈表,在第一個chunk釋放的時候,chunk空間并沒有什么變化。

            接下來對第二個chunk進行釋放,首先到達free的位置前,來觀察一下chunk空間的情況。

            單步步過,在此觀察chunk中的情況。

            可以看到,此時位于libc中的鏈表頭部指針已經暴露出來了,可以再通過任意地址讀取的方法獲得到這libc中的地址,之后可以計算出libc的基址地址。

            0x05 覆蓋free執行system


            在got表被保護的情況下,通過任意地址寫的方法,可以修改關鍵地址,從而達到執行代碼的目的,剛開始一直對z神 write up中關于最后執行的地方百思不得其解,后來通過調試終于發現這到底是怎么回事了。

            其實在前面的小節我已經提到過,在free的時候,會先free detail指針,而detail指針在創建的時候是可控的,于是按照z神的說法,在detail指針寫入/bin/sh,這樣在free detail的時候,如果通過任意地址寫覆蓋掉free,將system函數的地址覆蓋上,這樣free detail就會變成system detail,于是最后delete函數關鍵位置變成執行:system(/bin/sh)

            這樣就可以在目標端口拿到shell了(好像比shellcode還方便,但真實攻防中很難)

            0x06 二進制學習的一些心得


            到這里,所有疑問都基本上解決了,感覺學到了很多東西,我接觸二進制的時間比較短,還在努力摸索,這里想分享一些小心得,希望大家能多多指點。

            最后感謝三個白帽,ca叔邀請我到三個白帽做這個pwn題的時候還是看到我離大牛們還是有不少的差距,今后還是希望自己能夠多受點挫折,多進步一點!

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线