補遺C. ROPを次に学ぶための地図

C.1 ガジェット

ROPでは、実行可能領域にすでにある「短い命令列 + ret」をガジェットとして扱う。スタック先頭に次のガジェットのアドレスがあれば、現在のretが次の命令列へ移る。

pop rdi
ret

この二命令なら、スタック先頭の値をRDIへ入れ、その次の値をRIPへ入れる。本リポジトリの仮想レジスタ演習は、実際の戻り先を壊さずに状態遷移を観察する。

C.2 動的リンクとGOT/PLT

外部関数の呼び出しでは、PLTの入口とGOTの解決済みアドレス表が関与する。RELROはこの表の書き換え可能期間を制限する。これらは「戻り先の上書き」とは別の制御データの話であるため、本編では深入りしない。

C.3 本編とROPの接続点

  1. retはスタック先頭の値をRIPへ入れる。
  2. popはスタック先頭の値をレジスタへ入れる。
  3. 呼び出し規約が関数の引数レジスタを定める。

これらがつながると、スタックを「戻り先の一個の保存場所」から「複数の状態遷移を指定する列」として見られるようになる。