Jurczyk windows metafile_pacsec_jp3

503 views

Published on

PacSec2016

Published in: Internet
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
503
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
13
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Jurczyk windows metafile_pacsec_jp3

  1. 1. Windows メタファイル EMF攻撃ポイントと最近の脆弱性の分析 Mateusz “j00ru” Jurczyk PacSec, Tokyo 2016
  2. 2. PS> whoami •  GoogleのProject Zero 所属 •  脆弱性の研究とソフトウェアエクスプロイトに興味がある低レイヤー のセキュリティ研究者 •  hAp://j00ru.vexillium.org/ •  @j00ru
  3. 3. アジェンダ •  Windows メタファイル入門、GDIデザイン、攻撃ベクタ •  ハック対象: •  Internet Explorer (GDI) •  Windows Kernel (ATMFD.DLL) •  MicrosoV Office (GDI+) •  VMware virtualiza[on (プリントスプール) •  結論
  4. 4. Windows GDI & メタファイル入門
  5. 5. Windows GDI •  GDI はGraphics Device Interface(グラフィックス・デバイス・インターフェイス)の略 •  ユーザーモードアプリケーションで、グラフィックや整形されたテキストをビデオ ディスプレイやプリンターへの出力を可能にする •  システムAPIの大半を占める (約 300 のドキュメント化された機能) •  初期のOSの頃から存在 (1985年にリリースされたWindows 1.0 から) •  最も古いサブシステムの1つで、31年経った今でも大半は元のコードのまま稼働している •  偶然にも(?)もっともバグが多い構成要素の1つである
  6. 6. どのように描画するか 1.  デバイスコンテキスト へのハンドル(HDC)をつかむ •  様々なグラフィカル設定(ペン、ブラシ、パレットなど)の永続的なコンテナを 認識する •  スクリーン(もっとも典型的)、プリンター、メタファイルへの描画で使用可能 •  最も簡単な例: HDC hdc = GetDC(NULL); (画面全体のために HDCを取得)
  7. 7. どのように描画するか 2.  描画機能を使用 Ellipse(hdc, 100, 100, 500, 300); RoundRect(hdc, 100, 100, 500, 500, 100, 100);
  8. 8. Windows GDI – 簡易化したアーキテクチャ app1.exe app3.exe app4.exe app2.exe GDI+ (gdiplus.dll) User-mode GDI (gdi32.dll) Kernel-mode GDI (win32k.sys) NT OS Kernel Printer Drivers Font Drivers Display Drivers ring-3 ring-0
  9. 9. ユーザーモードとカーネルAPIマッピング 大半のユーザーモードGDI関数は直接対応するカーネルAPIを持って いる: GDI32.DLL win32k.sys AbortDoc NtGdiAbortDoc AbortPath NtGdiAbortPath AddFontMemResourceEx NtGdiAddFontMemResourceEx AddFontResourceW NtGdiAddFontResourceW AlphaBlend NtGdiAlphaBlend ... ...
  10. 10. Windows メタファイル コアアイデア: GDI関数呼び出しを記述するレコードのリストとして イメージを格納する.
  11. 11. Windows メタファイル •  長所: •  GDI関数が与えられたパラメータで呼び出された時だけ、ラスタライズ処理の計算は ほとんど必要とされない •  GDIが再現可能な画像を操作するための公式な方法を提供 •  ベクター形式、ラスター形式また両方の形式として動作する •  短所: •  サポートされているグラフィックのGDI操作が外部に完全に実装されていない場合 は、Windows上でのみ動作する
  12. 12. First version: WMF •  最初のメタファイル (WMF = Windows MetaFiles). •  1990年のWindows 3.0 で導入された •  GDIそれ自体のほどではないが、同じくらい古典的 •  はじめてドキュメント化されたのは Windows 3.1 SDK (1994年, volume 4) •  改訂され、より完全な仕様は2006年にリリース、それ以来メンテされ続けている •  全てのレコードや構造はMS-WMFドキュメントに記載されている
  13. 13. WMF files – サポートされている60のAPI関数 AnimatePaletteArc BitBlt Chord CreateBrushIndirect CreateDIBPatternBrush CreateFontIndirect CreatePalette CreatePatternBrush CreatePenIndirect DeleteObject Ellipse Escape ExcludeClipRect ExtFloodFill ExtTextOut FillRgn FloodFill FrameRgn IntersectClipRect InvertRgn LineToMoveToEx OffsetClipRgn OffsetViewportOrgEx OffsetWindowOrgEx PaintRgn PatBlt Pie Polygon Polyline PolyPolygon RealizePalette Rectangle ResizePalette RestoreDC RoundRect SaveDC ScaleViewportExtEx ScaleWindowExtEx SelectClipRgn SelectObject SelectPaletteSetBkColor SetBkMode SetDIBitsToDevice SetMapMode SetMapperFlags SetPaletteEntries SetPixel SetPolyFillMode SetROP2 SetStretchBltMode SetTextAlign SetTextCharacterExtra SetTextColor SetTextJustification SetViewportOrgEx SetWindowExtEx SetWindowOrgEx StretchBlt StretchDIBits TextOut
  14. 14. 一目見ただけでも興味深そうなもの AnimatePaletteArc BitBlt Chord CreateBrushIndirect CreateDIBPatternBrush CreateFontIndirect CreatePalette CreatePatternBrush CreatePenIndirect DeleteObject Ellipse Escape ExcludeClipRect ExtFloodFill ExtTextOut FillRgn FloodFill FrameRgn IntersectClipRect InvertRgn LineToMoveToEx OffsetClipRgn OffsetViewportOrgEx OffsetWindowOrgEx PaintRgn PatBlt Pie Polygon Polyline PolyPolygon RealizePalette Rectangle ResizePalette RestoreDC RoundRect SaveDC ScaleViewportExtEx ScaleWindowExtEx SelectClipRgn SelectObject SelectPaletteSetBkColor SetBkMode SetDIBitsToDevice SetMapMode SetMapperFlags SetPaletteEntries SetPixel SetPolyFillMode SetROP2 SetStretchBltMode SetTextAlign SetTextCharacterExtra SetTextColor SetTextJustification SetViewportOrgEx SetWindowExtEx SetWindowOrgEx StretchBlt StretchDIBits TextOut
  15. 15. WMF: まだまだある! •  このフォーマットは、GDI関数では直接の対応をしていない多くのレ コードをサポートしている. •  ヘッダ情報を持つmetadata •  埋め込み EMF •  プリンタードライバー/出力デバイスを直接扱うレコード •  ファイル終端マーク •  ...
  16. 16. WMF: まだまだある! •  大抵は、最も興味深いレコードが2つのセクションからみつかる:
  17. 17. Windows Metafile – 例 ... R0003: [017] META_SETMAPMODE (s=12) {iMode(8=MM_ANISOTROPIC)} R0004: [011] META_SETVIEWPORTEXTEX (s=16) {szlExtent(1920,1200)} R0005: [009] META_SETWINDOWEXTEX (s=16) {szlExtent(1920,1200)} R0006: [010] META_SETWINDOWORGEX (s=16) {ptlOrigin(-3972,4230)} R0007: [009] META_SETWINDOWEXTEX (s=16) {szlExtent(7921,-8462)} R0008: [049] META_CREATEPALETTE (s=960) {ihPal(1) LOGPAL[ver:768, entries:236]} R0009: [048] META_SELECTPALETTE (s=12) {ihPal(Table object: 1)} R0010: [052] META_REALIZEPALETTE (s=8) R0011: [039] META_CREATEBRUSHINDIRECT (s=24) {ihBrush(2), style(0=BS_SOLID, color:0x00FFFFFF)} R0012: [037] META_SELECTOBJECT (s=12) {Table object: 2=OBJ_BRUSH.(BS_SOLID)} R0013: [037] META_SELECTOBJECT (s=12) {Stock object: 8=OBJ_PEN.(PS_NULL)} R0014: [019] META_SETPOLYFILLMODE (s=12) {iMode(1=ALTERNATE)} R0015: [086] META_POLYGON16 (s=320) {rclBounds(89,443,237,548), nbPoints:73, P1(-2993,398) - Pn(-2993,398)} R0016: [038] META_CREATEPEN (s=28) {ihPen(3), style(0=PS_SOLID | COSMETIC), width(0), color(0x00000000)} ...
  18. 18. WMF: 今なおとても時代遅れなまま •  それ自体がすでに複雑であるが、そのフォーマットは現代的な使用 法に対して考え抜かれたものになることはなかった •  GDIにサポートされているが故に、いくつかのクライアントの一部に使 用されている(例: MicrosoV Office、ペイント、いくつかのWindows標 準アプリケーションなど) •  ここ10年かそれ以上、実世界でのユースケースを忘れ去られていた
  19. 19. WMF: 使う気がおきない •  マイクロソフトでさえ、もう使うべきではない多くの理由をあげている:
  20. 20. 次に来たもの: EMF (Enhanced MetaFiles: 拡張メタファイル) •  すでに1993年に、マイクロソフトはEMFと呼ばれる改良版のイメージフォー マットをリリース •  公式のMS-EMF仕様としてドキュメント化されている •  多くの方法でWMFを上回る: •  16ビットではなく、32ビットのデータ/オフセット長を使用 •  デバイスに依存しない •  古いレコードとの下位互換性を維持しながら、いくつかの新しいGDIコールをサポート
  21. 21. 拡張メタファイル – 例 ... R0121: [039] EMR_CREATEBRUSHINDIRECT (s=24) {ihBrush(2), style(1=BS_NULL)} R0122: [037] EMR_SELECTOBJECT (s=12) {Table object: 2=OBJ_BRUSH.(BS_NULL)} R0123: [040] EMR_DELETEOBJECT (s=12) {ihObject(1)} R0124: [090] EMR_POLYPOLYLINE16 (s=44) {rclBounds(128,-256,130,-254), nPolys:1, nbPoints:2, P1(386,-765) - Pn(386,-765)} R0125: [019] EMR_SETPOLYFILLMODE (s=12) {iMode(1=ALTERNATE)} R0126: [039] EMR_CREATEBRUSHINDIRECT (s=24) {ihBrush(1), style(0=BS_SOLID, color:0x00A86508)} R0127: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)} R0128: [040] EMR_DELETEOBJECT (s=12) {ihObject(2)} R0129: [058] EMR_SETMITERLIMIT (s=12) {Limit:0.000} R0130: [091] EMR_POLYPOLYGON16 (s=60) {rclBounds(127,-259,138,-251), nPolys:1, nbPoints:6, P1(384,-765) - Pn(384,-765)} R0131: [040] EMR_DELETEOBJECT (s=12) {ihObject(1)} R0132: [040] EMR_DELETEOBJECT (s=12) {ihObject(3)} R0133: [014] EMR_EOF (s=20) {nPalEntries:0, offPalEntries:16, nSizeLast:20} ...
  22. 22. EMF: 一目見ただけでも興味深いレコード
  23. 23. EMF: 一目見ただけでも興味深いレコード
  24. 24. EMF: 一目見ただけでも興味深いレコード
  25. 25. EMF: 現在のサポート •  WMFのわずかに3年新しいものではあるが、EMFは今日まで使用さ れている •  メインストリームの画像フォーマットではないが、有効な攻撃ベクタ •  さまざまな攻撃ベクタ: •  Win32 GDI クライアント – 代表は Internet Explorer •  GDI+ クライアント – 代表は MicrosoV Office •  プリンタードライバー、仮想化技術で使われるものも含む
  26. 26. ツールセット – 検査 (EMFexplorer)
  27. 27. ツールセット – 検査 (MetafileExplorer)
  28. 28. ツールセット – リーディング & ライティング (pyemf) #!/usr/bin/env python import os import pyemf import sys def main(argv): if len(argv) != 2: print "Usage: %s /path/to/poc.emf" % argv[0] sys.exit(1) emf = pyemf.EMF(width = 100, height = 100, density = 1) emf.CreateSolidBrush(0x00ff00) emf.SelectObject(1) emf.Polygon([(0, 0), (0, 100), (100, 100), (100, 0)]) emf.save(argv[1]) if __name__ == "__main__": main(sys.argv)
  29. 29. 最新: EMF+ •  GDIはすべて基本的な機能を備えているが、多くの複雑な機能に欠ける (アンチエイリアシング、浮動小数点座標、JPG/PNGのサポートなど) •  WIndows XPは2001年にGDI+と呼ばれる高度なライブラリーを導入 •  大部分はGDI(gdi32.dll)の上に、ユーザーモードgdiplus.dll ライブラリが作られた •  C++ や.NET 向けに高レベルのインターフェースを提供するため、容易に使用可能 •  GDI+はそれ自体C++で書かれているため、典型的なメモリー破損バグが未だに存在
  30. 30. 最新: EMF+ •  新しいインターフェースがあるため、新しい画像フォーマットとそのシリアライズさ れた呼び出しが必要とある •  EMF+にあいさつ! •  基本的にはEMFと同じだが、GDI+の呼び出しを表す •  2種類ある: EMF+ Only と EMF+ Dual •  „Only”は専用のGDI+レコードが含まれ、そしてGDI+でのみ表示することができる •  „Dual”はGDI/GDI+クライアント両方と互換性があり、2つのレコードセットが保存されている
  31. 31. Windowsでのフォーマットと実装 •  考慮すべきは3つのフォーマット: WMF, EMF, EMF+ •  3つのライブラリ: GDI, GDI+ , MF3216 •  vMF3216.DLL は1つの重要な機能を提供するシステムライブラリ: ConvertEmfToWmf •  Windowsのクリップボード内のWMF/ EMFフォーマット間の自動変換する際に使用 •  „Synthesized” formats CF_METAFILEPICT と CF_ENHMETAFILE •  ここにはバグは無かった. L
  32. 32. Windowsでのフォーマットと実装 Library Supported formats GDI WMF, EMF GDI+ WMF, EMF, EMF+ MF3216 EMF 今回の話では、最も(興味深い)問題が見つかったEMFに対する 監査とエクスプロイトにフォーカスする
  33. 33. 攻撃シナリオ •  全ての場合において、メタファイルは対応するDLLでレンダラープロセスのユーザモードコンテキスト として処理される •  GDI, GDI+,MF3216は全てのレコード入力に対し繰り返しGDI/GDI+の呼び出しに変換する •  メモリ破損のバグは、そのコンテキストで任意のコード実行につながる •  重要: メタファイルはレンダラーのGDIコンテキストを直接操作する •  プロセスの代わりとして、作成、削除、変更や、さまざまなGDIオブジェクトを使用することができる •  理論的には、自身のオブジェクトにのみアクセスすべきであり、自己完結である必要がある •  しかし、実装のバグはプログラムによって使用される外部グラフィックスオブジェクトへのアクセスを可能にする •  „権限昇格”の特異なケース
  34. 34. 攻撃シナリオ: GDI による権限昇格 renderer.exe GDI objects EMF #2 GDI objects EMF #3 GDI objects EMF #1 file EMF #1 GDI objects GDI プロセス EMF #2 file EMF #3 file セキュリティ境界
  35. 35. 攻撃シナリオ: GDI による権限昇格 renderer.exe GDI objects EMF #2 GDI objects EMF #3 GDI objects EMF #1 file EMF #1 GDI objects GDI プロセス セキュリティ境界
  36. 36. メタファイルのバグのタイプ 1.  メモリ破損のバグ •  バッファオーバーフローなど特定レコードの誤った取り扱いによるもの •  レンダリングのいずれかのタイプのエクスプロイトの可能性 •  影響: 典型的なリモートからのコード実行(RCE) 2.  メモリ漏えいのバグ •  初期化されていないレンダリング、境界外のヒープメモリーをイメージとして扱う •  画像のみを表示するコンテキストでは裏を読むことができる (Webブラウザ、リモートレンダラー) •  影響: 情報漏えい (秘密情報を盗む、ASLRの突破など) 3.  OSとGDIオブジェクトの誤った管理による不正な相互作用 •  影響、悪用可能性 = ???、バグの種類による
  37. 37. 始めよう! •  今年の初めから、利用可能なEMFの実装について監査を始めた •  結果として、MicrosoVから 10のCVE、VMWareから3つのCVEを見つ けた (実際の数十のバグをカバーする) •  根本原因と、最も面白いエクスプロイトについてもう少し深く見よう •  レイトして32-bit Windows 7に基づいて示しているが、ほとんどの調査内容は Windows10までの両方のビットバージョンにも適用できる
  38. 38. GDIの監査
  39. 39. 入門 •  一般的なアイディアとして、どんな機能が実装され、どんなタイプの バグが過去に見つかったのか、先行技術を確認することは理にか なっている •  „wmf 脆弱性”での検索でただ一つが見つかる: SetAbortProc のバグ!
  40. 40. SetAbortProc WMF バグ (CVE-2005-4560) •  2005/12/27に見つかり、 2006/1/5に修正された •  致命的なバグであり、GDIを使ったエクスプロイトを動かすと100%確実に RCEが出来た (例えば Internet Explorer上) •  „Windows メタファイルの 脆弱性”と呼ばれ Pwnie Award 2007を受賞 •  メモリー破損は関係無く、WMFの文書化された機能を使用 •  なにがバグだった?
  41. 41. GDIのAPI... func[on pointer
  42. 42. ... そして WMF 側では
  43. 43. 本質的には... ... 規約自体の呼び出しをサポート: SetAbortProc(hdc, (ABORTPROC)"controlled data"); そしてその後呼び出される関数インタ 仕様としてのコード実行
  44. 44. 学んだこと 1.  フォーマットは(非)公式にプロキシを呼び出し、興味深い/危険な APIを呼び出し、そのためそれぞれの機能やパラメータは安全でな い振る舞いをしないかチェックをする必要がある 2.  WMFのハンドリングは大きなスイッチ/ケースで起こる gdi32!PlayMetaFileRecord
  45. 45. EMF バグとは? •  „emf vulnerability”の検索でより多彩な結果が見つかる •  最新のもの: Hossein LoViによる„Yet Another Windows GDI Story” •  MS15-035の一部として2015年4月に修正、CVE-2015-1645が割り当てられた •  レコードの1つ(SETDIBITSTODEVICE) の入力である „size”の未検証による、 ヒープベースのバッファオーバーフロー •  EMFセキュリティを見るには大部分はインスピレーション(が必要)
  46. 46. 学んだこと •  EMFレコードを再生するためのメインファンクション gdi32! PlayEnhMetaFileRecord •  各レコードタイプはそれぞれ2つの独自のクラスをもっている: •  ::bCheckRecord() – レコードの内部整合性と正確さをチェック •  ::bPlay() – レコード内に示されたアクションを実行
  47. 47. GDI32 ::bCheckRecord array
  48. 48. GDI32 ::bPlay array
  49. 49. ここからが出発点
  50. 50. Impact: File Existence Informa[on Disclosure Record: EMR_CREATECOLORSPACE, EMR_CREATECOLORSPACEW Exploitable in: Internet Explorer CVE: CVE-2016-0168 google-security-research entry: 722 Fixed: MS16-055, 10 May 2016 CVE-2016-0168
  51. 51. マイナーバグ #1 in EMR_CREATECOLORSPACEW •  小さいけど明らかなバグを見ることでコードの品質がすぐに認識できた •  MRCREATECOLORSPACEW::bCheckRecord() レコードのサイズが 0x50バイ ト以上であるこをとチェック: .text:7DB01AEF mov eax, [esi+4] .text:7DB01AF2 cmp eax, 50h .text:7DB01AF5 jb short loc_7DB01B1E •  その後すぐに、オフセット0x25Cの.cbData フィールドを読み込む: .text:7DB01AF7 mov ecx, [esi+25Ch] •  その結果: 0x20Cバイトの範囲外を読み込む
  52. 52. マイナーバグ #2 in EMR_CREATECOLORSPACEW •  その後、無効オフセット0x25Cの.cbDataはレコード長のチェックに使われ る: .text:7DB01AF7 mov ecx, [esi+25Ch] .text:7DB01AFD add ecx, 263h .text:7DB01B03 and ecx, 0FFFFFFFCh .text:7DB01B06 cmp eax, ecx .text:7DB01B08 ja short loc_7DB01B1E •  上記は以下の様に変換できる: if (... && record.length <= ((record->cbData + 0x263) & ~3) && ...) { // Record valid. }
  53. 53. マイナーバグ #2 in EMR_CREATECOLORSPACEW •  2つの問題がここに: 1.  明らかな整数オーバーフローにより、大きな.cbDataがチェックを通過 する 2.  なぜレコード長は、宣言されたデータよりも小さいのだろうか?それ は大きくあるべきだ! •  データはそれ以降の処理で使用されていないので、幸いそんなに大 きな問題にはなっていない
  54. 54. マイナーバグ #3 in EMR_CREATECOLORSPACEW •  ユーザ定義 LOGCOLORSPACEW 構造体の .lcsFilename バッ ファーはヌル終端のチェックをしていない •  文字列のアクセス中に範囲外を読みだされる可能性がある •  あきらかなように、多くの未チェックの前提データが多く実装されてお り、これまではマイナーという扱いであった •  これらはより深刻ななにかにつながるという予測
  55. 55. 存在ファイル情報の公開 •  EMR_CREATECOLORSPACE[W] レコードの機能に戻る: 完全にコントロール されたLOGCOLORSPACE 構造体とCreateColorSpace[W] を呼び出す typedef struct tagLOGCOLORSPACE { DWORD lcsSignature; DWORD lcsVersion; DWORD lcsSize; LCSCSTYPE lcsCSType; LCSGAMUTMATCH lcsIntent; CIEXYZTRIPLE lcsEndpoints; DWORD lcsGammaRed; DWORD lcsGammaGreen; DWORD lcsGammaBlue; TCHAR lcsFilename[MAX_PATH]; } LOGCOLORSPACE, *LPLOGCOLORSPACE;
  56. 56. CreateColorSpaceWの内側 •  この関数はカラープロファイルパスを組み立てるのに内部で使用される gdi32!BuildIcmProfilePath •  提供されるファイル名が相対的である場合、システムのディレクトリ・パスに追加される •  それ以外の場合は、絶対パスがそのまま残されている •  全てのパスは"/"または""の2文字で始まるものを除き認められている: if ((pszSrc[0] == '' || pszSrc[0] == '/') && (pszSrc[1] == '' || pszSrc[1] == '/')) { // Path denied }
  57. 57. CreateColorSpaceWの内側 •  これは多分“”プレフィックスで始まるパスは例えば 192.168.1.13C Userstestprofile.icc のようにリモートUNCのパス指定を想定している •  しかし, James Forshawはこのチェックが有効でないことを書き示している, “??”のようなプレフィックスでも表記ができるため •  チェックは容易に回避できた: ??192.168.1.13CUserstestprofile.icc
  58. 58. CreateColorSpaceInternalW: 最終段階 •  パスが形成された後, NtGdiCreateColorSpace システムコールが呼び出さ れる前に, 関数はファイルを開き、それが存在稼働かを確認してすぐに閉じる: HANDLE hFile = CreateFileW(&FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { GdiSetLastError(2016); return 0; } CloseHandle(hFile);
  59. 59. 結果 •  その結果, CreateFileW() の呼び出しは任意のパスにすることが できる •  成功すれば、カラースペースオブジェクトが作成され、関数が成功を返す •  失敗した場合は、GDIオブジェクトが作成されず、ハンドラーが失敗を返す •  情報公開の可能性に聞こえる •  例えば Internet Explorerでのエクスプロイトにはどのようにアプローチをすれ ばいい?
  60. 60. 直感的な方法: 戻り値をリーク •  CreateFileW()の戻り値がレコード処理の成功を決定することから、 少しリークできるのではないか? •  最初のアイデア: 描画操作に続いて EMR_CREATECOLORSPACEを最初のレ コードとして使用 •  ( <canvas> タグで決定することができる)描画が行わなければ, 呼び出しは 失敗
  61. 61. 直感的な方法: 戻り値をリーク •  残念ながら不可能 •  関数 (PlayEnhMetaFile 自身によって呼び出される) gdi32! _bInternalPlayEMF は1つのレコードが失敗した時にレコード処理は中 断しない •  „success” のフラグが FALSEにセットされ, 機能が次のプロセスに進む •  全てのレコードが常に実行され、戻り値は少なくともプロセス中の1つのレ コードの失敗したかどうかのフラグを示している
  62. 62. 最終的な戻り値をリークすることはできない? •  あまりできない •  PlayEnhMetaFile の戻り値は Internet Explorer の mshtml! CImgTaskEmf::Decode:によって破棄される .text:64162B49 call ds:__imp__PlayEnhMetaFile@12 .text:64162B4F or dword ptr [ebx+7Ch], 0FFFFFFFFh .text:64162B53 lea eax, [esp+4C8h+var_49C]
  63. 63. その他の開示オプション •  他のインジケータはNtGdiCreateColorSpaceを通したカラース ペースオブジェクトとして作られる •  (すべての可能性を考慮しても)直接の漏えいは簡単ではない、しか しサイドチャンネルがあったらどうだろう?
  64. 64. GDI オブジェクト使用時の制限 •  Windowsの全てのプロセスは、標準で GDIオブジェクトが最大 10,000に制限されている •  数はレジストリで変更できる、しかしIEのためのものではない •  10,000のファイルパス付きEMR_CREATECOLORSPACEWレコードを確認したいときには: •  ファイルが存在するとき、10,000のカラースペースオブジェクトはプロセスの限界に達する •  ファイルが存在しないときは、カラースペースを全く持たない •  限界に達しているかどうかという時、(もうひとつ)ブラシを作成しペイントをすると: •  ファイルが存在するとき、ブラシの作成は失敗し標準のブラシが使用される •  ファイルが存在しないとき、ブラシは作成されペイントに使用される
  65. 65. oracle に示されているGDI オブジェクト限界 Bitmap Font PaleAe Color space Color space Color space Color space ... Color space Color space Color space Color space Color space Color space Color space 限界 Brush Brush Bitmap Font PaleAe Brush Brush ファイルあり: ファイル無し:
  66. 66. デモ
  67. 67. 脆弱性のインパクト •  任意のファイル存在情報が漏えいし、多くの目的で利用可能: •  標的型の攻撃の際に、特定のソフトウェア(およびバージョン)がインストー ルされていることを特定できる •  (既知のファイルに基づいてプロファイルを作成することで)ユーザを追跡 •  オフラインドキュメントのオープンした時間を追跡(例としてMicrosoVOfficeで 開く度にSMB経由でリモートサーバにpingを送るなど) •  ユーザが利用可能なネットワーク共有を探し出す
  68. 68. Impact: Memory disclosure Record: Mul[ple records (10) Exploitable in: Internet Explorer CVE: CVE-2016-3216 google-security-research entry: 757 Fixed: MS16-074, 14 June 2016 CVE-2016-3216
  69. 69. デバイス独立ビットマップ (DIBs) Windows GDIでは、ラスタビットマップは メモリ上でDIB形式で格納されている: •  オプションパレットに続いてイメージの基 本的なメタデータを含むショートヘッダが ある •  画像データそのもの BITMAPINFO BITMAPINFOHEADER RGBQUAD bmiColors[...]; Bitmap data 11142211142211142 21114221114221114 22111422111422111 42211142211142211 14221114221114221 11422111422101321 10132110132110132 11013211013211013 211013210F12200F1 2200F12200F12200F 12200F12200F12200
  70. 70. .BMP ファイルも DIBsと同じ BITMAPINFO BITMAPINFOHEADER RGBQUAD bmiColors[...]; Bitmap data 11142211142211142 21114221114221114 22111422111422111 42211142211142211 14221114221114221 11422111422101321 10132110132110132 11013211013211013 211013210F12200F1 2200F12200F12200F 12200F12200F12200 BITMAPFILEHEADER typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; bfOffBits
  71. 71. BITMAPINFOHEADER、些細なヘッダ typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER; •  短くてシンプルな構造 •  40 バイトの長さ (典型的な形) •  8個だけが重要なフィールド
  72. 72. そんなに簡単な操作なのか? •  biSize はサニタイズする必要がある (ほんの1-2個の有効な値になれるだけ) •  biWidth, biHeight, biPlanes, biBitCount は整数オーバーフローを起こす可能性 がある (お互いに掛け合わすので) •  biHeight はボトムアップビットマップを示すために負の値を指定できる •  biPlanes は1でなければならない •  biBitCount は {1, 2, 4, 8, 16, 24, 32}のうちの1つでなければならない •  biBitCount < 16の場合,カラーパレットを使用できる •  カラーパレットのサイズはbiClrUsedに影響する
  73. 73. その扱いは本当に些細なのか? •  biCompression は BI_RGB, BI_RLE8, BI_RLE4, BI_BITFIELDS, ...とすることができ る •  各圧縮方式は正しく処理されなければならない •  biSizeImage は実際のイメージサイズに対応している必要がある •  パレットは全てのエントリーを格納できる充分な大きさが必要 •  ピクセルデータバッファは全てのピクセルを情報を入れる充分な大きさが必要 •  エンコードされたピクセルはヘッダの値に対応している必要がある (例えばバレットのサ イズを超えないなど)
  74. 74. 多くの潜在的な問題 1.  ヘッダにもとづいてDIBを正しく処理をする決定木(decision tree)は 非常に複雑 2.  多くのやっかいなケースとしては保護とバグを避ける実装をする必 要がある 3.  コードの様々な部分では一貫性のある取り扱いが必要
  75. 75. DIB上で (直接)動作するGDI 関数 イメージデータのポインタ DIB ヘッダのポインタ
  76. 76. DIB上で (直接)動作するGDI 関数
  77. 77. データサニタイズの責任 •  全ての場合において、ヘッダとデータが正しく適切であることをチェックする のはAPI呼び出し元の責任である •  アプリケーションコードが „クローン” GDIによる DIB ハンドリングができるよ うに、完全にユーザが制御可能な入力データを渡すことは問題がある •  何だと思う?EMFは組み込みDIBを含む複数のレコードをサポートしている
  78. 78. DIBを含むEMFレコード •  EMR_ALPHABLEND •  EMR_BITBLT •  EMR_MASKBLT •  EMR_PLGBLT •  EMR_STRETCHBLT •  EMR_TRANSPARENTBLT •  EMR_SETDIBITSTODEVICE •  EMR_STRETCHDIBITS •  EMR_CREATEMONOBRUSH •  EMR_EXTCREATEPEN
  79. 79. 一般的なスキーム •  ヘッダとビットマップの両方のための2組の (offset, size) :
  80. 80. EMFレコードハンドラで必要なチェック •  DIBを扱う各ハンドラでは, 必須な整合性チェックが4つある: 1.  cbBmiSrc はヘッダ内に収まるように充分に大きい事 2.  (offBmiSrc, offBmiSrc + cbBmiSrc) は完全にレコード内に存在する事 3.  cbBitsSrc はビットマップデータ内におさまるように充分に大きい 4.  (offBitsSrc, offBitsSrc + cbBitsSrc) は完全にレコード内に存在する事
  81. 81. チェックは多くの組み合わせで欠落 Record handlers Missing checks MRALPHABLEND::bPlay MRBITBLT::bPlay MRMASKBLT::bPlay MRPLGBLT::bPlay MRSTRETCHBLT::bPlay MRTRANSPARENTBLT::bPlay #1, #2 MRSETDIBITSTODEVICE::bPlay #3 MRSTRETCHDIBITS::bPlay #1, #3 MRSTRETCHDIBITS::bPlay MRCREATEMONOBRUSH::bPlay MREXTCREATEPEN::bPlay #1, #2, #3, #4 * これはざっと見た状態; MicrosoVはもっと修正をしている可能性がある
  82. 82. 結果 •  欠落のチェックのために、イメージ説明の一部は、他のパーツプロセ スのアドレス空間からロードできる (例 隣接するヒープの割り当て): •  DIB ヘッダ •  カラーパレット •  ピクセルデータ •  初期化されていないか、境界外のヒープメモリはパレットやピクセル データにより読み出される
  83. 83. Proof of concept •  ファイルを越えたパレットエントリーの8-bpp DIB を含む EMR_STRETCHBLTレコードを使用したPoC をハックした •  結果: 集められたバイトはイメージとして表示される •  同じ画像がIEの1行に3回表示されている: •  データはHTML5を使用して漏えいしたモジュールアドレスや他の機密情報などを読むことができる
  84. 84. デモ
  85. 85. ATMFD.DLLの監査 間に合わなかったので、カンファレンス後に公開する完全版のSlideDeckを見てく ださい J
  86. 86. GDI+ の監査
  87. 87. GDI+ は充分なターゲット •  GDI+ はEMF と EMF+の両方をサポートする •  多くの実装は独立しているが, フォーマットのいくつかのパーツはGDIのコー ドから来ている •  したがっていくつかのGDIバグはGDI+のクライアントに影響を与える •  最も主要な GDI+クライアントはMicrosoV Office 製品 •  もう1度EMFレコードハンドラの全体を手動で監査してみよう
  88. 88. 攻撃ポイント(アタックサーフェス)は容易に見つかる
  89. 89. 攻撃ポイント(アタックサーフェス)は容易に見つかる
  90. 90. いくつか特定のバグを見てみましょう
  91. 91. Impact: Write-what-where Record: All records opera[ng on DIBs Exploitable in: MicrosoV Office CVE: CVE-2016-3301 google-security-research entry: 824 Fixed: MS16-097, 9 August 2016 CVE-2016-3301
  92. 92. EMF中におけるRLE圧縮されたビットマップ •  前述のように、複数の EMF レコードはDIBを含む •  DIBは4から8ビットのRLEなどの簡単な方式で圧縮ができる •  ヘッダの biCompression フィールドに示される •  いくつかのハンドラのコードを読むことで、8-ビット RLEはGDI+でサ ポートされていることを見つけた •  RLE展開は歴史的にバグが多く見つかっている
  93. 93. コードへの到達 DecodeCompressedRLEBitmap CopyOnWriteBitmap::CopyOnWriteBitmap CopyOnWriteBitmap::Create GpBitmap::GpBitmap CEmfPlusEnumState::PlgBlt CEmfPlusEnumState::RenderBlt
  94. 94. DecodeCompressedRLEBitmap()の内部 •  2つの値は計算される: columns = abs(biHeight) bytes_per_row = abs(biWidth * (((biPlanes * biBitCount + 31) & 0xFFFFFFE0) / 8)) •  出力バッファはサイズからヒープが割り当てられる columns * bytes_per_row •  バッファ長を高度にコントロール •  RLE „プログラム”の解釈と実行が始まる
  95. 95. „最終行” 命令コード •  出力ポインタを次の行に移す (同じオフセットで)
  96. 96. „最終行” 命令コード •  GDI+では, 以下の様に実装: out_ptr += bytes_per_row; if (out_ptr > output_buffer_end) { // Bail out } •  境界チェックはあらゆる種類の範囲外のアクセスを防ぐために実装されている •  64ビットプラットフォーム上で正しく動作するように行われるが, 状態は本当に充 分なのか?
  97. 97. 不十分な検証 プロセスのアドレス空間の終わり 0xffffffff 出力バッファ
  98. 98. トリッキーなポインタ演算 •  非常に広いビットマップの場合、現在の出力ポインタからアドレス空間の終 わりまでの距離を走査線の幅よりも小さくすることができる •  式: out_ptr += bytes_per_row; その後のチェックが効果がなく, オーバーフローを引き起こす •  その結果, 出力ポインタを多くの制御可能なアドレスに設定することができる
  99. 99. 例 •  biWidth = 0x05900000 •  biHeight = 0x00000017 •  biPlanes = 0x0001 •  biBitCount = 0x0008 •  その結果、columns = 0x17 と bytes_per_row = 0x590000 •  合計バッファ サイズ = 0x7FF00000 (およそ 2 GB) •  配置アドレスの例: 0x7FFFF0020、最終位置: 0xFFEF0020
  100. 100. メモリアドレス空間レイアウト 0x00000000 0xFFFFFFFF 0x7FFF0020
  101. 101. メモリアドレス空間レイアウト (EOL #1) 0x00000000 0xFFFFFFFF 0x858F0020
  102. 102. メモリアドレス空間レイアウト (EOL #2) 0x00000000 0xFFFFFFFF 0x8B1F0020
  103. 103. メモリアドレス空間レイアウト (EOL #3-22) 0x00000000 0xFFFFFFFF …
  104. 104. メモリアドレス空間レイアウト (EOL #23) 0x00000000 0xFFFFFFFF 0xFFEF0020
  105. 105. メモリアドレス空間レイアウト (EOL #24) 0x00000000 0xFFFFFFFF 0x057F0020
  106. 106. (3434.194): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0011015e ebx=ffef0020 ecx=000000fe edx=057f01cc esi=057f0020 edi=0011a6f0 eip=6b090e5a esp=0037f290 ebp=0037f2ac iopl=0 nv up ei pl nz na pe cy cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010207 gdiplus!DecodeCompressedRLEBitmap+0x195: 6b090e5a 8816 mov byte ptr [esi],dl ds:002b:057f0020=?? 0:000> kb ChildEBP RetAddr Args to Child 0037f2ac 6b091124 057f0020 cc11012c 0037f2cc gdiplus!DecodeCompressedRLEBitmap+0x195 0037f6f4 6b092c7a 001100f8 0011012c 00000000 gdiplus!CopyOnWriteBitmap::CopyOnWriteBitmap+0x96 0037f708 6b0932cc 001100f8 0011012c 00000000 gdiplus!CopyOnWriteBitmap::Create+0x23 0037f720 6b0c1e8b 001100f8 0011012c 00000000 gdiplus!GpBitmap::GpBitmap+0x32 0037f804 6b0c7ed1 0000004f 00143a30 0000a67c gdiplus!CEmfPlusEnumState::PlgBlt+0x92 …
  107. 107. サマリー •  要件: PAEが有効な32-ビットプロセス •  4 GBアドレス空間全部をプログラムに使用可能にする必要がある •  結果: どこに何を書くという条件は、„どこ”以上に高度なコントロールが必要 •  特定の値を達成させるだけでなく、上書きされた領域は元の出力バッファ以下の必要あり •  エクスプロイトの確実さはイメージがロードされた時のアドレス空間の状態に強く 依存する
  108. 108. Impact: Heap-based buffer overflow Record: EMR_EXTTEXTOUTA, EMR_POLYTEXTOUTA Exploitable in: MicrosoV Office CVE: CVE-2016-3304 google-security-research entry: 828 Fixed: MS16-097, 9 August 2016 CVE-2016-3304
  109. 109. ExtTextOutA() と PolyTextOutA()
  110. 110. EMF レコード内のDx 配列
  111. 111. 関数の簡単なバグ •  Dx配列はN個の要素であると想定され、Nは表示されているキャラク タの数 •  以下はレコードサイズの検証チェック: if (record_size - offString >= nChars && (!nChars || record_size - 4 >= record->emrtext.offDx)) { // Validation passed, continue processing the record. } •  何かが欠けていない?
  112. 112. 関数の些細なバグ •  コードはDx配列が4バイトを保持するかをチェック •  4 × N バイトを保持することができれば本当に検証をすべき •  典型的なヒューマンエラーの整合性チェック •  だから何? 入力値検証の問題で外の境界を読み出すだけでは? •  はい、エクストラのロジックのためにコードを呼び出さなければ
  113. 113. 拡張機能ロジック •  MultiByteToWideChar()を使用して、stringをwide-charへ変換 •  コードページは最後に選択したフォントで指定される •  全ての文字列が変換されたとき, 通常 CEmfPlusEnumState::PlayExtTextOut() が呼び出される •  しかしそうでない場合は…
  114. 114. DBCS (ダブルバイト文字セットの)扱い •  1バイト以上で構成する文字もサポート •  以下の様に取り扱いが実装されている: •  EMF レコードの正確なコピーが (同じサイズに)配置される •  Dx配列の項目はオリジナルのレコードから新しいものに書き換えられる, „先 行バイト” (IsDBCSLeadByteEx() がTRUEを返す)のエントリを省略 •  新しいレコードが以降通常として処理される
  115. 115. コードパスに到達 •  DBCSをサポートするコードページのフォントが最初に選択されなければならない •  典型的なものは CJK (中国語,日本語, 韓国語) のコードページ, 例として SHIFTJIS_CHARSET •  その後,少なくとも1つの„lead byte”が含まれる影響を受けたレコードの1つは使用されなけ ればならない •  その結果、境界を越えて他の配置から読み出す典型的なヒープベースのオー バーフローになる •  heap massagingにより,制御した上書きを可能にする
  116. 116. ヒープオーバーフローの仕組み オリジナルのレ コード 新しいレコード ヒープ領域
  117. 117. ヒープオーバーフローの仕組み オリジナルのレ コード 新しいレコード ヒープ領域 Dx配列の書き換え
  118. 118. (2a8c.2bd8): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000000 ecx=772336ab edx=0022cb85 esi=03bd0000 edi=1171ffc0 eip=7728e815 esp=0022cdd8 ebp=0022ce50 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200206 ntdll!RtlReportCriticalFailure+0x29: 7728e815 cc int 3 0:000> kb ChildEBP RetAddr Args to Child 0022ce50 7728f749 c0000374 772c4270 0022ce94 ntdll!RtlReportCriticalFailure+0x29 0022ce60 7728f829 00000002 64dc1326 03bd0000 ntdll!RtlpReportHeapFailure+0x21 0022ce94 7724ab46 0000000c 03bd0000 1171ffc0 ntdll!RtlpLogHeapFailure+0xa1 0022cf84 771f3431 00000258 00000260 03bd00c4 ntdll!RtlpAllocateHeap+0x7b2 0022d008 695071ec 03bd0000 00000000 00000258 ntdll!RtlAllocateHeap+0x23a 0022d01c 6951bbf1 00000258 116b5104 03bdd558 gdiplus!GpMalloc+0x16 0022d030 69557185 116b50e0 116b50e0 03bdd558 gdiplus!GpGraphics::Save+0x11 0022d4b0 69557bdc 116b50e0 116b5104 116b30d8 gdiplus!CEmfPlusEnumState::PlayExtTextOut+0xda 0022d4ec 69557f25 00000053 03bdae00 00006044 gdiplus!CEmfPlusEnumState::ExtTextOutA+0x136 0022d500 695286ca 00000053 00006044 0d67b568 gdiplus!CEmfPlusEnumState::ProcessRecord+0x13b 0022d51c 69528862 00000053 00000000 00006044 gdiplus!GdipPlayMetafileRecordCallback+0x6c 0022d544 768155f4 9d211b17 0d567180 0d67b568 gdiplus!EnumEmfDownLevel+0x6e 0022d5d0 6952aa36 9d211b17 403581b3 695287f4 GDI32!bInternalPlayEMF+0x6a3
  119. 119. Impact: Heap memory disclosure Record: All records handling DIBs Exploitable in: MicrosoV Office Online CVE: ? google-security-research entry: 825, 829 Fixed: MS16-???, 11 October 2016 (?) GDI+ の情報漏えいバグ
  120. 120. GDI+ vs DIB •  GDIとは異なり, GDI+ はビットマップの取り扱いに起因する情報漏えいバ グを避けなかった •  具体的に: 1.  „ビットマップの終わり”のマーカーで始まる、RLE圧縮されたビットマップのデータ ストリームでは , 画像の出力バッファ全体が初期化されていない (ジャンクヒープ データが含まれる) 2.  ビットマップパレットが完全にEMFレコードに収まるようになっているかはチェックさ れない
  121. 121. はっきりと目に見えるバグ •  PoCコードのピクチャをwordに読み込ませると, はっきりとジャンク データがピクセルとして表示されているのが見える
  122. 122. リモートからの悪用可能性? •  ピクセルが何かに戻せるのでもないので、ヒープメモリを表示することはそんな にシリアスな状況ではない。 •  インタラクティブに出来ないため、バグの唯一のターゲットはOfficeプログラム •  MicrosoVに報告し、深刻度の評価と、攻撃につながる可能性についての評価を 待った •  MSRC はこの事象を „vNext”としてクローズした (毎月のパッチでは修正せず, 次 期バージョンなどのタイミングで修正)
  123. 123. 深刻度の評価 •  これは私自身が考えていた露呈問題の理解と一致しており, 決定に同意 した •  P0 バグの #825 と #829 はそれぞれ7/26と8/9に解決とした •  8月の始めに, Ivan Fratric がチャットで GDI+/EMFのバグはOffice Online に おいてリモートから攻撃につながる可能性があることを伝えてきた •  私はこのプログラムの存在を知らなかった •  攻撃可能ではなかったが,特にGDI+のメモリー漏えいのバグは興味深い •  EMF イメージはドキュメント内に挿入できないが, .docxには埋め込みEMFとして可能
  124. 124. Office オンライン •  数週間前にチェックをしたら…
  125. 125. Office オンライン •  EMFイメージは毎回異なったレンダリングがされる •  MicrosoVのサーバのレンダリングプロセスからリモートのメモリを読み出 せる •  MSRCに再考を求めるために新しい情報を提供 •  彼らはOffice Online のシナリオは以前には考慮されていなかった, それは 修正に値するバグとされた •  10月の定例パッチまでに修正される必要があった
  126. 126. VMware Workstadonのハック
  127. 127. プリントスプールのEMF •  EMF ファイルはプリントスプールに頻繁に使われる •  これはプリンタドライバ (およびその他関連ソフトウェア)の形式で, フォーマットに起因する攻撃ベクタとして使用される •  1つのターゲットとしてVMware Worksta[onを選定
  128. 128. 仮想プリンタ •  これは仮想マシンからホストを通してドキュメントの印刷を可能にする昨日 (基本的には プリンタの共有) •  実現可能なVM回避の攻撃ベクタ •  T私の知る限りでは, 2015年まではデフォルトで有効であったが, 現在は有効ではない (Kostya Kortchinskyが報告したバグが役立った) •  いまだ頻繁に使用するオプション
  129. 129. 構造 VM #3 VM #2 VM #3 poc.exe Virtual Machines vmware.exe COM1 vprintproxy.exe Windows 名前付きパイプ
  130. 130. 構造 •  攻撃プロセスは vprintproxy.exe が稼働するホスト •  ゲストシステムで非特権プロセスによって送信され、ほぼそのままのデータ を受信します •  通信のチャンネル •  データは EMFSPOOL ファイルの形式で送られる •  EMFと同様に, 追加オプションを指定して、様々な形式のフォントを埋め込む ことができる
  131. 131. TPView •  特に, 最も興味深いEMF処理は TPview.dllで行われる •  その他プリンタに関するライブラリは, すべてサードパーティのThinPrintで開 発がされていると思われる •  いくつかのレコードタイプの特殊処理は, GDIに処理が戻る •  全ては簡単なバグではあったが, Kostya は(ほぼ)全てを見つけた! •  他を見ていたら, ダブル・フリーと out-of-bounds memset()を見つけた, それ らは (問題 #848 と #849)に含まれる
  132. 132. JPEG2000 デコード •  完全に未調査であった最後のカスタムEMFレコード •  ID = 0x8000 •  デバッグ文字列に基づいて,それらは JPEG2000のデコードに関してのもので ある •  JPEG2Kの専門家でもないので, コードは手動検査にとっては便利で はないように見えた •  ファジングしてみる?
  133. 133. ファジングによるアプローチ •  ベストなファジング: Linux上で, スケールで, AddressSani[zerを使用してカバレッ ジフィードバックを待つ •  いくつかの調査後, JPEG2000デコーダーは別のベンダーのLuraTechによって開 発されていることが分かった •  商用ライセンス, 自由に利用できないソースコード •  そのため, 我々はVMware Worksta[onでラップされた TPview.dll で止まった? •  継続可能だが, より複雑で, 遅くて, 先進的でない
  134. 134. さらなる調査 •  さらなる調査で, 同じベンダーがフリーウェアとして人気のIrfanViewプログ ラムの用にJPEG2000のデコードプラグインを提供して居ることを見つけた •  JPEG2000.DLL. •  大まかな分析により同じか非常に近いコードをベースとしていることが分かった •  プラグインインターフェースを使用することは非常に簡単で, 次の定義に 似ている
  135. 135. HGLOBAL ReadJPG2000(IN PCHAR lpFilename, IN DWORD dwUnknown, OUT PCHAR lpStatus, OUT PCHAR lpFormat, OUT LPDWORD lpWidth, OUT LPDWORD lpHeight);
  136. 136. それにより... •  これのおかげで, 我々はVMWareを起動することなく, Windows上の 単一プロセスの実装に対しファジングテストを簡単に実施できた •  DLLをロードするラッパープログラムと関連する関数の呼び出しは <50 LOC long •  しかし, 私はこれらがLinuxに実装されていることを好むだろうか...
  137. 137. Linux上でのファジングDLL •  なぜない, 本当に? •  望ましいベースアドレスは 0x10000000, アドレス空間で利用可能 •  再配置は必要ではない; セクションはそれぞれのアクセス権限があるところにマップされるべき •  その他のアクション: •  必要なインポートを解決 •  エクスポートされた関数のアドレスを取得 •  デコードを実行するためにそれを呼び出す •  動作するはず!
  138. 138. インポートの解決 •  インポートテーブルは面倒なポイントでもある •  WinAPI 関数はLinux上では提供されていない •  DLL インポート元は ADVAPI32, KERNEL32, MSVCRT, SHELL32 と USER32 •  Cランタイムのインポートは直接libcにリダイレクトされる •  他の全てのものは書き換えられるか少なくともスタブアウトしなければならな い
  139. 139. KERNEL32 imports •  デコードに使われる3つの WinAPI 関数: GlobalAlloc, GlobalLock and GlobalUnlock: void *GlobalAlloc(uint32_t uFlags, uint32_t dwBytes) __attribute__((stdcall)); void *GlobalAlloc(uint32_t uFlags, uint32_t dwBytes) { void *ret = malloc(dwBytes); if (ret != NULL) { memset(ret, 0, dwBytes); } return ret; } void *GlobalLock(void *hMem) __attribute__((stdcall)); void *GlobalLock(void *hMem) { return hMem; } bool GlobalUnlock(void *hMem) __attribute__((stdcall)); bool GlobalUnlock(void *hMem) { return true; }
  140. 140. libc のインポートが無いとき •  再実装されなければならない、2つの MSVCRT-固有のインポートが 見つかった: long long _ftol(double val) __attribute__((cdecl)); long long _ftol(double val) { return (long long)val; } double _CIpow(double x, double y) __attribute__((cdecl)); double _CIpow(double x, double y) { return pow(x, y); }
  141. 141. 動いた! $ ./loader JPEG2000.dll test.jp2 [+] Successfully loaded image (9b74ba8), format: JPEG2000 - Wavelet, width: 4, height: 4
  142. 142. ファジングの実行 •  内部的に利用可能なJPEG2000の入力ファイルコーバスを使用 •  ミューテーションストラテジのレートは成功/失敗が50/50になるように 調整 •  数日間ファジングを実行させて, そして... •  ... 186 のクラッシュとユニークなスタックトレースが見つかった
  143. 143. クラッシュの再現 •  クラッシュはプラグインDLL上のものであって、まだVMware Worksta[onの ものではない点に注意 •  vprintproxy.exe はとても便利に使える: 名前付きパイプを作成しCOM1に 書かれているデータを正確に読み出すことができる •  もう1度、我々は実際のVMを起動せずにテストケースをチェックすることができる •  ページヒープはよりよいバグの検出と重複の排除を可能にする
  144. 144. 最終結果 InstrucRon Reason add [eax+edx*4], edi Heap buffer overflow cmp [eax+0x440], ebx Heap out-of-bounds read cmp [eax+0x8], esi Heap out-of-bounds read cmp [edi+0x70], ebx Heap out-of-bounds read cmp [edi], edx Heap out-of-bounds read cmp dword [eax+ebx*4], 0x0 Heap out-of-bounds read cmp dword [esi+eax*4], 0x0 Heap out-of-bounds read div dword [ebp-0x24] Division by zero div dword [ebp-0x28] Division by zero fld dword [edi] NULL pointer dereference idiv ebx Division by zero idiv edi Division by zero imul ebx, [edx+eax+0x468] Heap out-of-bounds read mov [eax-0x4], edx Heap buffer overflow mov [ebx+edx*8], eax Heap buffer overflow mov [ecx+edx], eax Heap buffer overflow mov al, [esi] Heap out-of-bounds read mov bx, [eax] NULL pointer dereference mov eax, [ecx] NULL pointer dereference mov eax, [edi+ecx+0x7c] Heap out-of-bounds read InstrucRon Reason mov eax, [edx+0x7c] Heap out-of-bounds read movdqa [edi], xmm0 Heap buffer overflow movq mm0, [eax] NULL pointer dereference movq mm1, [ebx] NULL pointer dereference movq mm2, [edx] NULL pointer dereference movzx eax, byte [ecx-0x1] Heap out-of-bounds read movzx eax, byte [edx-0x1] Heap out-of-bounds read movzx ebx, byte [eax+ecx] Heap out-of-bounds read movzx ecx, byte [esi+0x1] Heap out-of-bounds read movzx ecx, byte [esi] Heap out-of-bounds read movzx edi, word [ecx] NULL pointer dereference movzx esi, word [edx] NULL pointer dereference push dword [ebp-0x8] Stack overflow (deep / infinite recursion) push ebp Stack overflow (deep / infinite recursion) push ebx Stack overflow (deep / infinite recursion) push ecx Stack overflow (deep / infinite recursion) push edi Stack overflow (deep / infinite recursion) push esi Stack overflow (deep / infinite recursion) rep movsd Heap buffer overflow, Heap out-of-bounds read
  145. 145. 最終結果 •  39のユニークなインストラクションでクラッシュが発生 •  多くのものはそんなに正確なメトリックのところでなく memcpy()のような一般 的の機能の様々なポイントで発生 •  簡単に分類: 18 の低深刻度, 15 中深刻度, 6 高深刻度 •  6月15日にVmwareに報告された •  9月 13日 (90 日以内)にVMSA-2016-0014 として修正された
  146. 146. 結論
  147. 147. 結論 •  メタファイルは複雑で興味深いファイルで、研究の価値があるもの •  様々な攻撃ベクタが有効 •  システムAPIについていろいろと教えてくれる (i.e. NamedEscapeインター フェース) •  いつものことだが, 古くて曖昧なフォーマット/実装 – バグハンター向け •  以前の成果からのインスピレーションにももっと目を向けよう •  適材適所 – 手動のコード監査 vs ファジング
  148. 148. ありがとう! @j00ru http://j00ru.vexillium.org/ j00ru.vx@gmail.com

×