2

長いsschpealヘッドが必要ない場合は、最後の段落->

gets()関数のローカル1024文字*バッファを埋めるために使用しているプログラムにバッファオーバーフローの脆弱性が見つかりました。Sparc Solaris 5.8(sun4u)32ビット上にあります。

克服すべき最初の障害は、tch手動で257文字以上を入力できないことでした(Enterキーを押したい場合は256文字)。

これを回避するために、私は実行/bin/shしていてstty raw、1095文字を超えるバッファを効果的にオーバーフローさせることができます。(注:ラインフィード/入力を行うにはCtrl-Jを使用する必要がありますが、この変更が発生する理由を調べるためにsttyrawを調査していません。

私の問題はこれです:バッファをオーバーフローさせるだけでなく、新しいリターンアドレスを書き込む/ 16進コードで%fpを保持する時が来ました。しかし、ターミナルプログラム内から16進コードを手動で入力する方法がわからないため、Cを使用して、脆弱なプログラムを実行/対話し、最終的にカスタムバッファを送信する方法を見つけることができると考えました。

ただし、16進バイトを手動で入力/コピーして貼り付ける方法があれば、このような簡単なことを実行できます。

perl -e 'print "n" . "A"x1094 . "\xff\xbe\xf5\x58" . "\xff\xbe\xff\x68" . "\0"'

(なぜ私が'n'を出力しているのか疑問に思っているのなら、脆弱なプログラムが文字列のyes / no @ index 0をチェックするからです)

このような16進情報を手動で貼り付ける方法がわからないため、Cで試しています。Cでは、特別なバッファーを作成しpopen()、脆弱なプログラム( "w")を学習して、バッファーをfputしましたが、せいぜいiffyで動作します。(popenで、IPC私にとってはまったく新しいものです)

(私も試しpiping/dup2ingましたが、結果は得られず、効果的な文字列の出力/入力の証拠もありませんでした)何が問題になっているのかわからないので、コードを何度も試し、後でそれを放棄しました。

私の「popen」プログラムからの出力を表すのに最適なのは、インデックス[1096-> 1099]でバッファを区切るだけで、脆弱なプログラムにセグメンテーション違反が発生することです。これは事実上、関数の場所である%fpため、正常に見えました@最初。ただし、これよりも高いインデックスで文字列を区切ると、プログラミングは正常に機能します(WTF)!!! そして、そのような振る舞いは私にWTFを考えさせます!!?これは手動で貼り付けるのと同じ動作ではありません。文字を増やすと、セグメンテーション違反->バスエラーが最も確実に変化します。次に、リターンアドレスを上書きし、その後にそのスタックフレーム内およびそれ以降の重要な情報を上書きするためです。

文字列全体が実際に1回の強打で送信されないのですか?!?!?fflush()からバッファの問題について何か聞いたのですpopen() manpageが、その話がわかりません!!

を使用するのは初めてpopen()で、奇妙だと思った動作がさらにあります->fputs()データを停止すると、脆弱なプログラムは無限ループに入り、通常は1回しか出力されない最後の出力文字列を繰り返し出力しますが、これでは場合によっては、fputingを停止すると、無限に印刷が開始されます。さて、私が出力していないのなら、プログラムはただ座って、良いアヒルのようにさらなる入力を待つのではないかと期待していました。??? どうやらそうではありません。次の文字列を入力する必要があるのは、どうやら小便とうめき声を続けなければならないようです!これはpopenでの通常の動作ですか?!おそらく、実際に終了する前に、私のpopen'プログラムがpclose()で終了して終了したことが原因です(ただし、バッファオーバーフローが予想されていたため、手動で貼り付けた場合のように取得できない理由がわかりません)

:「\ r \ n」を使用して、脆弱なプログラムに「return」を実行するように通知しています。CTRL-J/ Enterキー(Enterキーはraw ttyでは機能しません)に相当するものかどうかはわかりません。また、バッファを配管するときにrawttyが必要かどうかもわかりません。

それから私は賢くして文字列をファイルにキャットし、コマンドラインを介してパイプを実行しようと思った。この形式の入力を期待するプログラムにこのようにパイプできるかどうかはわかり
ませんが、オーバーフローは1つも発生しませんでした。すなわち

printf "\r\n" > derp && perl -e 'print "n" . "A"x1025' >> derp && printf "\r\n" >> derp
cat derp | ./vuln

ここで、<->をtshに巻き戻します。私は、257文字の制限があると言いました。Enterキーを押してプログラムの操作を続行できるようにするには、それより1つ少なくする必要がありました。したがって、おそらく\ r \ nはここにありません。これは、2文字です。それかあなたはcatこのようなプログラムに参加することはできません。しかし、私はCプログラムで\ r \ nを使用して、脆弱なプログラムにEnterキーを押したことを伝えています。手動で貼り付けるのと同じ方法でバッファをオーバーフローさせることはありませんが、少なくとも穏やかに機能します(実際にはそうではありません)。ゴミ箱バッファ。

ARGh !!!

また、どちらか一方だけを使用すると、「\r」または「\n」は間違いなく機能しませんでした。私が見逃している別のコントロール文字はありますか?そして、これが私のプログラムの問題の1つである可能性はありますか?

しかし、基本的に私の全体的な問題は、実行してコマンドライン実行可能ファイルとインターフェイスするプログラムを作成する方法を理解できず、ちょっと言ってしまうことです!!! このバッファ全体をgets()に入れてください、私はあなたが本当にそれを好きになることを知っています!! 自分でターミナルからプログラムを実行している場合と同じように。
そして、16進コードを手動で端末に貼り付ける/書き込む方法がないことを私は知っています、それが理由ですなぜ私はCでhextバイトの文字列を作成し、そのプログラムのgets()に送信する相互作用プログラムを作成しようとしているのですか!!!! この段落にジャンプした場合は、257文字以上を手動で入力できるように/ bin /bashとsttyrawを具体的に使用していることも知っておいてください(正常に作成できる場合は、これを続行する必要があるかどうかはわかりません)脆弱なプログラムにバッファを送信するための相互作用するプログラム。おそらく、その方法でバッファを送信すると、tchの端末257文字の制限がバイパスされます)

