2015-06-22 29 views
3

我想利用一個SUID程序。gdb退出而不是產生一個shell

的程序是:

#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdio.h> 


#define e(); if(((unsigned int)ptr & 0xff000000)==0xca000000) { setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); } 

void print(unsigned char *buf, int len) 
{ 
    int i; 
    printf("[ "); 
    for(i=0; i < len; i++) printf("%x ", buf[i]); 
    printf(" ]\n"); 
} 

int main() 
{ 
    unsigned char buf[512]; 
    unsigned char *ptr = buf + (sizeof(buf)/2); 
    unsigned int x; 

    while((x = getchar()) != EOF) { 
      switch(x) { 
        case '\n': print(buf, sizeof(buf)); continue; break; 
        case '\\': ptr--; break; 
        default: e(); if(ptr > buf + sizeof(buf)) continue; ptr++[0] = x; break; 
      } 
    } 
    printf("All done\n"); 
} 

我們可以很容易地看到,如果我們以某種方式改變PTR的內容與CA開頭,則某些地址的新外殼將催生我們。而且由於ptr通常擁有一些以FF開頭的地址,減少它的方式(ptr)是輸入\字符。所以,我就與0x35000000文件「\」字符,最後3「」在文件

perl -e "print '\\\'x889192448" > file  # decimal equivalent of 0x35000000 
echo aaa > file  # So that e() is called which actually spawns the shell 

最後在gdb年底,

run < file 

然而,而不是產卵殼GDB在說

process <some number> is executing new program /bin/dash 
inferior 1 exited normally 

然後回到gdb提示符而不是獲得一個shell。 我已經通過在合適的位置設置斷點來確認ptr確實是在setresuid()被調用之前以CA開始的。

此外,如果我管這gdb之外,沒有任何反應。

./vulnProg < file 

Bash提示返回。

請告訴我我在哪裏犯錯。

+0

如果去掉所有的冗餘代碼,只是做'會發生什麼INT的main(){setresuid(geteuid(),geteuid(),geteuid()); execlp(「/ bin/sh」,「sh」,「-i」,NULL); }'?這實際上是否符合你的期望? –

+0

對不起,但我不能這樣做,因爲程序在遠程CTF服務器上,而且我的權限有限。 –

回答

3

您可以通過編寫一個簡單的測試程序看問題

int main() { execlp("/bin/sed", "-e", "s/^/XXX:/", NULL); } 

這一切確實是在前面加上「XXX:」開始的版本的sed(而不是外殼)和轉換輸入。

如果您運行在終端生成的程序,並輸入你的行爲是這樣的:

$./a.out 
Hello 
XXX:Hello 
Test 
XXX:Test 
^D 

這正是我們所料。

現在,如果你給它輸入含有「你好\ nWorld」你

$./a.out < file 
XXX:Hello 
XXX:World 
$ 

文件和應用程序立即退出,與輸入流應用程序時輸入的文件已經全部被關閉讀。

如果你想提供額外的輸入,你需要使用一個技巧來不打破輸入流。

{ cat file ; cat - ; } | ./a.out 

這將會把所有從文件中輸入從標準輸入運行./a.out然後 讀取並添加太多。

$ { cat file ; cat - ; } | ./a.out 
XXX:Hello 
XXX:World 
This is a Test 
XXX:This is a Test 
+0

非常感謝。我只有一個小問題。如果我想把'\'放在一個文件(比如payload)和我想要在一個文件上執行的命令(比如commandsFile)上,那麼...... cat payload commandsFile | ./vulnProg ...執行命令並顯示結果,但是... cat有效載荷命令文件> combinedFile; cat combinedFile> ./vulnProg ...不顯示任何結果。兩者有什麼區別? –

+0

'>'表示將它寫入這個文件,'|'用它作爲新進程的輸入。因此'cat a> ./b'將會覆蓋'./b'的內容(不執行'b'),而'cat a | 。/ b'將執行'b'並將'a'的內容作爲輸入。 –