2017-08-25 25 views
-2

我試圖從CSCI 4971 course瞭解逆向工程,我正在努力解決一個特定的實驗問題(fmt_string)。如何使用格式字符串漏洞從堆棧中讀取任意指針?

我應該在某處找到並打印出旗幟商店。這裏的源代碼的樣子:

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

#define LINK "\x1b\x5b" "34m" 
#define RESET "\x1b\x5b" "0m" 


int main() 
{ 
    char buf[256]; 
    char *blah = (char *)0xdeadbeef; 
    char *pointer = flag; 
    char *xblah = (char *)0x1337c0de; 

    printf("\x1b\x5b" "32;1m" "Format string bugs " RESET "were discovered in 1990 using fuzz testing\n" RESET 
     "Nobody really cared though until this exploit for ProFTPD was\n" 
     "dropped in 1999 " LINK "http://seclists.org/bugtraq/1999/Sep/328" RESET ".....\n" 
     "\n" 
     "In this challenge you do not need code execution. The flag is\n" 
     "somewhere in memory. There is a pointer to it on the stack. You\n" 
     "must use this pointer to dump the flag...\n" 
     "\n" 
     "You will retrieve it by passing in format string specifiers to\n" 
     "the printf() function\n" 
     "\n" 
     "After class read this article by rebel for fmt string leetness\n" 
     LINK " http://neworder.box.sk/newsread.php?newsid=9103" RESET "\n" 
     "\n" 
     "As a hint, your pointer is somewhere\n between 0x1337c0de and 0xdeadbeef\n" 
     "\n oh, and man printf\n" 
     "\n" 
     "\n" 
     ); 

    while(1) 
    { 
    printf("> "); 
    fgets(buf, sizeof(buf), stdin); 
    printf(buf); 
    } 

} 

這是我走近這個問題:我知道,輸入%x將打印出存儲在堆棧中的數據。所以當我輸入AAAA.%08x.%08x.%08x.%08x.%08x.%08x.%08x,我得到輸出AAAA.00000100.080c7020.00000000.1337c0de.080c90a0.deadbeef.41414141,這是我的預期。

最後4個字節41414141是4個字節的開頭,4個字節deadbeef1337c0de是在源代碼中硬編碼的。現在,我很確定該標誌存儲在地址080c90a0

然而,當我運行this bash command,我不能讓國旗:

$ printf "\xa0\x90\x0c\x08.%08x.%08x.%08x.%08x.%08x.%08x.%s | ./fmt_string" 

我得到的是:

000000.> �� 
      .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                    .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
        .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                      .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
          .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                        .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
            .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                          .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
              .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                            .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
.00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                  .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
     .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                    .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
       .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                      .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
         .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                        .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
           .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                          .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
             .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                            .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
               .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                              .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                 .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
     .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                   .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
       .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                     .00000000.00000000.00000000.00000000.00000000.00000000.> �� 

請幫助我瞭解我在做什麼錯,爲什麼我得到這個輸出,我應該怎麼做才能得到這個標誌?

+0

這個任務聽起來像是無稽之談,因爲它假設1)某個分配順序2)沒有優化完成。 – Lundin

+0

「運行命令'$ printf ...'」???這是一個shell命令嗎?或者你的意思是你輸入的? –

+1

@PaulOgilvie那是shell命令。 –

回答

1

你的bash命令printf甚至從來沒有遇到你的C程序。 ./fmt_string位於雙引號內,作爲printf內建參數的一部分。

在我的桌面上(在沒有所謂fmt_string文件的目錄),我得到:

$ printf "\xa0\x90\x0c\x08.%08x.%08x.%08x.%08x.%08x.%08x.%s | ./fmt_string" 
�� 
.00000000.00000000.00000000.00000000.00000000.00000000. | ./fmt_string 

這是從你顯示輸出不同,所以也許你沒抄你居然跑的命令?


也許你實際上跑過printf "\xa0\x90\x0c\x08.%08x.%08x.%08x.%08x.%08x.%08x.%s" | ./fmt_string。如果沒有管道,它打印:

�� 
.00000000.00000000.00000000.00000000.00000000.00000000. 

因爲你沒有做任何事情,從你打印字符串中解釋% S停止printf內置。使用printf '%s\n' ...,或使用echo。具有諷刺意味的是,你嘗試測試一個格式字符串漏洞被格式字符串的錯誤處理所擊敗。

通過程序輸出的管道printf會逐字打印,因爲它不再有任何printf元字符。在這種情況下,fgets/printf循環只是將stdin複製到stdout,即使它具有二進制垃圾。


至於真正找到其中flag存儲在堆棧中,gcc -O0 -fverbose-asm -masm=intel foo.c -S -o- | less編譯,並期待在海灣合作委員會的意見,看看它把你想要的指針。

(我假設你的攻擊只能針對與-O0編譯的代碼,否則指針將永遠不會被保存在棧上。)

IDK如果你使用-m32與否。如果不是,那麼printf的前6個整數參數將傳入整數寄存器(在x86-64 System V ABI中),所以您需要先通過它們。

查看關於ABI doc鏈接的標籤wiki。我假設你在使用printfbash命令的Linux上。

+0

這是爲什麼downvoted?這完美地解釋了OP從嘗試將格式字符串傳送到C程序失敗的輸出中看到的輸出。 –

3

您的第一次嘗試指示指針存儲在第5個位置。

只需用合適的格式代碼替換第5個%08x,具體取決於指向位置的數據。如果標誌指向一個字符串,然後%s是合適的:

AAAA.%08x.%08x.%08x.%08x.%s.%08x.%08x 

預期輸出:

AAAA.00000100.080c7020.00000000.1337c0de.<secret message>.deadbeef.41414141 
+0

感謝您指出簡單的方法來做到這一點! –