このコードが保護されていないのはなぜですか?
#include <stdio.h>
int main( int argc, char *argv[] )
    {
       printf(argv[1]);
       printf("\n");
       return 0;
    }
printf%dとのようなものを探して、最初のパラメータを処理します%s。
それらの値に基づいて、スタックからより多くのデータを取得し、それを出力します。
したがって、誰かがあなたのプログラムを呼び出した場合:
a.out "%d %d %d %d %d %d %d %d %d %d %d %d"
彼らはあなたのコンピュータのコールスタックのセクションを見ることができました。
フォーマット指定子を使用してさらにクリエイティブになれば、クレジットカード番号やパスワードなどの重要なものをダンプできる可能性があります。
コントロールの最初の引数が何であるかを検討してくださいprintf(ヒント:printf入力引数を読み取るだけではありません)。
フォーマット文字列の脆弱性とは何かを見てください。
ここで説明を見つけることができます。 https://www.owasp.org/index.php/Testing_for_Format_String
ポスターが例を求めたので、何をしますか%n:
printfフォーマット文字列がメモリを変更する方法は、%nオプションを使用することです。書き込まれる特定の値は、フォーマット幅指定子を「賢く」使用することによって取得できます。テストとして:
#include <stdio.h>
int main(int argc, char **argv)
{
    int *q = (int *)argv[0];
    printf("%1$300000d%5$n",
        123,         // %1 - 1st param (formatted as '300000d')
        0,           // %2 - 2nd param (unused)
        0,           // %3 - 3rd param (unused)
        0,           // %4 - 4th param (unused)
        argv[0]);    // %5 - 5th param (written to via 'n')
    printf("\nNow *q == %d\n", *q);
    return 0;
}
これを実行して出力の最後の行を見ると、印刷されますNow *q == 300000(Linuxでテスト済み)。
ここでは、「興味のない」ものを使用せずに、引数をスキップして変更する引数を選択する方法を示すために、あまり知られていない位置形式の構文(%<pos> $<fmt>)を使用しています。printf()
printf()のような呼び出しの「引数」として何が扱われるかを理解するために、読者の実験に任せますprintf(argv[1])。その答えは、呼び出し規約(または関連するシステムのABI)によって異なり、32/64ビットのWindows / Linux/MacOSXなどでは異なります。