<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址: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

                    一血留念

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频