JavaScriptを使うバイナリアンの心をくすぐる極上プレゼン

(via Ajaxian)「Heap Feng Shui (風水) in JavaScript」。

ポイントを要約すると

  • Webブラウザ exploit の手法について概説
    • スタックオーバフローは非常に難しい
    • 一般的な heap exploitation も難しい
    • ほかの可能性は?
      • 配列の介在しないスタックオーバフロー (非常に稀)
      • 未初期化変数
      • ヒープ上のアプリケーションデータ操作
        • アプリケーション固有のアロケータ
        • 関数ポインタ
        • オブジェクトポインタ
  • 具体的事例 - WebView setSlice Exploit
    • Heap spraying という手法を利用 (ひたすらヒープをシェルコードで埋める)
    • 関数ポインタを書き換える方法
    • オブジェクトポインタおよび仮想関数テーブルポインタを書き換える方法
    • まとめると Heap spraying は exploit としては確実ではない。確実にするにはヒープをコントロールすべし。
  • ヒープ風水
    • アロケータの挙動は決定論的である
    • 特別なアロケータ操作のシーケンスによりヒープのレイアウトを操作可能
  • IE のJavaScriptにおけるヒープ風水
  • HeapLib (JavaScript で書かれたヒープ制御ライブラリ)
  • Windows のヒープ構造について概説
  • Visual C++ のオブジェクトポインタや仮想関数テーブルのレイアウトについて概説

しかし、よくまあここまで。これは使えると思ったのは、WinDbgブレークポイントでマクロを使ってログを出力する方法。

bc *
bu 7c9106eb "j (poi(esp+4)==0x150000) '.printf \"alloc(0x%x) = 0x%x\", poi(esp+c), eax; .echo; g'; 'g';"
bu ntdll!RtlFreeHeap "j ((poi(esp+4)==0x150000) & (poi(esp+c)!=0)) '.printf \"                          free(0x%x), size=0x%x\", poi(esp+c), wo(poi(esp+c)-8)*8-8; .echo; g'; 'g';"
bd 0 1
bu jscript!JsAtan2 "j (poi(poi(esp+14)+18) == babe) '.printf \"DEBUG: %mu\", poi(poi(poi(esp+14)+8)+8); .echo; g';"
bu jscript!JsAtan "j (poi(poi(esp+14)+8) == babe) '.echo DEBUG: Enabling heap breakpoints; be 0 1; g';"
bu jscript!JsAsin "j (poi(poi(esp+14)+8) == babe) '.echo DEBUG: Disabling heap breakpoints; bd 0 1; g';"
bu jscript!JsAcos "j (poi(poi(esp+14)+8) == babe) '.echo DEBUG: heapLib breakpoint'"
g

のようにブレークポイントを設定しておいて、

heapLib.ie.prototype.debug = function(msg) {
    void(Math.atan2(0xbabe, msg));
}

これでメッセージを出力する、という。