shellcode之五:堆溢出

來源:互聯網
上載者:User

聲明:主要內容來自《The Shellcoder's Handbook》,摘錄重點作為筆記並加上個人的一些理解,如有錯,請務必指出。

幾乎所有的malloc實現都會用中繼資料儲存塊的位置、大小或與小塊有關的特殊資料。dlmalloc用儲存桶儲存這些資料,還有些malloc實現用平衡樹結構儲存它們。這些中繼資料一般儲存在兩個地方:malloc實現自己使用的全域變數;分配給使用者的記憶體塊的前/後位置。

基本堆溢出

絕大多數堆溢出的基本原理如下:堆和棧很相似,既包含了資料資訊,也包含了用來控製程序理解這些資料的維護資訊。我們所要掌握的技巧,就是通過malloc和free來達到這個目的:把一或兩個字寫入我們能控制的記憶體位址。

我們先看一個會產生堆溢出的程式:

//file: basicheap.c#include <stdio.h>int main(int argc, char *argv[]){    char *buf;    char *buf2;    buf = (char *)malloc(1024);    buf2 = (char *)malloc(1024);    printf("buf=%p, buf2=%p/n", buf, buf2);        strcpy(buf, argv[1]);    free(buf2);}

該程式分配有兩個緩衝區,它們在記憶體中是相鄰的,當第一個緩衝區溢位時會改寫第二個緩衝區中的中繼資料。編譯用ltrace跟蹤運行:

