jurczyk windows metafile_pacsec_jp3

150
Windows メタファイル EMF攻撃ポイントと最近の脆弱性の分析 Mateusz “j00ru” Jurczyk PacSec, Tokyo 2016

Upload: pacsecjp

Post on 08-Jan-2017

464 views

Category:

Internet


5 download

TRANSCRIPT

Page 1: Jurczyk windows metafile_pacsec_jp3

Windows メタファイル EMF攻撃ポイントと最近の脆弱性の分析

Mateusz“j00ru”Jurczyk

PacSec,Tokyo2016

Page 2: Jurczyk windows metafile_pacsec_jp3

PS> whoami

• GoogleのProjectZero所属

• 脆弱性の研究とソフトウェアエクスプロイトに興味がある低レイヤー

のセキュリティ研究者

• hAp://j00ru.vexillium.org/

• @j00ru

Page 3: Jurczyk windows metafile_pacsec_jp3

アジェンダ

• Windows メタファイル入門、GDIデザイン、攻撃ベクタ

• ハック対象:

•  InternetExplorer(GDI)

• WindowsKernel(ATMFD.DLL)

•  MicrosoVOffice(GDI+)

•  VMwarevirtualiza[on(プリントスプール)

• 結論

Page 4: Jurczyk windows metafile_pacsec_jp3

Windows GDI & メタファイル入門

Page 5: Jurczyk windows metafile_pacsec_jp3

Windows GDI

•  GDIはGraphicsDeviceInterface(グラフィックス・デバイス・インターフェイス)の略

•  ユーザーモードアプリケーションで、グラフィックや整形されたテキストをビデオ

ディスプレイやプリンターへの出力を可能にする

•  システムAPIの大半を占める(約300のドキュメント化された機能)

•  初期のOSの頃から存在(1985年にリリースされたWindows1.0から)

•  最も古いサブシステムの1つで、31年経った今でも大半は元のコードのまま稼働している

•  偶然にも(?)もっともバグが多い構成要素の1つである

Page 6: Jurczyk windows metafile_pacsec_jp3

どのように描画するか

1.  デバイスコンテキスト へのハンドル(HDC)をつかむ

•  様々なグラフィカル設定(ペン、ブラシ、パレットなど)の永続的なコンテナを

認識する

•  スクリーン(もっとも典型的)、プリンター、メタファイルへの描画で使用可能

•  最も簡単な例:

HDChdc=GetDC(NULL);

(画面全体のためにHDCを取得)

Page 7: Jurczyk windows metafile_pacsec_jp3

どのように描画するか

2.  描画機能を使用

Ellipse(hdc,100,100,500,300); RoundRect(hdc,100,100,500,500,100,100);

Page 8: Jurczyk windows metafile_pacsec_jp3

Windows GDI – 簡易化したアーキテクチャ

app1.exe app3.exe app4.exeapp2.exe

GDI+(gdiplus.dll)

User-modeGDI(gdi32.dll)

Kernel-modeGDI(win32k.sys)

NTOSKernel PrinterDrivers FontDriversDisplayDrivers

ring-3

ring-0

Page 9: Jurczyk windows metafile_pacsec_jp3

ユーザーモードとカーネルAPIマッピング

大半のユーザーモードGDI関数は直接対応するカーネルAPIを持って

いる:

GDI32.DLL win32k.sysAbortDoc NtGdiAbortDoc

AbortPath NtGdiAbortPath

AddFontMemResourceEx NtGdiAddFontMemResourceEx

AddFontResourceW NtGdiAddFontResourceW

AlphaBlend NtGdiAlphaBlend

... ...

Page 10: Jurczyk windows metafile_pacsec_jp3

Windows メタファイル

コアアイデア:

GDI関数呼び出しを記述するレコードのリストとして

イメージを格納する.

Page 11: Jurczyk windows metafile_pacsec_jp3

Windows メタファイル

• 長所:•  GDI関数が与えられたパラメータで呼び出された時だけ、ラスタライズ処理の計算は

ほとんど必要とされない

•  GDIが再現可能な画像を操作するための公式な方法を提供

•  ベクター形式、ラスター形式また両方の形式として動作する

• 短所:•  サポートされているグラフィックのGDI操作が外部に完全に実装されていない場合

は、Windows上でのみ動作する

Page 12: Jurczyk windows metafile_pacsec_jp3

First version: WMF

• 最初のメタファイル (WMF=WindowsMetaFiles).

•  1990年のWindows3.0で導入された

•  GDIそれ自体のほどではないが、同じくらい古典的

• はじめてドキュメント化されたのはWindows3.1SDK(1994年,volume4)

•  改訂され、より完全な仕様は2006年にリリース、それ以来メンテされ続けている

•  全てのレコードや構造はMS-WMFドキュメントに記載されている

Page 13: Jurczyk windows metafile_pacsec_jp3

WMF files – サポートされている60のAPI関数 AnimatePaletteArcBitBltChordCreateBrushIndirectCreateDIBPatternBrushCreateFontIndirectCreatePaletteCreatePatternBrushCreatePenIndirectDeleteObjectEllipseEscapeExcludeClipRectExtFloodFillExtTextOutFillRgnFloodFillFrameRgnIntersectClipRectInvertRgn

LineToMoveToExOffsetClipRgnOffsetViewportOrgExOffsetWindowOrgExPaintRgnPatBltPiePolygonPolylinePolyPolygonRealizePaletteRectangleResizePaletteRestoreDCRoundRectSaveDCScaleViewportExtExScaleWindowExtExSelectClipRgnSelectObject

SelectPaletteSetBkColorSetBkModeSetDIBitsToDeviceSetMapModeSetMapperFlagsSetPaletteEntriesSetPixelSetPolyFillModeSetROP2SetStretchBltModeSetTextAlignSetTextCharacterExtraSetTextColorSetTextJustificationSetViewportOrgExSetWindowExtExSetWindowOrgExStretchBltStretchDIBitsTextOut

Page 14: Jurczyk windows metafile_pacsec_jp3

一目見ただけでも興味深そうなもの AnimatePaletteArcBitBltChordCreateBrushIndirectCreateDIBPatternBrushCreateFontIndirectCreatePaletteCreatePatternBrushCreatePenIndirectDeleteObjectEllipseEscapeExcludeClipRectExtFloodFillExtTextOutFillRgnFloodFillFrameRgnIntersectClipRectInvertRgn

LineToMoveToExOffsetClipRgnOffsetViewportOrgExOffsetWindowOrgExPaintRgnPatBltPiePolygonPolylinePolyPolygonRealizePaletteRectangleResizePaletteRestoreDCRoundRectSaveDCScaleViewportExtExScaleWindowExtExSelectClipRgnSelectObject

SelectPaletteSetBkColorSetBkModeSetDIBitsToDeviceSetMapModeSetMapperFlagsSetPaletteEntriesSetPixelSetPolyFillModeSetROP2SetStretchBltModeSetTextAlignSetTextCharacterExtraSetTextColorSetTextJustificationSetViewportOrgExSetWindowExtExSetWindowOrgExStretchBltStretchDIBitsTextOut

Page 15: Jurczyk windows metafile_pacsec_jp3

WMF: まだまだある!

• このフォーマットは、GDI関数では直接の対応をしていない多くのレ

コードをサポートしている.

•  ヘッダ情報を持つmetadata

•  埋め込み EMF

•  プリンタードライバー/出力デバイスを直接扱うレコード

•  ファイル終端マーク

•  ...

Page 16: Jurczyk windows metafile_pacsec_jp3

WMF: まだまだある!

• 大抵は、最も興味深いレコードが2つのセクションからみつかる:

Page 17: Jurczyk windows metafile_pacsec_jp3

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(Tableobject: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){Tableobject:2=OBJ_BRUSH.(BS_SOLID)}R0013:[037]META_SELECTOBJECT(s=12){Stockobject: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)}...

