2013-02-09 22 views
9

我正在學習緩衝區溢出並試圖創建一個緩衝區溢出。我有這樣的代碼:編譯C以允許緩衝區溢出

#include <stdio.h> 

char *secret = "password"; 

void go_shell() { 
    char *shell = "/bin/sh"; 
    char *cmd[] = { "/bin/sh", 0 }; 
    setreuid(0); 
    execve(shell,cmd,0); 
} 

int authorize() { 
    char password[64]; 
    printf("Enter Password: "); 
    gets(password); 
    if (!strcmp(password,secret)) { 
     return 1; 
    } 
    else { 
     return 0; 
    } 
} 

int main() { 
    if (authorize()) { 
     printf("login successful\n"); 
     go_shell(); 
    } else { 
     printf("Incorrect password\n"); 
    } 
    return 0; 
} 

我用gcc編譯這個,然後在gdb

我進入大約100「A」 S密碼和程序崩潰運行它。

的問題是沒有寄存器改寫爲0x4141414141414141

我GOOGLE了這一點,並增加了-fno-stack-protector標誌gcc,允許RBP被覆蓋到0x4141414141414141,但沒有別的。

我想知道是否有辦法編譯代碼,以便RIP可以被覆蓋。

+0

您使用的是Linux嗎?我想你還需要在那裏設置一些旗幟。 – nhahtdh 2013-02-09 15:58:45

+0

使用Mac OSX。任何想法是什麼國旗? – carloabelli 2013-02-09 15:59:33

+0

我不知道Mac OSX - 可能會和Ubuntu有很大不同(對不起,我其實是在Ubuntu上做的,而不是Linux)。 – nhahtdh 2013-02-09 16:27:02

回答

3

如果您使用-fno-stack-protector進行編譯,您的代碼已經做到了你想要的。在GDB中看不到RIP的值爲0x4141414141414141的原因是在更新RIP之前會引發一般性保護故障。 (如果發生頁面錯誤,GPF處理程序通常從交換中加載頁面,並通過從失敗的指令開始恢復執行。)

+0

感謝您的幫助,但我想知道是否有辦法關閉GPF,以便RIP可以設置爲「0x4141414141414141」,因爲這就是我正在使用的教程中會發生的情況。 – carloabelli 2013-02-11 22:33:31

+0

@ cabellicar123除非您在該地址創建可執行頁面,否則無法避免GPF。繼續你的教程。下一步可能會提供一個特製的密碼,使密碼跳轉到有效的地址。 – nwellnhof 2013-02-11 22:47:04

+0

非常感謝您的幫助! – carloabelli 2013-02-11 22:49:37

1

在x32上碰到EIP 0×41414141的原因是因爲當程序彈出之前保存的EIP值離開堆棧並返回到EIP,然後CPU嘗試執行存儲器地址0x41414141處的指令,這會導致段錯誤。 (它必須在執行過程之前獲取頁面)

現在,在x64執行過程中,當程序彈出之前保存的RIP值返回到RIP寄存器時,內核會嘗試執行內存地址0x 4141414141414141處的指令。首先,由於規範形式尋址,任何虛擬地址的第48到63位必須是第47位的複製(類似於符號擴展),否則處理器將引發異常。如果這不是問題 - 由於最大用戶空間地址是0x00007FFFFFFFFFF,內核在調用頁面錯誤處理程序之前會執行額外的檢查。

回想一下,在x32體系結構中,地址是在沒有任何「驗證」的情況下傳遞給頁面錯誤處理程序的,該頁面錯誤處理程序試圖加載觸發內核發送程序段錯誤的頁面,但是x64並沒有得到這麼多。

測試它,用0×0000414141414141覆蓋RIP,你會看到預期值被放置在RIP中,因爲內核預先檢查通過,然後頁面錯誤處理程序被調用,就像x32的情況(當然,然後導致程序崩潰)。