誰か助けてくれませんか!?!?!?!?!

4

4 に答える 4

2

popen呼び出しはおそらくあなたが望む呼び出しです。pclose子プロセスが適切に刈り取られるように、テストの終了後に必ず電話してください。

バイナリモードではモードに「b」を追加することが可能であると述べたLinuxのマニュアルページを編集しますが、POSIXは「r」または「w」以外は未定義であると述べています。これを指摘してくれたDanMoldingに感謝します。

FILE *f = popen("./vuln", "w");
fwrite(buf, size, count, f);
pclose(f);
于 2012-06-25T22:45:11.977 に答える
1

シェルがで読み取っている場合gets()は、標準入力を読み取っています。

したがって、エクスプロイトコードでは、適切な長すぎる文字列を生成する必要があります。で遊んでいない限りexpect、エクスプロイトプログラムから被害者の標準入力に接続されたパイプに長すぎるバッファを書き込むだけです。長すぎる文字列に改行(CRまたはLF)が含まれていないことを確認する必要があります。パイプを使用すると、端末設定とcontrol-Jのcontrol-Mなどの変動を回避できます。パイプは透過的な8ビットのトランスポートメカニズムです。

したがって、プログラムは次のようにする必要があります。

  1. パイプを作成します(pipe())。
  2. フォーク。
  3. 子:
    • パイプの読み取り端を標準入力(dup2())に接続します。
    • パイプの読み取り端と書き込み端を閉じます。
    • 被害者プログラムを実行します。
    • エラーを報告し、被害者の実行に失敗した場合は終了します。
  4. 親:
    • パイプの読み取り端を閉じます。
    • 被害者の入力バッファをオーバーフローさせる文字列を生成します。
    • パイプを下って犠牲者に文字列を書きます。
  5. 座って花火を見てください!

popen()オプションを使用すると、これを単純化できる場合があり"w"ます(親プロセスが子に書き込みたいため)。

信号処理について何をすべきかを考慮する必要があるかもしれません。ここでも、そうしない方が簡単ですが、レシーバー(犠牲者)が終了したときにパイプに書き込むと、親を終了するSIGPIPEシグナルを受け取ります。

于 2012-06-25T22:47:45.287 に答える
1

何も結果を生み出していません。

私が問題だと思うものを強調しておきましょう。私がパイプする文字列に\nは、脆弱なプログラムの「Enterキーを押して続行する」ことを確認するための最初の文字列が含まれています。

