<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/16257

            0x00 前言


            三個白帽終于出了一個pwn的挑戰。總算是能讓我這種不會web的菜雞拿幾個貓幣了。而且這一道題目出的很有心意,后面利用過程一環扣一環,質量很高。

            現在就來分享一些詳細的利用思路。

            附上原文件:vms.zip

            0x01 代碼分析


            做pwn題的第一步就是要分析代碼,尋找漏洞。這次的程序代碼流程不是很長,總共的函數數量也只有十幾個,所以在分析代碼方面不存在很多的問題。

            結構體

            這個是經過分析還原出來的Vulnerability結構體。也是程序中儲存數據的主要結構。當然最重要的就是結構體里有一個指針。一旦覆蓋可以用來任意讀寫

            00000000 Vulnerability   struc ; (sizeof=0x60, mappedto_1)
            00000000 rank            dq ?
            00000008 titleSize       dq ?
            00000010 detailLen       dq ?
            00000018 title           db 64 dup(?)
            00000058 detail          dq ?                    ; offset
            00000060 Vulnerability   ends
            

            存在漏洞的

            程序存在2個主要的漏洞 第一個是在edit修改Vulnerability結構的時候沒有校驗in_use位。所以存在即使內存已經被釋放,卻仍然能夠修改內存的情況。也就是所謂的use after free漏洞

            image1

            稍微分析一下,很容易就可以發現這一出的uaf漏洞

            第二處漏洞就相對比較隱晦了。在add添加Vulnerability和edit修改Vulnerability結構的時候,如果輸入的rank位負數,則程序會選擇跳過而不是給rank字段賦值。我們可以利用這一點來leak堆上的信息。因為這是整個程序唯一一處不會破壞堆上原先數據的的的地方。Vulnerability結構的其他字段都會強制的修改內存中的數據,無法用來泄露信息

            image2

            出題人挖的坑

            出題人在整個題目里挖了3個大坑等著人來跳。要想拿到shell,需要一個一個的繞過。

            1.所有堆指針加密

            無論是存在.bss段的Vulnerability的指針還是Vulnerability結構中指向detail的指針,都是用一個隨機數亦或之后再存放的。所以無法直接通過uaf來修改指針實現任意地址讀寫。

            所以我們必須要先想辦法搞到亦或用的隨機數,否則無法完成利用。

            2.堆指針的check函數

            在程序通過指針讀寫detail內存之前都會有一個check函數來校驗堆指針的有效性,如果校驗錯誤就會直接退出程序

            image3

            好在這個check并沒有這個嚴格。一般來說只要保證Vulnerability的指針小于等于detail的指針的時候,有很大概率通過check。實際的測試下來,整個攻擊一般在20次嘗試以內就能成功

            3.FULL RELRO保護

            通過checksec就可以發現,程序開啟了FULL RELRO,這意味著我們無法修改got表。即使通過uaf實現的任意讀寫,也無法控制eip。內存里也沒有明顯的函數指針能夠被覆蓋。

            這里我通過覆蓋free_hook來實現最后的調用system。這里是相關的代碼。可以發現free函數可以通過hook來使他調用我們自定義的函數。只要我們修改__free_hook的值為system函數的地址,就可以拿到shell

            2926    __libc_free (void *mem)
            2927    {
            2928      mstate ar_ptr;
            2929      mchunkptr p;                          /* chunk corresponding to mem */
            2930    
            2931      void (*hook) (void *, const void *)
            2932        = atomic_forced_read (__free_hook);
            2933      if (__builtin_expect (hook != NULL, 0))
            2934        {
            2935          (*hook)(mem, RETURN_ADDRESS (0));
            2936          return;
            2937        }
            ...
            2962    }
            2963    libc_hidden_def (__libc_free)
            

            0x02 詳細利用流程


            詳細的利用代碼我和我分析代碼時的idb在這里
            利用第一步就是要leak出用于亦或的隨機數。需要用一些猥瑣的思路來構建堆結構。

            1.獲得堆地址

            首先,我們需要知道堆塊的具體地址。這個我們可以leak堆管理中的鏈表指針來實現。Vulnerability結構的rank字段正好是存放鏈表指針的位置。正如前面所說的,只要我們在add的時候不寫入rank的值就能夠通過rank來leak堆的地址。

            2.利用fastbin漏洞控制malloc內存地址

            我們知道fastbin的單向鏈表鏈接的。而通過uaf,我們的rank字段正好可以覆蓋這個單項鏈表指針。從而控制下一次malloc時候的地址。而且我們已經知道了堆的地址。所以我們就能控制malloc。使得新分配的Vulnerability結構的rank字段于另外一個Vulnerability的detail指針重合。這樣我們就能夠實現對detail字段的leak和修改了。而且結合剛才獲得的堆地址。我們也可以反向算出用于亦或的隨機數的數值。

            image4

            到此,我們實現了任意地址的讀寫

            3.泄露libc基地址

            這個比較簡單。因為normal bin是通過雙向鏈表來管理的。而雙向鏈表的頭是存放在libc里的。所以只要在堆上隨意的釋放一塊大的內存就能產生一個指向libc的指針。在我利用過程中。正好在堆上有這樣一個指針,直接leak出來然后推算出libc基地址。

            image5

            4.寫入free_hook

            用ida查看一下libc就能找到libc中free_hook的地址

            image6

            最后的實際的地址是0x3C0A10。把算好的system函數的地址寫入進去就可以了。最后找一塊內存寫入/bin/sh然后拿去free就可以完成整個利用的過程了

            image6

            一血留念

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

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

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

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

                      亚洲欧美在线