Page 18: Jurczyk windows metafile_pacsec_jp3

WMF: 今なおとても時代遅れなまま

• それ自体がすでに複雑であるが、そのフォーマットは現代的な使用

法に対して考え抜かれたものになることはなかった

• GDIにサポートされているが故に、いくつかのクライアントの一部に使

用されている(例: MicrosoVOffice、ペイント、いくつかのWindows標

準アプリケーションなど)

• ここ10年かそれ以上、実世界でのユースケースを忘れ去られていた

Page 19: Jurczyk windows metafile_pacsec_jp3

WMF: 使う気がおきない

• マイクロソフトでさえ、もう使うべきではない多くの理由をあげている:

Page 20: Jurczyk windows metafile_pacsec_jp3

次に来たもの: EMF (Enhanced MetaFiles:拡張メタファイル)

• すでに1993年に、マイクロソフトはEMFと呼ばれる改良版のイメージフォー

マットをリリース

• 公式のMS-EMF仕様としてドキュメント化されている

• 多くの方法でWMFを上回る:

•  16ビットではなく、32ビットのデータ/オフセット長を使用

•  デバイスに依存しない

•  古いレコードとの下位互換性を維持しながら、いくつかの新しいGDIコールをサポート

Page 21: Jurczyk windows metafile_pacsec_jp3

拡張メタファイル – 例

...R0121:[039]EMR_CREATEBRUSHINDIRECT(s=24){ihBrush(2),style(1=BS_NULL)}R0122:[037]EMR_SELECTOBJECT(s=12){Tableobject: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){Tableobject: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}...

Page 22: Jurczyk windows metafile_pacsec_jp3

EMF: 一目見ただけでも興味深いレコード

Page 23: Jurczyk windows metafile_pacsec_jp3

EMF: 一目見ただけでも興味深いレコード

Page 24: Jurczyk windows metafile_pacsec_jp3

EMF: 一目見ただけでも興味深いレコード

Page 25: Jurczyk windows metafile_pacsec_jp3

EMF: 現在のサポート

• WMFのわずかに3年新しいものではあるが、EMFは今日まで使用さ

れている

•  メインストリームの画像フォーマットではないが、有効な攻撃ベクタ

• さまざまな攻撃ベクタ:

• Win32GDIクライアント–代表はInternetExplorer

•  GDI+クライアント–代表はMicrosoVOffice

•  プリンタードライバー、仮想化技術で使われるものも含む

Page 26: Jurczyk windows metafile_pacsec_jp3

ツールセット – 検査 (EMFexplorer)

Page 27: Jurczyk windows metafile_pacsec_jp3

ツールセット – 検査 (MetafileExplorer)

Page 28: Jurczyk windows metafile_pacsec_jp3

ツールセット – リーディング & ライティング (pyemf) #!/usr/bin/envpythonimportosimportpyemfimportsysdefmain(argv):iflen(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)

Page 29: Jurczyk windows metafile_pacsec_jp3

最新: EMF+

•  GDIはすべて基本的な機能を備えているが、多くの複雑な機能に欠ける

(アンチエイリアシング、浮動小数点座標、JPG/PNGのサポートなど)

• WIndowsXPは2001年にGDI+と呼ばれる高度なライブラリーを導入

•  大部分はGDI(gdi32.dll)の上に、ユーザーモードgdiplus.dll ライブラリが作られた

•  C++や.NET向けに高レベルのインターフェースを提供するため、容易に使用可能

•  GDI+はそれ自体C++で書かれているため、典型的なメモリー破損バグが未だに存在

Page 30: Jurczyk windows metafile_pacsec_jp3

最新: EMF+

•  新しいインターフェースがあるため、新しい画像フォーマットとそのシリアライズさ

れた呼び出しが必要とある

•  EMF+にあいさつ!

•  基本的にはEMFと同じだが、GDI+の呼び出しを表す

•  2種類ある:EMF+Onlyと EMF+Dual

•  „Only”は専用のGDI+レコードが含まれ、そしてGDI+でのみ表示することができる

•  „Dual”はGDI/GDI+クライアント両方と互換性があり、2つのレコードセットが保存されている

Page 31: Jurczyk windows metafile_pacsec_jp3
Page 32: Jurczyk windows metafile_pacsec_jp3

Windowsでのフォーマットと実装

• 考慮すべきは3つのフォーマット:WMF,EMF,EMF+

•  3つのライブラリ:GDI,GDI+,MF3216

•  vMF3216.DLLは1つの重要な機能を提供するシステムライブラリ:

ConvertEmfToWmf

•  Windowsのクリップボード内のWMF/EMFフォーマット間の自動変換する際に使用

•  „Synthesized”formatsCF_METAFILEPICTと CF_ENHMETAFILE

•  ここにはバグは無かった.L

Page 33: Jurczyk windows metafile_pacsec_jp3

Windowsでのフォーマットと実装

Library Supportedformats

GDI WMF,EMF

GDI+ WMF,EMF,EMF+

MF3216 EMF

今回の話では、最も(興味深い)問題が見つかったEMFに対する

監査とエクスプロイトにフォーカスする

Page 34: Jurczyk windows metafile_pacsec_jp3

攻撃シナリオ

•  全ての場合において、メタファイルは対応するDLLでレンダラープロセスのユーザモードコンテキスト

として処理される

•  GDI,GDI+,MF3216は全てのレコード入力に対し繰り返しGDI/GDI+の呼び出しに変換する

•  メモリ破損のバグは、そのコンテキストで任意のコード実行につながる

•  重要:メタファイルはレンダラーのGDIコンテキストを直接操作する

•  プロセスの代わりとして、作成、削除、変更や、さまざまなGDIオブジェクトを使用することができる

•  理論的には、自身のオブジェクトにのみアクセスすべきであり、自己完結である必要がある

•  しかし、実装のバグはプログラムによって使用される外部グラフィックスオブジェクトへのアクセスを可能にする

•  „権限昇格”の特異なケース

Page 35: Jurczyk windows metafile_pacsec_jp3

攻撃シナリオ: GDI による権限昇格

renderer.exeGDIobjects EMF#2GDIobjects EMF#3GDIobjects

EMF#1file

EMF#1GDIobjects

GDIプロセス

EMF#2file EMF#3file

セキュリティ境界

Page 36: Jurczyk windows metafile_pacsec_jp3

攻撃シナリオ: GDI による権限昇格

renderer.exeGDIobjects EMF#2GDIobjects EMF#3GDIobjects

EMF#1file

EMF#1GDIobjects

GDIプロセス

セキュリティ境界

Page 37: Jurczyk windows metafile_pacsec_jp3

メタファイルのバグのタイプ

1.   メモリ破損のバグ

•  バッファオーバーフローなど特定レコードの誤った取り扱いによるもの

•  レンダリングのいずれかのタイプのエクスプロイトの可能性

•  影響:典型的なリモートからのコード実行(RCE)

2.   メモリ漏えいのバグ

•  初期化されていないレンダリング、境界外のヒープメモリーをイメージとして扱う

•  画像のみを表示するコンテキストでは裏を読むことができる (Webブラウザ、リモートレンダラー)

•  影響:情報漏えい(秘密情報を盗む、ASLRの突破など)

3.   OSとGDIオブジェクトの誤った管理による不正な相互作用

•  影響、悪用可能性=???、バグの種類による

Page 38: Jurczyk windows metafile_pacsec_jp3

始めよう!

• 今年の初めから、利用可能なEMFの実装について監査を始めた