sep@sep:~/project/shellcode$ ltrace ./basicheap `perl -e 'print "A" x 5000'`__libc_start_main(0x8048444, 2, 0xbfb19a24, 0x80484d0, 0x80484c0 <unfinished ...>malloc(1024)                                                        = 0x804a008malloc(1024)                                                        = 0x804a410printf("buf=%p, buf2=%p/n", 0x804a008, 0x804a410buf=0x804a008, buf2=0x804a410)                   = 30strcpy(0x804a008, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...)            = 0x804a008free(0x804a410 <unfinished ...>--- SIGSEGV (Segmentation fault) ---+++ killed by SIGSEGV +++

發生了segmentation fault。兩個緩衝區的首地址分別是0x804a008和0x804a410,它們之間的距離是0x804a410-0x804a008=1032=1024+8,它等於緩衝區的長度1024位元組加上存貯塊資訊頭的8個位元組。進行strcpy了5000個位元組的資料到buf中時,發生了堆溢出,從而改寫了buf2的頭部塊資訊,這時進行free(buf2)操作就會導致段故障。

對於strace、ltrace等工具的使用,見:http://www.ibm.com/developerworks/cn/linux/l-tsl/

我們怎樣欺騙malloc,使它處理改寫後的記憶體塊是問題的關鍵。首先,我們要清除被改寫的塊頭部的previous-in-use位,然後把“前一塊”的長度設為負數,這樣將運行我們在緩衝區中定義我們自己的塊。

malloc實現,包括Linux中dlmalloc,都把額外資訊儲存到空閑塊裡。空閑塊的前4個位元組是前向指標,接下來的4個位元組是一個後向指標,這兩種指標把空閑塊掛在雙向鏈表上。在對雙向鏈表的插入和刪除操作中,我們可以利用這些指標改寫任意記憶體位址中的資料。

./basicheap `python -c 'print "A" * 1024 + "/xff/xff/xff/xff" + "/xf0/xff/xff/xff"'`

該命令運行後,堆緩衝區buf溢出,改寫了buf2頭部的8個位元組為0xfffffff0和0xffffffff。

找出緩衝區的長度,在以上的例子中我們通常可以在記憶體中看到緩衝區(以A開始的)的起始位置,這個word之前的資料就是緩衝區的長度。(gdb) x/xw buf-4顯示長度是1033,它等於buf的長度1024加上儲存塊資訊的8個位元組,而最後1位指示這個塊之前是否還有其他塊。如果它被置位(像這個例子),表明這塊頭部沒有儲存前一個塊的大小;如果它被置0,則表示這個塊之前還有一個塊,而且buf-8中的資料就是前一個塊的大小。倒數第二位是一個標記,表示這個塊是否由nmap分配的。

sep@sep:~/project/shellcode$ gdb ./basicheapGNU gdb 6.4.90-debianCopyright (C) 2006 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/i686/cmov/libthread_db.so.1".(gdb) r `python -c 'print "A"*(1024)+"/xfc/xff/xff/xff"+"/xf0/xff/xff/xff"+"AAAAABCDEFGH" '`Starting program: /home/sep/project/shellcode/basicheap `python -c 'print "A"*(1024)+"/xfc/xff/xff/xff"+"/xf0/xff/xff/xff"+"AAAAABCDEFGH" '`Failed to read a valid object file image from memory.buf=0x804a008, buf2=0x804a410 ;輸出兩個緩衝區的首地址*** glibc detected *** /home/sep/project/shellcode/basicheap: free(): invalid pointer: 0x0804a410 ***======= Backtrace: =========/lib/i686/cmov/libc.so.6[0xb7ecc764]/lib/i686/cmov/libc.so.6(cfree+0x96)[0xb7ece966]/home/sep/project/shellcode/basicheap[0x80484b2]/lib/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7e74455]/home/sep/project/shellcode/basicheap[0x80483b1]======= Memory map: ========08048000-08049000 r-xp 00000000 08:01 30559 /home/sep/project/shellcode/basicheap08049000-0804a000 rw-p 00000000 08:01 30559 /home/sep/project/shellcode/basicheap0804a000-0806b000 rw-p 0804a000 00:00 0 [heap]b7d00000-b7d21000 rw-p b7d00000 00:00 0 b7d21000-b7e00000 ---p b7d21000 00:00 0 b7e48000-b7e54000 r-xp 00000000 08:01 1318 /lib/libgcc_s.so.1b7e54000-b7e55000 rw-p 0000b000 08:01 1318 /lib/libgcc_s.so.1b7e5d000-b7e5e000 rw-p b7e5d000 00:00 0 b7e5e000-b7fb3000 r-xp 00000000 08:01 11668 /lib/i686/cmov/libc-2.7.sob7fb3000-b7fb4000 r--p 00155000 08:01 11668 /lib/i686/cmov/libc-2.7.sob7fb4000-b7fb6000 rw-p 00156000 08:01 11668 /lib/i686/cmov/libc-2.7.sob7fb6000-b7fb9000 rw-p b7fb6000 00:00 0 b7fc0000-b7fc3000 rw-p b7fc0000 00:00 0 b7fc3000-b7fc4000 r-xp b7fc3000 00:00 0 [vdso]b7fc4000-b7fde000 r-xp 00000000 08:01 11658 /lib/ld-2.7.sob7fde000-b7fe0000 rw-p 0001a000 08:01 11658 /lib/ld-2.7.sobf879000-bf88e000 rw-p bf879000 00:00 0 [stack]Program received signal SIGABRT, Aborted.0xb7fc3410 in ?? ()(gdb) x/xw 0x804a008-4 ;列印buf-4處的內容0x804a004: 0x00000409  ;buf的大小(gdb) x/xw 0x804a410-8 ;列印buf2-8處的內容0x804a408: 0xfffffffc  ;原來應該為前一個塊的大小,現被改寫為0xfffffffc(gdb) x/xw 0x804a410-4 ;列印buf2-4處的內容0x804a40c: 0xfffffff0  ;原來應該為buf2的大小,現被改寫為0xfffffff0(gdb) x/xw 0x804a410   ;緩衝區buf2被填充了字串“AAAAABCDEFGH”0x804a410: 0x41414141  (gdb) x/xw 0x804a410+40x804a414: 0x44434241(gdb)

到這裡,在我作業系統上實驗的結果和原書的完全不同。由於缺少實驗的直觀結果,加上原書寫得非常簡略晦澀,很多內容我是一知半解的,在這裡就不繼續這部分了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.