2013-04-06 69 views
2

這項計劃與我的機器上的root權限運行的一個基本的堆棧溢出,我需要執行以下代碼堆棧溢出攻擊,並獲取root權限:創建使用IDA

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <openssl/sha.h> 

void sha256(char *string, char outputBuffer[65]) 
{ 
    unsigned char hash[SHA256_DIGEST_LENGTH]; 
    int i = 0; 
    SHA256_CTX sha256; 
    SHA256_Init(&sha256); 
    SHA256_Update(&sha256, string, strlen(string)); 
    SHA256_Final(hash, &sha256); 

    for(i = 0; i < SHA256_DIGEST_LENGTH; i++) 
    { 
     sprintf(outputBuffer + (i * 2), "%02x", hash[i]); 
    } 
    outputBuffer[64] = 0; 
} 

int password_check(char *userpass) 
{ 
    char text[20] = "thisisasalt"; 
    unsigned int password_match = 0; 
    char output[65] = { 0, }; 
    // >>> hashlib.sha256("Hello, world!").hexdigest() 
    char pass[] = "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"; 

    text[0] = 'a'; 
    text[1] = 't'; 
    text[2] = 'j'; 
    text[3] = '5'; 
    text[4] = '3'; 
    text[5] = 'k'; 
    text[6] = '$'; 
    text[7] = 'g'; 
    text[8] = 'f'; 
    text[9] = '['; 
    text[10] = ']'; 
    text[11] = '\0'; 
    strcat(text, userpass); 
    sha256(text, output); 

    if (strcmp(output, pass) == 0) 
    { 
     password_match = 1; 
    } 

    return (password_match == 1); 
} 

int main(int argc, char **argv) 
{ 
    if (argc < 3) 
    { 
     printf("Usage: %s <pass> <command>\n", argv[0]); 
     exit(1); 
    } 
    if (strlen((const char *) argv[1]) > 10) 
    { 
     printf("Error: pasword too long\n"); 
     exit(1); 
    } 

    if (password_check(argv[1])) 
    { 
     printf("Running command as root: %s\n", argv[2]); 
     setuid(0); 
     setgid(0); 
     system(argv[2]); 
    } 
    else 
    { 
     printf("Authentication failed! This activity will be logged!\n"); 
    } 

    return 0; 
} 

所以我試着分析使用IDA的程序看到文本段從低位地址到高位地址,高於我看到的數據,然後是bss,最後是外部命令。

現在據我所知,堆棧應該剛好在上面,但我不確定如何查看它,我應該如何查看堆棧才能知道我在寫什麼? (難道我甚至需要它還是我完全無能?)

第二個問題是考慮輸入的長度,我該如何解決這個檢查代碼得到:

if (strlen((const char *) argv[1]) > 10) 
    { 
     printf("Error: pasword too long\n"); 
     exit(1); 
    } 

我可以以某種方式給字符串通過引用到程序中?如果是這樣,我該怎麼做? (同樣,希望我沒有完全無能)

回答

3

現在據我知道棧應該只是上面說的,但我不能確定如何看待它,究竟我應該查看爲了知道我在寫什麼? (難道我甚至需要它還是我完全無能?)

堆棧位置改變一切的時候 - 你需要看看ESP/RSP寄存器的值,其值是頂級的當前地址的堆棧。通常,可變尋址將基於EBP而不是ESP,但它們都將指向相同的一般內存區域。

在分析過程中,IDA爲每個函數設置了一個堆棧框架,其行爲非常類似於struct--您可以定義其中包含類型和名稱的變量。此框架彙總在功能頂部:stack summary view 雙擊它或函數體中的任何局部變量將打開一個更詳細的窗口。如果沒有在調試器中實際運行程序,那就好。

你可以看到,text毗鄰password_match,並從地址來看,有分配text,正如人們所期望0x14字節。但是,這不能保證和編譯器可以自由混洗變量,填充它們或優化它們到寄存器。

第二個問題是考慮輸入的長度,我該如何解決這個檢查代碼:

if (strlen((const char *) argv[1]) > 10) 
{ 
    printf("Error: pasword too long\n"); 
    exit(1); 
} 

你不需要繞過這個檢查,它已經打破足夠。有一個錯誤的錯誤。

如果你想弄清楚自己的溢出,請在這裏停止閱讀。


指數text跨距從text[0]通過text[19]的有效範圍。在代碼中,用戶輸入寫入從text[11]開始的內存區域。 strlen檢查允許的最大輸入長度爲10個符號+ NULL終止符。不幸的是,這意味着text[19]包含第9個用戶輸入的符號,並且第10個符號+終止符溢出到相鄰的存儲空間中。在某些情況下,允許用任意值覆蓋password_match的最低有效字節,而使用0覆蓋第二個最低有效字節。
如果password_match等於1,則表示密碼中的第10個字符需要爲'\x01'(請注意,這與'1'的字符不同)。

以下是IDA作爲調試器運行的兩個屏幕截圖。 text以黃色突出顯示,password_match呈綠色。

我輸入的密碼是123456789\x01

  1. 棧之前用戶輸入的密碼strcat倒是爲textstack variables before overflow

  2. strcat後堆棧。請注意,password_match已更改。 stack variables after overflow

+0

哇男人太感謝你了,我想通了一些出來單獨包括溢出是哪裏,但我相信我在寫在寄信人地址,而不是過度的密碼!它的偉大工程,謝謝! – 2013-04-09 10:32:40

+0

@MehMeh:不客氣。 – DCoder 2013-04-09 19:29:39