オーバーフローに進むバッファが宣言されていchar c[1024]ます; 今、私はこれを1100バイト以上で埋めます。理解できません; うまくいくこともあれば、うまくいかないこともあります。揺らぐ要因は、私がgdbにいる場合です(gdbにいるとより良い結果が得られます)。しかし、時にはそれもあふれません。このため、これは、バッファの転送方法に関するシェル/端末設定のある種の問題であると本当に信じています。しかし、私はこれを修正する方法がわかりません:(

皆さんの助けに本当に感謝しています。しかし、私は一貫した結果を受け取っていません。私は多くのことをし、多くの大まかな資料を学びましたが、この努力を断念する時が来たのではないかと思います。または、少なくとも誰かが答えを出すまでもっと長く待ちます。

psがインストールされているExpect、:)しかし、その中からオーバーフローを受け取ることができませんでした...

パイプがその仕事を終えた後、私はストリームの制御を取り戻す必要があるので、とにかくExpectを必要としているように見えました。プログラムをオーバーフローさせることができないという事実を除けば、これを非常に単純にしたことを期待してください。

私はこれがターミナルシェルの設定と何か関係があることを誓いますが、私には手がかりがありません。

于 2012-06-26T13:34:15.760 に答える
0

別の更新

それは最も奇妙です。

私は実際にリターンアドレスをシェルコード環境変数のアドレスで効果的に上書きしました。

それは昨夜でした。奇妙なことに、環境変数の最後に移動した後、プログラムがクラッシュし、シェルが表示されませんでした。シェルコードは手書きで機能します(メインのリターンアドレスをシェルコードのアドレスに変更して、シェルコードが機能することを確認するためのテスト目的で戻る空のプログラムで)。このテストプログラムでは、MainがSPARCシェルコードに戻り、シェルを生成します。

... so....idk新しいコンテキストで機能しなかった理由。しかし、それは私の問題の中で最も少ないものです。オーバーフローがおかしいので.....

以前の投稿で述べたように、しばらくするとオーバーフローを再現できなかったようです。だから、私はちょっと考えました、セグフォールトを確実にするために、@JonathanLefflerが推奨するようなゴミ「A」で満たされたより大きくてより危険な4000文字のバッファを送ってみましょう。そして、STRANGEの結果を言ってみましょう。

送信する文字数が3960文字未満の場合、オーバーフロー(WTF?!?!)は発生しませんが、以前は約1100文字しか実行しないとオーバーフローが発生する可能性がありました。これは大幅に少なく、その小さいバッファーは正確な文字を上書きします。差出人住所のスポット(それが機能したとき。*

今、最も奇妙な部分!!!

この「ピッキー」バッファは、特定の長さに対してのみセグメンテーション違反のようです。しかし、4000文字の大きなバッファを送信した後にgdbを使用しようとすると、何か奇妙なことに気づきました。はい、セグフォールトしましたが、以前はオーバーフローできた差出人住所を含む「保存領域」があり、何とか無傷で、画像から見ることができます(まだクリックしないでください)次の段落を読んですべてを理解してください正しく表示できます。私はそれが適切な理解なしに混乱しているように見えると確信しています。細工したバッファの一部は、以前に小さいバッファで影響を与えたメモリの特定の領域に影響を与えていません。これがどのように、またはなぜ起こっているのか。まだ知らない。この振る舞いがどれほど規則的かはわかりません。しかし、私は見つけようとします。

そのイメージは、バッファの開始アドレスから約1000バイトで発生します。私のバッファ(16進数の「A」)からの多くの0x41の間に埋め込まれた「保存されたメモリセグメント」を見ることができます。実際には、アドレス0xffbef4bcは0x0001136cのリターンアドレスを保持しますが、これは上書きする必要があります。これは、これを呼び出した関数のリターンアドレスです。'thisone'=脆弱なバッファーを保持する関数です。SPARCのスタックウィンドウの性質上、 (*脆弱なバッファが属する関数 *のリターンアドレスを書き込むことはできません。そのリターンアドレスは実際にはバッファのアドレスより下にあり、到達できないため、リターンを上書きする必要があります。上記の関数のアドレス。別名私たちの発信者;)

とにかく重要なのは、以前はそのリターンアドレスを小さなバッファでオーバーフローさせることもできたということです。したがって、WTFはこれらのギャップに対応しています!!?!??!より大きなバッファがこれらをオーバーフローできるべきではありません、特に。小さいバッファが可能であれば(一貫性はありませんが)。何であれ、ここに画像があります。

[画像] http://s16.postimage.org/4l5u9g3c3/Screen_shot_2012_06_26_at_11_29_38_PM.png

于 2012-06-27T05:54:58.303 に答える