• 結果として、MicrosoVから 10のCVE、VMWareから3つのCVEを見つ

けた (実際の数十のバグをカバーする)

• 根本原因と、最も面白いエクスプロイトについてもう少し深く見よう

•  レイトして32-bitWindows7に基づいて示しているが、ほとんどの調査内容は

Windows10までの両方のビットバージョンにも適用できる

Page 39: Jurczyk windows metafile_pacsec_jp3

GDIの監査

Page 40: Jurczyk windows metafile_pacsec_jp3

入門

• 一般的なアイディアとして、どんな機能が実装され、どんなタイプの

バグが過去に見つかったのか、先行技術を確認することは理にか

なっている

•  „wmf脆弱性”での検索でただ一つが見つかる:

SetAbortProcのバグ!

Page 41: Jurczyk windows metafile_pacsec_jp3

SetAbortProc WMF バグ (CVE-2005-4560)

•  2005/12/27に見つかり、 2006/1/5に修正された

• 致命的なバグであり、GDIを使ったエクスプロイトを動かすと100%確実に

RCEが出来た (例えばInternetExplorer上)

•  „Windowsメタファイルの 脆弱性”と呼ばれPwnieAward2007を受賞

• メモリー破損は関係無く、WMFの文書化された機能を使用

• なにがバグだった?

Page 42: Jurczyk windows metafile_pacsec_jp3

GDIのAPI...

func[onpointer

Page 43: Jurczyk windows metafile_pacsec_jp3

... そして WMF 側では

Page 44: Jurczyk windows metafile_pacsec_jp3

本質的には...

...規約自体の呼び出しをサポート:

SetAbortProc(hdc,(ABORTPROC)"controlleddata");

そしてその後呼び出される関数インタ

仕様としてのコード実行

Page 45: Jurczyk windows metafile_pacsec_jp3

学んだこと

1.  フォーマットは(非)公式にプロキシを呼び出し、興味深い/危険な

APIを呼び出し、そのためそれぞれの機能やパラメータは安全でな

い振る舞いをしないかチェックをする必要がある

2.  WMFのハンドリングは大きなスイッチ/ケースで起こる

gdi32!PlayMetaFileRecord

Page 46: Jurczyk windows metafile_pacsec_jp3
Page 47: Jurczyk windows metafile_pacsec_jp3

EMF バグとは?

•  „emfvulnerability”の検索でより多彩な結果が見つかる

• 最新のもの:HosseinLoViによる„YetAnotherWindowsGDIStory”

•  MS15-035の一部として2015年4月に修正、CVE-2015-1645が割り当てられた

•  レコードの1つ(SETDIBITSTODEVICE) の入力である „size”の未検証による、

ヒープベースのバッファオーバーフロー

•  EMFセキュリティを見るには大部分はインスピレーション(が必要)

Page 48: Jurczyk windows metafile_pacsec_jp3

学んだこと

•  EMFレコードを再生するためのメインファンクション gdi32!

PlayEnhMetaFileRecord

• 各レコードタイプはそれぞれ2つの独自のクラスをもっている:

•  ::bCheckRecord()–レコードの内部整合性と正確さをチェック

•  ::bPlay()–レコード内に示されたアクションを実行

Page 49: Jurczyk windows metafile_pacsec_jp3

GDI32 ::bCheckRecord array

Page 50: Jurczyk windows metafile_pacsec_jp3

GDI32 ::bPlay array

Page 51: Jurczyk windows metafile_pacsec_jp3

ここからが出発点

Page 52: Jurczyk windows metafile_pacsec_jp3

Impact: FileExistenceInforma[onDisclosure

Record: EMR_CREATECOLORSPACE,EMR_CREATECOLORSPACEW

Exploitablein: InternetExplorer

CVE: CVE-2016-0168

google-security-researchentry: 722

Fixed: MS16-055,10May2016

CVE-2016-0168

Page 53: Jurczyk windows metafile_pacsec_jp3

マイナーバグ #1 in EMR_CREATECOLORSPACEW

• 小さいけど明らかなバグを見ることでコードの品質がすぐに認識できた

•  MRCREATECOLORSPACEW::bCheckRecord()レコードのサイズが 0x50バイ

ト以上であるこをとチェック:.text:7DB01AEFmoveax,[esi+4].text:7DB01AF2cmpeax,50h.text:7DB01AF5jbshortloc_7DB01B1E

• その後すぐに、オフセット0x25Cの.cbDataフィールドを読み込む:.text:7DB01AF7movecx,[esi+25Ch]

• その結果:0x20Cバイトの範囲外を読み込む

Page 54: Jurczyk windows metafile_pacsec_jp3

マイナーバグ #2 in EMR_CREATECOLORSPACEW

• その後、無効オフセット0x25Cの.cbDataはレコード長のチェックに使われ

る:.text:7DB01AF7movecx,[esi+25Ch].text:7DB01AFDaddecx,263h.text:7DB01B03andecx,0FFFFFFFCh.text:7DB01B06cmpeax,ecx.text:7DB01B08jashortloc_7DB01B1E

• 上記は以下の様に変換できる:if(...&&record.length<=((record->cbData+0x263)&~3)&&...){

//Recordvalid.

}

Page 55: Jurczyk windows metafile_pacsec_jp3

マイナーバグ #2 in EMR_CREATECOLORSPACEW

•  2つの問題がここに:

1.  明らかな整数オーバーフローにより、大きな.cbDataがチェックを通過

する

2.  なぜレコード長は、宣言されたデータよりも小さいのだろうか?それは大きくあるべきだ!

• データはそれ以降の処理で使用されていないので、幸いそんなに大きな問題にはなっていない

Page 56: Jurczyk windows metafile_pacsec_jp3

マイナーバグ #3 in EMR_CREATECOLORSPACEW

• ユーザ定義 LOGCOLORSPACEW 構造体の .lcsFilenameバッ

ファーはヌル終端のチェックをしていない

•  文字列のアクセス中に範囲外を読みだされる可能性がある

• あきらかなように、多くの未チェックの前提データが多く実装されてお

り、これまではマイナーという扱いであった

•  これらはより深刻ななにかにつながるという予測

Page 57: Jurczyk windows metafile_pacsec_jp3

存在ファイル情報の公開

•  EMR_CREATECOLORSPACE[W]レコードの機能に戻る:完全にコントロール

されたLOGCOLORSPACE構造体とCreateColorSpace[W]を呼び出す

typedefstructtagLOGCOLORSPACE{DWORDlcsSignature;DWORDlcsVersion;DWORDlcsSize;LCSCSTYPElcsCSType;LCSGAMUTMATCHlcsIntent;CIEXYZTRIPLElcsEndpoints;DWORDlcsGammaRed;DWORDlcsGammaGreen;DWORDlcsGammaBlue;TCHARlcsFilename[MAX_PATH];}LOGCOLORSPACE,*LPLOGCOLORSPACE;

Page 58: Jurczyk windows metafile_pacsec_jp3

CreateColorSpaceWの内側

•  この関数はカラープロファイルパスを組み立てるのに内部で使用される

gdi32!BuildIcmProfilePath

•  提供されるファイル名が相対的である場合、システムのディレクトリ・パスに追加される

•  それ以外の場合は、絶対パスがそのまま残されている

•  全てのパスは"/"または"\"の2文字で始まるものを除き認められている:

if((pszSrc[0]=='\\'||pszSrc[0]=='/')&&(pszSrc[1]=='\\'||pszSrc[1]=='/')){//Pathdenied}

Page 59: Jurczyk windows metafile_pacsec_jp3

CreateColorSpaceWの内側

• これは多分“\\”プレフィックスで始まるパスは例えば \\192.168.1.13\C

\Users\test\profile.iccのようにリモートUNCのパス指定を想定している

• しかし,JamesForshawはこのチェックが有効でないことを書き示している,

“\??\”のようなプレフィックスでも表記ができるため

• チェックは容易に回避できた:

\??\192.168.1.13\C\Users\test\profile.icc

Page 60: Jurczyk windows metafile_pacsec_jp3

CreateColorSpaceInternalW: 最終段階

•  パスが形成された後,NtGdiCreateColorSpaceシステムコールが呼び出さ

れる前に,関数はファイルを開き、それが存在稼働かを確認してすぐに閉じる:

HANDLEhFile=CreateFileW(&FileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);if(hFile==INVALID_HANDLE_VALUE){GdiSetLastError(2016);return0;}CloseHandle(hFile);

Page 61: Jurczyk windows metafile_pacsec_jp3

結果

• その結果,CreateFileW()の呼び出しは任意のパスにすることが

できる

•  成功すれば、カラースペースオブジェクトが作成され、関数が成功を返す

•  失敗した場合は、GDIオブジェクトが作成されず、ハンドラーが失敗を返す

• 情報公開の可能性に聞こえる

•  例えば InternetExplorerでのエクスプロイトにはどのようにアプローチをすれ

ばいい?

Page 62: Jurczyk windows metafile_pacsec_jp3

直感的な方法: 戻り値をリーク

• CreateFileW()の戻り値がレコード処理の成功を決定することから、

少しリークできるのではないか?

•  最初のアイデア:描画操作に続いて EMR_CREATECOLORSPACEを最初のレ

コードとして使用

•  (<canvas>タグで決定することができる)描画が行わなければ,呼び出しは

失敗

Page 63: Jurczyk windows metafile_pacsec_jp3

直感的な方法: 戻り値をリーク

• 残念ながら不可能

• 関数(PlayEnhMetaFile自身によって呼び出される)gdi32!

_bInternalPlayEMFは1つのレコードが失敗した時にレコード処理は中

断しない

•  „success”のフラグがFALSEにセットされ,機能が次のプロセスに進む

• 全てのレコードが常に実行され、戻り値は少なくともプロセス中の1つのレ

コードの失敗したかどうかのフラグを示している

Page 64: Jurczyk windows metafile_pacsec_jp3

最終的な戻り値をリークすることはできない?

• あまりできない

• PlayEnhMetaFileの戻り値はInternetExplorerの mshtml!

CImgTaskEmf::Decode:によって破棄される

.text:64162B49callds:__imp__PlayEnhMetaFile@12

.text:64162B4Fordwordptr[ebx+7Ch],0FFFFFFFFh

.text:64162B53leaeax,[esp+4C8h+var_49C]

Page 65: Jurczyk windows metafile_pacsec_jp3

その他の開示オプション

• 他のインジケータはNtGdiCreateColorSpaceを通したカラース

ペースオブジェクトとして作られる

•  (すべての可能性を考慮しても)直接の漏えいは簡単ではない、しか

しサイドチャンネルがあったらどうだろう?

Page 66: Jurczyk windows metafile_pacsec_jp3

GDI オブジェクト使用時の制限

•  Windowsの全てのプロセスは、標準でGDIオブジェクトが最大10,000に制限されている

•  数はレジストリで変更できる、しかしIEのためのものではない

•  10,000のファイルパス付きEMR_CREATECOLORSPACEWレコードを確認したいときには:

•  ファイルが存在するとき、10,000のカラースペースオブジェクトはプロセスの限界に達する

•  ファイルが存在しないときは、カラースペースを全く持たない

•  限界に達しているかどうかという時、(もうひとつ)ブラシを作成しペイントをすると:

•  ファイルが存在するとき、ブラシの作成は失敗し標準のブラシが使用される

•  ファイルが存在しないとき、ブラシは作成されペイントに使用される

Page 67: Jurczyk windows metafile_pacsec_jp3

oracle に示されているGDI オブジェクト限界

BitmapFontPaleAe

ColorspaceColorspaceColorspaceColorspace

...ColorspaceColorspaceColorspaceColorspaceColorspaceColorspaceColorspace

限界

Brush

BrushBitmapFontPaleAe

Brush

Brush

ファイルあり: ファイル無し:

Page 68: Jurczyk windows metafile_pacsec_jp3

デモ

Page 69: Jurczyk windows metafile_pacsec_jp3

脆弱性のインパクト

• 任意のファイル存在情報が漏えいし、多くの目的で利用可能:

•  標的型の攻撃の際に、特定のソフトウェア(およびバージョン)がインストー

ルされていることを特定できる

•  (既知のファイルに基づいてプロファイルを作成することで)ユーザを追跡

•  オフラインドキュメントのオープンした時間を追跡(例としてMicrosoVOfficeで

開く度にSMB経由でリモートサーバにpingを送るなど)

•  ユーザが利用可能なネットワーク共有を探し出す

Page 70: Jurczyk windows metafile_pacsec_jp3

Impact: Memorydisclosure

Record: Mul[plerecords(10)

Exploitablein: InternetExplorer

CVE: CVE-2016-3216

google-security-researchentry: 757

Fixed: MS16-074,14June2016

CVE-2016-3216

Page 71: Jurczyk windows metafile_pacsec_jp3

デバイス独立ビットマップ (DIBs)

WindowsGDIでは、ラスタビットマップは

メモリ上でDIB形式で格納されている:

•  オプションパレットに続いてイメージの基

本的なメタデータを含むショートヘッダが

ある

•  画像データそのもの

BITMAPINFO

BITMAPINFOHEADER

RGBQUADbmiColors[...];

Bitmapdata1114221114221114221114221114221114221114221114221114221114221114221114221114221114221114221114221013211013211013211013211013211013211013211013210F12200F12200F12200F12200F12200F12200F12200

Page 72: Jurczyk windows metafile_pacsec_jp3

.BMP ファイルも DIBsと同じ

BITMAPINFO

BITMAPINFOHEADER

RGBQUADbmiColors[...];

Bitmapdata1114221114221114221114221114221114221114221114221114221114221114221114221114221114221114221114221013211013211013211013211013211013211013211013210F12200F12200F12200F12200F12200F12200F12200

BITMAPFILEHEADERtypedefstructtagBITMAPFILEHEADER{WORDbfType;DWORDbfSize;WORDbfReserved1;WORDbfReserved2;DWORDbfOffBits;}BITMAPFILEHEADER;

bfOffBits

Page 73: Jurczyk windows metafile_pacsec_jp3

BITMAPINFOHEADER、些細なヘッダ

typedefstructtagBITMAPINFOHEADER{DWORDbiSize;LONGbiWidth;LONGbiHeight;WORDbiPlanes;WORDbiBitCount;DWORDbiCompression;DWORDbiSizeImage;LONGbiXPelsPerMeter;LONGbiYPelsPerMeter;DWORDbiClrUsed;DWORDbiClrImportant;}BITMAPINFOHEADER;

• 短くてシンプルな構造

•  40バイトの長さ(典型的な形)

•  8個だけが重要なフィールド

Page 74: Jurczyk windows metafile_pacsec_jp3

そんなに簡単な操作なのか?

•  biSizeはサニタイズする必要がある(ほんの1-2個の有効な値になれるだけ)

•  biWidth,biHeight,biPlanes,biBitCountは整数オーバーフローを起こす可能性

がある(お互いに掛け合わすので)

•  biHeightはボトムアップビットマップを示すために負の値を指定できる

•  biPlanesは1でなければならない

•  biBitCountは{1,2,4,8,16,24,32}のうちの1つでなければならない

•  biBitCount<16の場合,カラーパレットを使用できる

•  カラーパレットのサイズはbiClrUsedに影響する

Page 75: Jurczyk windows metafile_pacsec_jp3

その扱いは本当に些細なのか?

•  biCompressionは BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS,...とすることができ

•  各圧縮方式は正しく処理されなければならない

•  biSizeImageは実際のイメージサイズに対応している必要がある

•  パレットは全てのエントリーを格納できる充分な大きさが必要

•  ピクセルデータバッファは全てのピクセルを情報を入れる充分な大きさが必要

•  エンコードされたピクセルはヘッダの値に対応している必要がある(例えばバレットのサ

イズを超えないなど)

Page 76: Jurczyk windows metafile_pacsec_jp3

多くの潜在的な問題

1.  ヘッダにもとづいてDIBを正しく処理をする決定木(decisiontree)は

非常に複雑

2.  多くのやっかいなケースとしては保護とバグを避ける実装をする必

要がある

3.  コードの様々な部分では一貫性のある取り扱いが必要

Page 77: Jurczyk windows metafile_pacsec_jp3

DIB上で (直接)動作するGDI 関数

イメージデータのポインタ

DIBヘッダのポインタ

Page 78: Jurczyk windows metafile_pacsec_jp3

DIB上で (直接)動作するGDI 関数

Page 79: Jurczyk windows metafile_pacsec_jp3

データサニタイズの責任

• 全ての場合において、ヘッダとデータが正しく適切であることをチェックする

のはAPI呼び出し元の責任である

• アプリケーションコードが „クローン” GDIによる DIBハンドリングができるよ

うに、完全にユーザが制御可能な入力データを渡すことは問題がある

• 何だと思う?EMFは組み込みDIBを含む複数のレコードをサポートしている

Page 80: Jurczyk windows metafile_pacsec_jp3

DIBを含むEMFレコード

•  EMR_ALPHABLEND•  EMR_BITBLT•  EMR_MASKBLT•  EMR_PLGBLT•  EMR_STRETCHBLT•  EMR_TRANSPARENTBLT•  EMR_SETDIBITSTODEVICE•  EMR_STRETCHDIBITS•  EMR_CREATEMONOBRUSH•  EMR_EXTCREATEPEN

Page 81: Jurczyk windows metafile_pacsec_jp3

一般的なスキーム

• ヘッダとビットマップの両方のための2組の (offset,size):

Page 82: Jurczyk windows metafile_pacsec_jp3

EMFレコードハンドラで必要なチェック

• DIBを扱う各ハンドラでは,必須な整合性チェックが4つある:

1.  cbBmiSrcはヘッダ内に収まるように充分に大きい事

2.  (offBmiSrc,offBmiSrc+cbBmiSrc)は完全にレコード内に存在する事

3.  cbBitsSrcはビットマップデータ内におさまるように充分に大きい

4.  (offBitsSrc,offBitsSrc+cbBitsSrc)は完全にレコード内に存在する事

Page 83: Jurczyk windows metafile_pacsec_jp3

チェックは多くの組み合わせで欠落

Recordhandlers Missingchecks

MRALPHABLEND::bPlayMRBITBLT::bPlayMRMASKBLT::bPlayMRPLGBLT::bPlayMRSTRETCHBLT::bPlayMRTRANSPARENTBLT::bPlay

#1,#2

MRSETDIBITSTODEVICE::bPlay #3

MRSTRETCHDIBITS::bPlay #1,#3

MRSTRETCHDIBITS::bPlayMRCREATEMONOBRUSH::bPlayMREXTCREATEPEN::bPlay

#1,#2,#3,#4

*これはざっと見た状態;MicrosoVはもっと修正をしている可能性がある

Page 84: Jurczyk windows metafile_pacsec_jp3

結果

• 欠落のチェックのために、イメージ説明の一部は、他のパーツプロセ

スのアドレス空間からロードできる(例 隣接するヒープの割り当て):

•  DIBヘッダ

•  カラーパレット

•  ピクセルデータ

• 初期化されていないか、境界外のヒープメモリはパレットやピクセル

データにより読み出される

Page 85: Jurczyk windows metafile_pacsec_jp3

Proof of concept

•  ファイルを越えたパレットエントリーの8-bppDIBを含む EMR_STRETCHBLTレコードを使用したPoC

をハックした

•  結果:集められたバイトはイメージとして表示される

•  同じ画像がIEの1行に3回表示されている:

•  データはHTML5を使用して漏えいしたモジュールアドレスや他の機密情報などを読むことができる

Page 86: Jurczyk windows metafile_pacsec_jp3

デモ

Page 87: Jurczyk windows metafile_pacsec_jp3

ATMFD.DLLの監査 間に合わなかったので、カンファレンス後に公開する完全版のSlideDeckを見てください J

Page 88: Jurczyk windows metafile_pacsec_jp3

GDI+ の監査

Page 89: Jurczyk windows metafile_pacsec_jp3

GDI+ は充分なターゲット

• GDI+はEMFと EMF+の両方をサポートする

•  多くの実装は独立しているが,フォーマットのいくつかのパーツはGDIのコー

ドから来ている

•  したがっていくつかのGDIバグはGDI+のクライアントに影響を与える

• 最も主要なGDI+クライアントはMicrosoVOffice製品

• もう1度EMFレコードハンドラの全体を手動で監査してみよう

Page 90: Jurczyk windows metafile_pacsec_jp3

攻撃ポイント(アタックサーフェス)は容易に見つかる

Page 91: Jurczyk windows metafile_pacsec_jp3

攻撃ポイント(アタックサーフェス)は容易に見つかる

Page 92: Jurczyk windows metafile_pacsec_jp3

いくつか特定のバグを見てみましょう

Page 93: Jurczyk windows metafile_pacsec_jp3

Impact: Write-what-where

Record: Allrecordsopera[ngonDIBs

Exploitablein: MicrosoVOffice

CVE: CVE-2016-3301

google-security-researchentry: 824

Fixed: MS16-097,9August2016

CVE-2016-3301

Page 94: Jurczyk windows metafile_pacsec_jp3

EMF中におけるRLE圧縮されたビットマップ

• 前述のように、複数のEMFレコードはDIBを含む

• DIBは4から8ビットのRLEなどの簡単な方式で圧縮ができる

•  ヘッダの biCompressionフィールドに示される

• いくつかのハンドラのコードを読むことで、8-ビットRLEはGDI+でサ

ポートされていることを見つけた

• RLE展開は歴史的にバグが多く見つかっている

Page 95: Jurczyk windows metafile_pacsec_jp3

コードへの到達

DecodeCompressedRLEBitmap

CopyOnWriteBitmap::CopyOnWriteBitmap

CopyOnWriteBitmap::Create

GpBitmap::GpBitmap

CEmfPlusEnumState::PlgBlt CEmfPlusEnumState::RenderBlt

Page 96: Jurczyk windows metafile_pacsec_jp3

DecodeCompressedRLEBitmap()の内部

•  2つの値は計算される:columns=abs(biHeight)

bytes_per_row=abs(biWidth*(((biPlanes*biBitCount+31)&0xFFFFFFE0)/8))

• 出力バッファはサイズからヒープが割り当てられる

columns*bytes_per_row

•  バッファ長を高度にコントロール

• RLE„プログラム”の解釈と実行が始まる

Page 97: Jurczyk windows metafile_pacsec_jp3

„最終行” 命令コード

• 出力ポインタを次の行に移す(同じオフセットで)

Page 98: Jurczyk windows metafile_pacsec_jp3

„最終行” 命令コード

•  GDI+では,以下の様に実装:

out_ptr+=bytes_per_row;if(out_ptr>output_buffer_end){//Bailout}

•  境界チェックはあらゆる種類の範囲外のアクセスを防ぐために実装されている

•  64ビットプラットフォーム上で正しく動作するように行われるが,状態は本当に充

分なのか?

Page 99: Jurczyk windows metafile_pacsec_jp3

不十分な検証

プロセスのアドレス空間の終わり0xffffffff

出力バッファ

Page 100: Jurczyk windows metafile_pacsec_jp3

トリッキーなポインタ演算

• 非常に広いビットマップの場合、現在の出力ポインタからアドレス空間の終

わりまでの距離を走査線の幅よりも小さくすることができる

• 式:

out_ptr+=bytes_per_row;

その後のチェックが効果がなく,オーバーフローを引き起こす

• その結果,出力ポインタを多くの制御可能なアドレスに設定することができる

Page 101: Jurczyk windows metafile_pacsec_jp3

•  biWidth=0x05900000

•  biHeight=0x00000017

•  biPlanes=0x0001

•  biBitCount=0x0008

•  その結果、columns=0x17と bytes_per_row=0x590000

•  合計バッファ サイズ=0x7FF00000(およそ2GB)

•  配置アドレスの例:0x7FFFF0020、最終位置:0xFFEF0020

Page 102: Jurczyk windows metafile_pacsec_jp3

メモリアドレス空間レイアウト

0x00000000 0xFFFFFFFF

0x7FFF0020

Page 103: Jurczyk windows metafile_pacsec_jp3

メモリアドレス空間レイアウト (EOL #1)

0x00000000 0xFFFFFFFF

0x858F0020

Page 104: Jurczyk windows metafile_pacsec_jp3

メモリアドレス空間レイアウト (EOL #2)

0x00000000 0xFFFFFFFF

0x8B1F0020

Page 105: Jurczyk windows metafile_pacsec_jp3

メモリアドレス空間レイアウト (EOL #3-22)

0x00000000 0xFFFFFFFF

Page 106: Jurczyk windows metafile_pacsec_jp3

メモリアドレス空間レイアウト (EOL #23)

0x00000000 0xFFFFFFFF

0xFFEF0020

Page 107: Jurczyk windows metafile_pacsec_jp3

メモリアドレス空間レイアウト (EOL #24)

0x00000000 0xFFFFFFFF

0x057F0020

Page 108: Jurczyk windows metafile_pacsec_jp3

(3434.194):Accessviolation-codec0000005(firstchance)

Firstchanceexceptionsarereportedbeforeanyexceptionhandling.

Thisexceptionmaybeexpectedandhandled.

eax=0011015eebx=ffef0020ecx=000000feedx=057f01ccesi=057f0020edi=0011a6f0

eip=6b090e5aesp=0037f290ebp=0037f2aciopl=0nvupeiplnznapecy

cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00010207

gdiplus!DecodeCompressedRLEBitmap+0x195:

6b090e5a8816movbyteptr[esi],dlds:002b:057f0020=??

0:000>kb

ChildEBPRetAddrArgstoChild

0037f2ac6b091124057f0020cc11012c0037f2ccgdiplus!DecodeCompressedRLEBitmap+0x195

0037f6f46b092c7a001100f80011012c00000000gdiplus!CopyOnWriteBitmap::CopyOnWriteBitmap+0x96

0037f7086b0932cc001100f80011012c00000000gdiplus!CopyOnWriteBitmap::Create+0x23

0037f7206b0c1e8b001100f80011012c00000000gdiplus!GpBitmap::GpBitmap+0x32

0037f8046b0c7ed10000004f00143a300000a67cgdiplus!CEmfPlusEnumState::PlgBlt+0x92

Page 109: Jurczyk windows metafile_pacsec_jp3

サマリー

•  要件:PAEが有効な32-ビットプロセス

•  4GBアドレス空間全部をプログラムに使用可能にする必要がある

•  結果:どこに何を書くという条件は、„どこ”以上に高度なコントロールが必要

•  特定の値を達成させるだけでなく、上書きされた領域は元の出力バッファ以下の必要あり

•  エクスプロイトの確実さはイメージがロードされた時のアドレス空間の状態に強く

依存する

Page 110: Jurczyk windows metafile_pacsec_jp3

Impact: Heap-basedbufferoverflow

Record: EMR_EXTTEXTOUTA,EMR_POLYTEXTOUTA

Exploitablein: MicrosoVOffice

CVE: CVE-2016-3304

google-security-researchentry: 828

Fixed: MS16-097,9August2016

CVE-2016-3304

Page 111: Jurczyk windows metafile_pacsec_jp3

ExtTextOutA() と PolyTextOutA()

Page 112: Jurczyk windows metafile_pacsec_jp3

EMF レコード内のDx 配列

Page 113: Jurczyk windows metafile_pacsec_jp3

関数の簡単なバグ

• Dx配列はN個の要素であると想定され、Nは表示されているキャラク

タの数

• 以下はレコードサイズの検証チェック:

if(record_size-offString>=nChars&&(!nChars||record_size-4>=record->emrtext.offDx)){//Validationpassed,continueprocessingtherecord.}

• 何かが欠けていない?

Page 114: Jurczyk windows metafile_pacsec_jp3

関数の些細なバグ

• コードはDx配列が4バイトを保持するかをチェック

•  4×Nバイトを保持することができれば本当に検証をすべき

•  典型的なヒューマンエラーの整合性チェック

• だから何?入力値検証の問題で外の境界を読み出すだけでは?

•  はい、エクストラのロジックのためにコードを呼び出さなければ

Page 115: Jurczyk windows metafile_pacsec_jp3

拡張機能ロジック

•  MultiByteToWideChar()を使用して、stringをwide-charへ変換

•  コードページは最後に選択したフォントで指定される

• 全ての文字列が変換されたとき,通常

CEmfPlusEnumState::PlayExtTextOut()が呼び出される

• しかしそうでない場合は…

Page 116: Jurczyk windows metafile_pacsec_jp3

DBCS (ダブルバイト文字セットの)扱い

•  1バイト以上で構成する文字もサポート

• 以下の様に取り扱いが実装されている:

•  EMFレコードの正確なコピーが(同じサイズに)配置される

•  Dx配列の項目はオリジナルのレコードから新しいものに書き換えられる,„先

行バイト”(IsDBCSLeadByteEx()がTRUEを返す)のエントリを省略

•  新しいレコードが以降通常として処理される

Page 117: Jurczyk windows metafile_pacsec_jp3

コードパスに到達

•  DBCSをサポートするコードページのフォントが最初に選択されなければならない

•  典型的なものはCJK(中国語,日本語,韓国語)のコードページ,例として

SHIFTJIS_CHARSET

•  その後,少なくとも1つの„leadbyte”が含まれる影響を受けたレコードの1つは使用されなけ

ればならない

•  その結果、境界を越えて他の配置から読み出す典型的なヒープベースのオー

バーフローになる

•  heapmassagingにより,制御した上書きを可能にする

Page 118: Jurczyk windows metafile_pacsec_jp3

ヒープオーバーフローの仕組み

オリジナルのレコード新しいレコード

ヒープ領域

Page 119: Jurczyk windows metafile_pacsec_jp3

ヒープオーバーフローの仕組み

オリジナルのレコード新しいレコード

ヒープ領域

Dx配列の書き換え

Page 120: Jurczyk windows metafile_pacsec_jp3

(2a8c.2bd8):Breakinstructionexception-code80000003(firstchance)eax=00000000ebx=00000000ecx=772336abedx=0022cb85esi=03bd0000edi=1171ffc0eip=7728e815esp=0022cdd8ebp=0022ce50iopl=0nvupeiplnznapenccs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00200206ntdll!RtlReportCriticalFailure+0x29:7728e815ccint30:000>kbChildEBPRetAddrArgstoChild0022ce507728f749c0000374772c42700022ce94ntdll!RtlReportCriticalFailure+0x290022ce607728f8290000000264dc132603bd0000ntdll!RtlpReportHeapFailure+0x210022ce947724ab460000000c03bd00001171ffc0ntdll!RtlpLogHeapFailure+0xa10022cf84771f3431000002580000026003bd00c4ntdll!RtlpAllocateHeap+0x7b20022d008695071ec03bd00000000000000000258ntdll!RtlAllocateHeap+0x23a0022d01c6951bbf100000258116b510403bdd558gdiplus!GpMalloc+0x160022d03069557185116b50e0116b50e003bdd558gdiplus!GpGraphics::Save+0x110022d4b069557bdc116b50e0116b5104116b30d8gdiplus!CEmfPlusEnumState::PlayExtTextOut+0xda0022d4ec69557f250000005303bdae0000006044gdiplus!CEmfPlusEnumState::ExtTextOutA+0x1360022d500695286ca00000053000060440d67b568gdiplus!CEmfPlusEnumState::ProcessRecord+0x13b0022d51c69528862000000530000000000006044gdiplus!GdipPlayMetafileRecordCallback+0x6c0022d544768155f49d211b170d5671800d67b568gdiplus!EnumEmfDownLevel+0x6e0022d5d06952aa369d211b17403581b3695287f4GDI32!bInternalPlayEMF+0x6a3

Page 121: Jurczyk windows metafile_pacsec_jp3

Impact: Heapmemorydisclosure

Record: AllrecordshandlingDIBs

Exploitablein: MicrosoVOfficeOnline

CVE: ?

google-security-researchentry: 825,829

Fixed: MS16-???,11October2016(?)

GDI+ の情報漏えいバグ

Page 122: Jurczyk windows metafile_pacsec_jp3

GDI+ vs DIB

•  GDIとは異なり,GDI+はビットマップの取り扱いに起因する情報漏えいバ

グを避けなかった

• 具体的に:1.  „ビットマップの終わり”のマーカーで始まる、RLE圧縮されたビットマップのデータ

ストリームでは,画像の出力バッファ全体が初期化されていない(ジャンクヒープ

データが含まれる)

2.  ビットマップパレットが完全にEMFレコードに収まるようになっているかはチェックさ

れない

Page 123: Jurczyk windows metafile_pacsec_jp3

はっきりと目に見えるバグ

• PoCコードのピクチャをwordに読み込ませると,はっきりとジャンク

データがピクセルとして表示されているのが見える

Page 124: Jurczyk windows metafile_pacsec_jp3

リモートからの悪用可能性?

•  ピクセルが何かに戻せるのでもないので、ヒープメモリを表示することはそんな

にシリアスな状況ではない。

•  インタラクティブに出来ないため、バグの唯一のターゲットはOfficeプログラム

•  MicrosoVに報告し、深刻度の評価と、攻撃につながる可能性についての評価を

待った

•  MSRCはこの事象を„vNext”としてクローズした(毎月のパッチでは修正せず,次

期バージョンなどのタイミングで修正)

Page 125: Jurczyk windows metafile_pacsec_jp3

深刻度の評価

• これは私自身が考えていた露呈問題の理解と一致しており,決定に同意

した•  P0バグの#825と#829はそれぞれ7/26と8/9に解決とした

•  8月の始めに,IvanFratricがチャットで GDI+/EMFのバグはOfficeOnlineにおいてリモートから攻撃につながる可能性があることを伝えてきた

•  私はこのプログラムの存在を知らなかった

•  攻撃可能ではなかったが,特にGDI+のメモリー漏えいのバグは興味深い

•  EMFイメージはドキュメント内に挿入できないが,.docxには埋め込みEMFとして可能

Page 126: Jurczyk windows metafile_pacsec_jp3

Office オンライン

• 数週間前にチェックをしたら…

Page 127: Jurczyk windows metafile_pacsec_jp3

Office オンライン

•  EMFイメージは毎回異なったレンダリングがされる

• MicrosoVのサーバのレンダリングプロセスからリモートのメモリを読み出

せる

• MSRCに再考を求めるために新しい情報を提供

• 彼らはOfficeOnlineのシナリオは以前には考慮されていなかった,それは

修正に値するバグとされた

•  10月の定例パッチまでに修正される必要があった

Page 128: Jurczyk windows metafile_pacsec_jp3

VMware Workstadonのハック

Page 129: Jurczyk windows metafile_pacsec_jp3

プリントスプールのEMF

•  EMFファイルはプリントスプールに頻繁に使われる

• これはプリンタドライバ(およびその他関連ソフトウェア)の形式で,

フォーマットに起因する攻撃ベクタとして使用される

•  1つのターゲットとしてVMwareWorksta[onを選定

Page 130: Jurczyk windows metafile_pacsec_jp3

仮想プリンタ

•  これは仮想マシンからホストを通してドキュメントの印刷を可能にする昨日(基本的には

プリンタの共有)

•  実現可能なVM回避の攻撃ベクタ

•  T私の知る限りでは,2015年まではデフォルトで有効であったが,現在は有効ではない

(KostyaKortchinskyが報告したバグが役立った)

•  いまだ頻繁に使用するオプション

Page 131: Jurczyk windows metafile_pacsec_jp3

構造

VM#3 VM#2 VM#3poc.exe

VirtualMachines

vmware.exe

COM1

vprintproxy.exe

Windows名前付きパイプ

Page 132: Jurczyk windows metafile_pacsec_jp3

構造

• 攻撃プロセスは vprintproxy.exeが稼働するホスト

•  ゲストシステムで非特権プロセスによって送信され、ほぼそのままのデータ

を受信します

•  通信のチャンネル

• データはEMFSPOOLファイルの形式で送られる

•  EMFと同様に,追加オプションを指定して、様々な形式のフォントを埋め込む

ことができる

Page 133: Jurczyk windows metafile_pacsec_jp3

TPView

• 特に,最も興味深いEMF処理は TPview.dllで行われる

•  その他プリンタに関するライブラリは,すべてサードパーティのThinPrintで開

発がされていると思われる

• いくつかのレコードタイプの特殊処理は,GDIに処理が戻る

•  全ては簡単なバグではあったが,Kostyaは(ほぼ)全てを見つけた!

•  他を見ていたら,ダブル・フリーとout-of-boundsmemset()を見つけた,それ

らは(問題#848と#849)に含まれる

Page 134: Jurczyk windows metafile_pacsec_jp3

JPEG2000 デコード

• 完全に未調査であった最後のカスタムEMFレコード

•  ID=0x8000

•  デバッグ文字列に基づいて,それらは JPEG2000のデコードに関してのもので

ある

•  JPEG2Kの専門家でもないので,コードは手動検査にとっては便利で

はないように見えた

• ファジングしてみる?

Page 135: Jurczyk windows metafile_pacsec_jp3

ファジングによるアプローチ

•  ベストなファジング:Linux上で,スケールで,AddressSani[zerを使用してカバレッ

ジフィードバックを待つ

•  いくつかの調査後,JPEG2000デコーダーは別のベンダーのLuraTechによって開

発されていることが分かった

•  商用ライセンス,自由に利用できないソースコード

•  そのため,我々はVMwareWorksta[onでラップされたTPview.dllで止まった?

•  継続可能だが,より複雑で,遅くて,先進的でない

Page 136: Jurczyk windows metafile_pacsec_jp3

さらなる調査

• さらなる調査で,同じベンダーがフリーウェアとして人気のIrfanViewプログ

ラムの用にJPEG2000のデコードプラグインを提供して居ることを見つけた

•  JPEG2000.DLL.

•  大まかな分析により同じか非常に近いコードをベースとしていることが分かった

• プラグインインターフェースを使用することは非常に簡単で,次の定義に

似ている

Page 137: Jurczyk windows metafile_pacsec_jp3

HGLOBALReadJPG2000(INPCHARlpFilename,INDWORDdwUnknown,OUTPCHARlpStatus,OUTPCHARlpFormat,OUTLPDWORDlpWidth,OUTLPDWORDlpHeight);

Page 138: Jurczyk windows metafile_pacsec_jp3

それにより...

• これのおかげで,我々はVMWareを起動することなく,Windows上の

単一プロセスの実装に対しファジングテストを簡単に実施できた

•  DLLをロードするラッパープログラムと関連する関数の呼び出しは<50LOC

long

• しかし,私はこれらがLinuxに実装されていることを好むだろうか...

Page 139: Jurczyk windows metafile_pacsec_jp3

Linux上でのファジングDLL

•  なぜない,本当に?

•  望ましいベースアドレスは0x10000000,アドレス空間で利用可能

•  再配置は必要ではない;セクションはそれぞれのアクセス権限があるところにマップされるべき

•  その他のアクション:

•  必要なインポートを解決

•  エクスポートされた関数のアドレスを取得

•  デコードを実行するためにそれを呼び出す

•  動作するはず!

Page 140: Jurczyk windows metafile_pacsec_jp3

インポートの解決

• インポートテーブルは面倒なポイントでもある

• WinAPI関数はLinux上では提供されていない

• DLLインポート元は ADVAPI32,KERNEL32,MSVCRT,SHELL32と

USER32

•  Cランタイムのインポートは直接libcにリダイレクトされる

•  他の全てのものは書き換えられるか少なくともスタブアウトしなければならな

Page 141: Jurczyk windows metafile_pacsec_jp3

KERNEL32 imports

•  デコードに使われる3つのWinAPI関数:GlobalAlloc,GlobalLockandGlobalUnlock:

void*GlobalAlloc(uint32_tuFlags,uint32_tdwBytes)__attribute__((stdcall));void*GlobalAlloc(uint32_tuFlags,uint32_tdwBytes){void*ret=malloc(dwBytes);if(ret!=NULL){memset(ret,0,dwBytes);}returnret;}void*GlobalLock(void*hMem)__attribute__((stdcall));void*GlobalLock(void*hMem){returnhMem;}boolGlobalUnlock(void*hMem)__attribute__((stdcall));boolGlobalUnlock(void*hMem){returntrue;}

Page 142: Jurczyk windows metafile_pacsec_jp3

libc のインポートが無いとき

• 再実装されなければならない、2つのMSVCRT-固有のインポートが

見つかった:

longlong_ftol(doubleval)__attribute__((cdecl));longlong_ftol(doubleval){return(longlong)val;}double_CIpow(doublex,doubley)__attribute__((cdecl));double_CIpow(doublex,doubley){returnpow(x,y);}

Page 143: Jurczyk windows metafile_pacsec_jp3

動いた!

$./loaderJPEG2000.dlltest.jp2[+]Successfullyloadedimage(9b74ba8),format:JPEG2000-Wavelet,width:4,height:4

Page 144: Jurczyk windows metafile_pacsec_jp3

ファジングの実行

• 内部的に利用可能なJPEG2000の入力ファイルコーバスを使用

• ミューテーションストラテジのレートは成功/失敗が50/50になるように

調整

• 数日間ファジングを実行させて,そして...

•  ...186のクラッシュとユニークなスタックトレースが見つかった

Page 145: Jurczyk windows metafile_pacsec_jp3

クラッシュの再現

• クラッシュはプラグインDLL上のものであって、まだVMwareWorksta[onの

ものではない点に注意

•  vprintproxy.exeはとても便利に使える:名前付きパイプを作成しCOM1に

書かれているデータを正確に読み出すことができる

•  もう1度、我々は実際のVMを起動せずにテストケースをチェックすることができる

• ページヒープはよりよいバグの検出と重複の排除を可能にする

Page 146: Jurczyk windows metafile_pacsec_jp3

最終結果

InstrucRon Reasonadd[eax+edx*4],edi Heapbufferoverflowcmp[eax+0x440],ebx Heapout-of-boundsreadcmp[eax+0x8],esi Heapout-of-boundsreadcmp[edi+0x70],ebx Heapout-of-boundsreadcmp[edi],edx Heapout-of-boundsreadcmpdword[eax+ebx*4],0x0Heapout-of-boundsreadcmpdword[esi+eax*4],0x0Heapout-of-boundsreaddivdword[ebp-0x24] Divisionbyzerodivdword[ebp-0x28] Divisionbyzeroflddword[edi] NULLpointerdereferenceidivebx Divisionbyzeroidivedi Divisionbyzeroimulebx,[edx+eax+0x468] Heapout-of-boundsreadmov[eax-0x4],edx Heapbufferoverflowmov[ebx+edx*8],eax Heapbufferoverflowmov[ecx+edx],eax Heapbufferoverflowmoval,[esi] Heapout-of-boundsreadmovbx,[eax] NULLpointerdereferencemoveax,[ecx] NULLpointerdereferencemoveax,[edi+ecx+0x7c] Heapout-of-boundsread

InstrucRon Reasonmoveax,[edx+0x7c] Heapout-of-boundsreadmovdqa[edi],xmm0 Heapbufferoverflowmovqmm0,[eax] NULLpointerdereferencemovqmm1,[ebx] NULLpointerdereferencemovqmm2,[edx] NULLpointerdereferencemovzxeax,byte[ecx-0x1] Heapout-of-boundsreadmovzxeax,byte[edx-0x1] Heapout-of-boundsreadmovzxebx,byte[eax+ecx] Heapout-of-boundsreadmovzxecx,byte[esi+0x1] Heapout-of-boundsreadmovzxecx,byte[esi] Heapout-of-boundsreadmovzxedi,word[ecx] NULLpointerdereferencemovzxesi,word[edx] NULLpointerdereferencepushdword[ebp-0x8] Stackoverflow(deep/infiniterecursion)pushebp Stackoverflow(deep/infiniterecursion)pushebx Stackoverflow(deep/infiniterecursion)pushecx Stackoverflow(deep/infiniterecursion)pushedi Stackoverflow(deep/infiniterecursion)pushesi Stackoverflow(deep/infiniterecursion)repmovsd Heapbufferoverflow,Heapout-of-boundsread

Page 147: Jurczyk windows metafile_pacsec_jp3

最終結果

•  39のユニークなインストラクションでクラッシュが発生

•  多くのものはそんなに正確なメトリックのところでなく memcpy()のような一般

的の機能の様々なポイントで発生

•  簡単に分類:18の低深刻度,15中深刻度,6高深刻度

•  6月15日にVmwareに報告された

•  9月13日(90日以内)にVMSA-2016-0014として修正された

Page 148: Jurczyk windows metafile_pacsec_jp3

結論

Page 149: Jurczyk windows metafile_pacsec_jp3

結論

• メタファイルは複雑で興味深いファイルで、研究の価値があるもの•  様々な攻撃ベクタが有効

• システムAPIについていろいろと教えてくれる(i.e.NamedEscapeインター

フェース)

• いつものことだが,古くて曖昧なフォーマット/実装–バグハンター向け

• 以前の成果からのインスピレーションにももっと目を向けよう

• 適材適所–手動のコード監査 vsファジング

Page 150: Jurczyk windows metafile_pacsec_jp3

ありがとう!

@j00ru

http://j00ru.vexillium.org/

[email protected]