基本的なバイナリエクスプロイテーションの方法論

Reading time: 14 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

ELFの基本情報

何かをエクスプロイトする前に、ELFバイナリの構造の一部を理解することが興味深いです:

ELF Basic Information

エクスプロイトツール

Exploiting Tools

スタックオーバーフローの方法論

多くの技術があるため、各技術がどのように役立つかのスキームを持つことは良いことです。同じ保護が異なる技術に影響を与えることに注意してください。各保護セクションで保護を回避する方法を見つけることができますが、この方法論ではありません。

フローの制御

プログラムのフローを制御する方法はいくつかあります:

  • スタックオーバーフローによってスタックからリターンポインタを上書きするか、EBP -> ESP -> EIPを操作します。
  • オーバーフローを引き起こすために整数オーバーフローを悪用する必要があるかもしれません。
  • または任意の書き込み + 実行への書き込みを介して。
  • フォーマット文字列: printfを悪用して任意の内容を任意のアドレスに書き込みます。
  • 配列インデクシング: 不適切に設計されたインデクシングを悪用して、いくつかの配列を制御し、任意の書き込みを取得します。
  • オーバーフローを引き起こすために整数オーバーフローを悪用する必要があるかもしれません。
  • bofからWWWへのROP: バッファオーバーフローを悪用してROPを構築し、WWWを取得できるようにします。

実行への書き込み技術は以下で見つけることができます:

Write What Where 2 Exec

永続ループ

考慮すべきことは、通常脆弱性の1回のエクスプロイトでは不十分な場合があるということです。特にいくつかの保護を回避する必要があります。したがって、単一の脆弱性を同じバイナリの実行中に何度もエクスプロイト可能にするいくつかのオプションを議論することは興味深いです:

  • main関数のアドレスまたは脆弱性が発生しているアドレスをROPチェーンに書き込みます。
  • 適切なROPチェーンを制御することで、そのチェーン内のすべてのアクションを実行できるかもしれません。
  • exitのGOT内のアドレス(またはバイナリが終了する前に使用する他の関数)に脆弱性に戻るアドレスを書き込みます。
  • .fini_arrayで説明されているように、ここに2つの関数を格納します。1つは再度脆弱性を呼び出し、もう1つは__libc_csu_fini**を呼び出し、再度.fini_arrayから関数を呼び出します。

エクスプロイトの目標

目標: 既存の関数を呼び出す

  • ret2win: フラグを取得するために呼び出す必要がある関数がコード内にあります(特定のパラメータが必要な場合があります)。
  • PIEがない通常のbofでは、スタックに保存されたリターンアドレスにアドレスを書き込むだけで済みます。
  • PIEがあるbofでは、それを回避する必要があります。
  • canaryがあるbofでは、それを回避する必要があります。
  • ret2win関数を正しく呼び出すために複数のパラメータを設定する必要がある場合は、以下を使用できます:
  • すべてのパラメータを準備するための十分なガジェットがある場合は、ROP チェーン
  • SROP(このシステムコールを呼び出せる場合)を使用して多くのレジスタを制御します。
  • ret2csuおよびret2vdsoからのガジェットを使用して複数のレジスタを制御します。
  • Write What Whereを介して、他の脆弱性(bofではない)を悪用して**win**関数を呼び出すことができます。
  • ポインタのリダイレクト: スタックに呼び出される関数へのポインタや、興味深い関数(systemまたはprintf)で使用される文字列へのポインタが含まれている場合、そのアドレスを上書きすることが可能です。
  • ASLRまたはPIEがアドレスに影響を与える可能性があります。
  • 未初期化変数: あなたは決してわかりません。

目標: RCE

シェルコードを介して、nxが無効な場合またはシェルコードとROPを混合する場合:

  • (スタック)シェルコード: これは、リターンポインタを上書きする前または後にスタックにシェルコードを格納し、次にそれにジャンプして実行するのに役立ちます:
  • いかなる場合でも、 canaryがある場合、通常のbofではそれを回避する必要があります(リーク)
  • ASLRがない場合、および nxが無効な場合、スタックのアドレスにジャンプすることが可能です。なぜなら、それは決して変わらないからです。
  • ASLRがある場合、ret2esp/ret2regのような技術を使用してそこにジャンプする必要があります。
  • nxがある場合、いくつかのROPを使用してmemprotectを呼び出し、ページをrwxにしてから、そこにシェルコードを格納する(例えばreadを呼び出す)必要があります。そして、そこにジャンプします。
  • これはシェルコードとROPチェーンを混合します。

システムコールを介して

  • Ret2syscall: 任意のコマンドを実行するためにexecveを呼び出すのに役立ちます。特定のシステムコールをパラメータで呼び出すためのガジェットを見つける必要があります
  • ASLRまたはPIEが有効な場合、バイナリやライブラリからROPガジェットを使用するためにそれらを打破する必要があります。
  • SROPret2execveを準備するのに役立ちます。
  • ret2csuおよびret2vdsoからのガジェットを使用して複数のレジスタを制御します。

libcを介して

  • Ret2lib: libcのライブラリから関数(通常はsystem)を呼び出すのに役立ちます。準備された引数(例:'/bin/sh')を使用します。呼び出したい関数を持つライブラリをバイナリがロードする必要があります(通常はlibc)。
  • 静的にコンパイルされていて、 PIEがない場合、systemおよび/bin/shアドレスは変わらないため、静的に使用することが可能です。
  • ASLRがない場合、およびロードされたlibcのバージョンを知っている場合、systemおよび/bin/shアドレス**は変わらないため、静的に使用することが可能です。
  • ASLRがあるがPIEがない場合、libcを知っていて、バイナリがsystem**関数を使用している場合、GOT内のsystemのアドレスにretし、'/bin/sh'のアドレスをパラメータにすることが可能です(これを見つける必要があります)。
  • ASLRがあり、PIEがないが、libcを知っていて**バイナリがsystem**を使用していない場合:
  • ret2dlresolveを使用してsystemのアドレスを解決し、呼び出します。
  • ASLRを回避し、メモリ内のsystemおよび'/bin/sh'のアドレスを計算します。
  • ASLRがあり、PIEがあり、libcを知らない場合:次のことを行う必要があります:
  • PIEを回避します。
  • 使用されている**libcバージョン**を見つけます(いくつかの関数アドレスをリークします)。
  • 続行するためにASLRを使用した以前のシナリオを確認します

EBP/RBPを介して

  • スタックピボット/EBP2Ret/EBPチェイニング: スタック内の保存されたEBPを介してESPを制御してRETを制御します。
  • オフバイワンスタックオーバーフローに役立ちます。
  • ペイロードをメモリに構築し、次にEBPを介してそれにジャンプする際にEIPを制御するための代替手段として役立ちます。

その他

  • ポインタのリダイレクト: スタックに呼び出される関数へのポインタや、興味深い関数(systemまたはprintf)で使用される文字列へのポインタが含まれている場合、そのアドレスを上書きすることが可能です。
  • ASLRまたはPIEがアドレスに影響を与える可能性があります。
  • 未初期化変数: あなたは決してわかりません。

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする