jurczyk windows metafile_pacsec_jp3
Post on 08-Jan-2017
465 Views
Preview:
TRANSCRIPT
Windows メタファイル EMF攻撃ポイントと最近の脆弱性の分析
Mateusz“j00ru”Jurczyk
PacSec,Tokyo2016
PS> whoami
• GoogleのProjectZero所属
• 脆弱性の研究とソフトウェアエクスプロイトに興味がある低レイヤー
のセキュリティ研究者
• hAp://j00ru.vexillium.org/
• @j00ru
アジェンダ
• Windows メタファイル入門、GDIデザイン、攻撃ベクタ
• ハック対象:
• InternetExplorer(GDI)
• WindowsKernel(ATMFD.DLL)
• MicrosoVOffice(GDI+)
• VMwarevirtualiza[on(プリントスプール)
• 結論
Windows GDI & メタファイル入門
Windows GDI
• GDIはGraphicsDeviceInterface(グラフィックス・デバイス・インターフェイス)の略
• ユーザーモードアプリケーションで、グラフィックや整形されたテキストをビデオ
ディスプレイやプリンターへの出力を可能にする
• システムAPIの大半を占める(約300のドキュメント化された機能)
• 初期のOSの頃から存在(1985年にリリースされたWindows1.0から)
• 最も古いサブシステムの1つで、31年経った今でも大半は元のコードのまま稼働している
• 偶然にも(?)もっともバグが多い構成要素の1つである
どのように描画するか
1. デバイスコンテキスト へのハンドル(HDC)をつかむ
• 様々なグラフィカル設定(ペン、ブラシ、パレットなど)の永続的なコンテナを
認識する
• スクリーン(もっとも典型的)、プリンター、メタファイルへの描画で使用可能
• 最も簡単な例:
HDChdc=GetDC(NULL);
(画面全体のためにHDCを取得)
どのように描画するか
2. 描画機能を使用
Ellipse(hdc,100,100,500,300); RoundRect(hdc,100,100,500,500,100,100);
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
ユーザーモードとカーネルAPIマッピング
大半のユーザーモードGDI関数は直接対応するカーネルAPIを持って
いる:
GDI32.DLL win32k.sysAbortDoc NtGdiAbortDoc
AbortPath NtGdiAbortPath
AddFontMemResourceEx NtGdiAddFontMemResourceEx
AddFontResourceW NtGdiAddFontResourceW
AlphaBlend NtGdiAlphaBlend
... ...
Windows メタファイル
コアアイデア:
GDI関数呼び出しを記述するレコードのリストとして
イメージを格納する.
Windows メタファイル
• 長所:• GDI関数が与えられたパラメータで呼び出された時だけ、ラスタライズ処理の計算は
ほとんど必要とされない
• GDIが再現可能な画像を操作するための公式な方法を提供
• ベクター形式、ラスター形式また両方の形式として動作する
• 短所:• サポートされているグラフィックのGDI操作が外部に完全に実装されていない場合
は、Windows上でのみ動作する
First version: WMF
• 最初のメタファイル (WMF=WindowsMetaFiles).
• 1990年のWindows3.0で導入された
• GDIそれ自体のほどではないが、同じくらい古典的
• はじめてドキュメント化されたのはWindows3.1SDK(1994年,volume4)
• 改訂され、より完全な仕様は2006年にリリース、それ以来メンテされ続けている
• 全てのレコードや構造はMS-WMFドキュメントに記載されている
WMF files – サポートされている60のAPI関数 AnimatePaletteArcBitBltChordCreateBrushIndirectCreateDIBPatternBrushCreateFontIndirectCreatePaletteCreatePatternBrushCreatePenIndirectDeleteObjectEllipseEscapeExcludeClipRectExtFloodFillExtTextOutFillRgnFloodFillFrameRgnIntersectClipRectInvertRgn
LineToMoveToExOffsetClipRgnOffsetViewportOrgExOffsetWindowOrgExPaintRgnPatBltPiePolygonPolylinePolyPolygonRealizePaletteRectangleResizePaletteRestoreDCRoundRectSaveDCScaleViewportExtExScaleWindowExtExSelectClipRgnSelectObject
SelectPaletteSetBkColorSetBkModeSetDIBitsToDeviceSetMapModeSetMapperFlagsSetPaletteEntriesSetPixelSetPolyFillModeSetROP2SetStretchBltModeSetTextAlignSetTextCharacterExtraSetTextColorSetTextJustificationSetViewportOrgExSetWindowExtExSetWindowOrgExStretchBltStretchDIBitsTextOut
一目見ただけでも興味深そうなもの AnimatePaletteArcBitBltChordCreateBrushIndirectCreateDIBPatternBrushCreateFontIndirectCreatePaletteCreatePatternBrushCreatePenIndirectDeleteObjectEllipseEscapeExcludeClipRectExtFloodFillExtTextOutFillRgnFloodFillFrameRgnIntersectClipRectInvertRgn
LineToMoveToExOffsetClipRgnOffsetViewportOrgExOffsetWindowOrgExPaintRgnPatBltPiePolygonPolylinePolyPolygonRealizePaletteRectangleResizePaletteRestoreDCRoundRectSaveDCScaleViewportExtExScaleWindowExtExSelectClipRgnSelectObject
SelectPaletteSetBkColorSetBkModeSetDIBitsToDeviceSetMapModeSetMapperFlagsSetPaletteEntriesSetPixelSetPolyFillModeSetROP2SetStretchBltModeSetTextAlignSetTextCharacterExtraSetTextColorSetTextJustificationSetViewportOrgExSetWindowExtExSetWindowOrgExStretchBltStretchDIBitsTextOut
WMF: まだまだある!
• このフォーマットは、GDI関数では直接の対応をしていない多くのレ
コードをサポートしている.
• ヘッダ情報を持つmetadata
• 埋め込み EMF
• プリンタードライバー/出力デバイスを直接扱うレコード
• ファイル終端マーク
• ...
WMF: まだまだある!
• 大抵は、最も興味深いレコードが2つのセクションからみつかる:
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)}...
WMF: 今なおとても時代遅れなまま
• それ自体がすでに複雑であるが、そのフォーマットは現代的な使用
法に対して考え抜かれたものになることはなかった
• GDIにサポートされているが故に、いくつかのクライアントの一部に使
用されている(例: MicrosoVOffice、ペイント、いくつかのWindows標
準アプリケーションなど)
• ここ10年かそれ以上、実世界でのユースケースを忘れ去られていた
WMF: 使う気がおきない
• マイクロソフトでさえ、もう使うべきではない多くの理由をあげている:
次に来たもの: EMF (Enhanced MetaFiles:拡張メタファイル)
• すでに1993年に、マイクロソフトはEMFと呼ばれる改良版のイメージフォー
マットをリリース
• 公式のMS-EMF仕様としてドキュメント化されている
• 多くの方法でWMFを上回る:
• 16ビットではなく、32ビットのデータ/オフセット長を使用
• デバイスに依存しない
• 古いレコードとの下位互換性を維持しながら、いくつかの新しいGDIコールをサポート
拡張メタファイル – 例
...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}...
EMF: 一目見ただけでも興味深いレコード
EMF: 一目見ただけでも興味深いレコード
EMF: 一目見ただけでも興味深いレコード
EMF: 現在のサポート
• WMFのわずかに3年新しいものではあるが、EMFは今日まで使用さ
れている
• メインストリームの画像フォーマットではないが、有効な攻撃ベクタ
• さまざまな攻撃ベクタ:
• Win32GDIクライアント–代表はInternetExplorer
• GDI+クライアント–代表はMicrosoVOffice
• プリンタードライバー、仮想化技術で使われるものも含む
ツールセット – 検査 (EMFexplorer)
ツールセット – 検査 (MetafileExplorer)
ツールセット – リーディング & ライティング (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)
最新: EMF+
• GDIはすべて基本的な機能を備えているが、多くの複雑な機能に欠ける
(アンチエイリアシング、浮動小数点座標、JPG/PNGのサポートなど)
• WIndowsXPは2001年にGDI+と呼ばれる高度なライブラリーを導入
• 大部分はGDI(gdi32.dll)の上に、ユーザーモードgdiplus.dll ライブラリが作られた
• C++や.NET向けに高レベルのインターフェースを提供するため、容易に使用可能
• GDI+はそれ自体C++で書かれているため、典型的なメモリー破損バグが未だに存在
最新: EMF+
• 新しいインターフェースがあるため、新しい画像フォーマットとそのシリアライズさ
れた呼び出しが必要とある
• EMF+にあいさつ!
• 基本的にはEMFと同じだが、GDI+の呼び出しを表す
• 2種類ある:EMF+Onlyと EMF+Dual
• „Only”は専用のGDI+レコードが含まれ、そしてGDI+でのみ表示することができる
• „Dual”はGDI/GDI+クライアント両方と互換性があり、2つのレコードセットが保存されている
Windowsでのフォーマットと実装
• 考慮すべきは3つのフォーマット:WMF,EMF,EMF+
• 3つのライブラリ:GDI,GDI+,MF3216
• vMF3216.DLLは1つの重要な機能を提供するシステムライブラリ:
ConvertEmfToWmf
• Windowsのクリップボード内のWMF/EMFフォーマット間の自動変換する際に使用
• „Synthesized”formatsCF_METAFILEPICTと CF_ENHMETAFILE
• ここにはバグは無かった.L
Windowsでのフォーマットと実装
Library Supportedformats
GDI WMF,EMF
GDI+ WMF,EMF,EMF+
MF3216 EMF
今回の話では、最も(興味深い)問題が見つかったEMFに対する
監査とエクスプロイトにフォーカスする
攻撃シナリオ
• 全ての場合において、メタファイルは対応するDLLでレンダラープロセスのユーザモードコンテキスト
として処理される
• GDI,GDI+,MF3216は全てのレコード入力に対し繰り返しGDI/GDI+の呼び出しに変換する
• メモリ破損のバグは、そのコンテキストで任意のコード実行につながる
• 重要:メタファイルはレンダラーのGDIコンテキストを直接操作する
• プロセスの代わりとして、作成、削除、変更や、さまざまなGDIオブジェクトを使用することができる
• 理論的には、自身のオブジェクトにのみアクセスすべきであり、自己完結である必要がある
• しかし、実装のバグはプログラムによって使用される外部グラフィックスオブジェクトへのアクセスを可能にする
• „権限昇格”の特異なケース
攻撃シナリオ: GDI による権限昇格
renderer.exeGDIobjects EMF#2GDIobjects EMF#3GDIobjects
EMF#1file
EMF#1GDIobjects
GDIプロセス
EMF#2file EMF#3file
セキュリティ境界
攻撃シナリオ: GDI による権限昇格
renderer.exeGDIobjects EMF#2GDIobjects EMF#3GDIobjects
EMF#1file
EMF#1GDIobjects
GDIプロセス
セキュリティ境界
メタファイルのバグのタイプ
1. メモリ破損のバグ
• バッファオーバーフローなど特定レコードの誤った取り扱いによるもの
• レンダリングのいずれかのタイプのエクスプロイトの可能性
• 影響:典型的なリモートからのコード実行(RCE)
2. メモリ漏えいのバグ
• 初期化されていないレンダリング、境界外のヒープメモリーをイメージとして扱う
• 画像のみを表示するコンテキストでは裏を読むことができる (Webブラウザ、リモートレンダラー)
• 影響:情報漏えい(秘密情報を盗む、ASLRの突破など)
3. OSとGDIオブジェクトの誤った管理による不正な相互作用
• 影響、悪用可能性=???、バグの種類による
始めよう!
• 今年の初めから、利用可能なEMFの実装について監査を始めた
• 結果として、MicrosoVから 10のCVE、VMWareから3つのCVEを見つ
けた (実際の数十のバグをカバーする)
• 根本原因と、最も面白いエクスプロイトについてもう少し深く見よう
• レイトして32-bitWindows7に基づいて示しているが、ほとんどの調査内容は
Windows10までの両方のビットバージョンにも適用できる
GDIの監査
入門
• 一般的なアイディアとして、どんな機能が実装され、どんなタイプの
バグが過去に見つかったのか、先行技術を確認することは理にか
なっている
• „wmf脆弱性”での検索でただ一つが見つかる:
SetAbortProcのバグ!
SetAbortProc WMF バグ (CVE-2005-4560)
• 2005/12/27に見つかり、 2006/1/5に修正された
• 致命的なバグであり、GDIを使ったエクスプロイトを動かすと100%確実に
RCEが出来た (例えばInternetExplorer上)
• „Windowsメタファイルの 脆弱性”と呼ばれPwnieAward2007を受賞
• メモリー破損は関係無く、WMFの文書化された機能を使用
• なにがバグだった?
GDIのAPI...
func[onpointer
... そして WMF 側では
本質的には...
...規約自体の呼び出しをサポート:
SetAbortProc(hdc,(ABORTPROC)"controlleddata");
そしてその後呼び出される関数インタ
仕様としてのコード実行
学んだこと
1. フォーマットは(非)公式にプロキシを呼び出し、興味深い/危険な
APIを呼び出し、そのためそれぞれの機能やパラメータは安全でな
い振る舞いをしないかチェックをする必要がある
2. WMFのハンドリングは大きなスイッチ/ケースで起こる
gdi32!PlayMetaFileRecord
EMF バグとは?
• „emfvulnerability”の検索でより多彩な結果が見つかる
• 最新のもの:HosseinLoViによる„YetAnotherWindowsGDIStory”
• MS15-035の一部として2015年4月に修正、CVE-2015-1645が割り当てられた
• レコードの1つ(SETDIBITSTODEVICE) の入力である „size”の未検証による、
ヒープベースのバッファオーバーフロー
• EMFセキュリティを見るには大部分はインスピレーション(が必要)
学んだこと
• EMFレコードを再生するためのメインファンクション gdi32!
PlayEnhMetaFileRecord
• 各レコードタイプはそれぞれ2つの独自のクラスをもっている:
• ::bCheckRecord()–レコードの内部整合性と正確さをチェック
• ::bPlay()–レコード内に示されたアクションを実行
GDI32 ::bCheckRecord array
GDI32 ::bPlay array
ここからが出発点
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
マイナーバグ #1 in EMR_CREATECOLORSPACEW
• 小さいけど明らかなバグを見ることでコードの品質がすぐに認識できた
• MRCREATECOLORSPACEW::bCheckRecord()レコードのサイズが 0x50バイ
ト以上であるこをとチェック:.text:7DB01AEFmoveax,[esi+4].text:7DB01AF2cmpeax,50h.text:7DB01AF5jbshortloc_7DB01B1E
• その後すぐに、オフセット0x25Cの.cbDataフィールドを読み込む:.text:7DB01AF7movecx,[esi+25Ch]
• その結果:0x20Cバイトの範囲外を読み込む
マイナーバグ #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.
}
マイナーバグ #2 in EMR_CREATECOLORSPACEW
• 2つの問題がここに:
1. 明らかな整数オーバーフローにより、大きな.cbDataがチェックを通過
する
2. なぜレコード長は、宣言されたデータよりも小さいのだろうか?それは大きくあるべきだ!
• データはそれ以降の処理で使用されていないので、幸いそんなに大きな問題にはなっていない
マイナーバグ #3 in EMR_CREATECOLORSPACEW
• ユーザ定義 LOGCOLORSPACEW 構造体の .lcsFilenameバッ
ファーはヌル終端のチェックをしていない
• 文字列のアクセス中に範囲外を読みだされる可能性がある
• あきらかなように、多くの未チェックの前提データが多く実装されてお
り、これまではマイナーという扱いであった
• これらはより深刻ななにかにつながるという予測
存在ファイル情報の公開
• EMR_CREATECOLORSPACE[W]レコードの機能に戻る:完全にコントロール
されたLOGCOLORSPACE構造体とCreateColorSpace[W]を呼び出す
typedefstructtagLOGCOLORSPACE{DWORDlcsSignature;DWORDlcsVersion;DWORDlcsSize;LCSCSTYPElcsCSType;LCSGAMUTMATCHlcsIntent;CIEXYZTRIPLElcsEndpoints;DWORDlcsGammaRed;DWORDlcsGammaGreen;DWORDlcsGammaBlue;TCHARlcsFilename[MAX_PATH];}LOGCOLORSPACE,*LPLOGCOLORSPACE;
CreateColorSpaceWの内側
• この関数はカラープロファイルパスを組み立てるのに内部で使用される
gdi32!BuildIcmProfilePath
• 提供されるファイル名が相対的である場合、システムのディレクトリ・パスに追加される
• それ以外の場合は、絶対パスがそのまま残されている
• 全てのパスは"/"または"\"の2文字で始まるものを除き認められている:
if((pszSrc[0]=='\\'||pszSrc[0]=='/')&&(pszSrc[1]=='\\'||pszSrc[1]=='/')){//Pathdenied}
CreateColorSpaceWの内側
• これは多分“\\”プレフィックスで始まるパスは例えば \\192.168.1.13\C
\Users\test\profile.iccのようにリモートUNCのパス指定を想定している
• しかし,JamesForshawはこのチェックが有効でないことを書き示している,
“\??\”のようなプレフィックスでも表記ができるため
• チェックは容易に回避できた:
\??\192.168.1.13\C\Users\test\profile.icc
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);
結果
• その結果,CreateFileW()の呼び出しは任意のパスにすることが
できる
• 成功すれば、カラースペースオブジェクトが作成され、関数が成功を返す
• 失敗した場合は、GDIオブジェクトが作成されず、ハンドラーが失敗を返す
• 情報公開の可能性に聞こえる
• 例えば InternetExplorerでのエクスプロイトにはどのようにアプローチをすれ
ばいい?
直感的な方法: 戻り値をリーク
• CreateFileW()の戻り値がレコード処理の成功を決定することから、
少しリークできるのではないか?
• 最初のアイデア:描画操作に続いて EMR_CREATECOLORSPACEを最初のレ
コードとして使用
• (<canvas>タグで決定することができる)描画が行わなければ,呼び出しは
失敗
直感的な方法: 戻り値をリーク
• 残念ながら不可能
• 関数(PlayEnhMetaFile自身によって呼び出される)gdi32!
_bInternalPlayEMFは1つのレコードが失敗した時にレコード処理は中
断しない
• „success”のフラグがFALSEにセットされ,機能が次のプロセスに進む
• 全てのレコードが常に実行され、戻り値は少なくともプロセス中の1つのレ
コードの失敗したかどうかのフラグを示している
最終的な戻り値をリークすることはできない?
• あまりできない
• PlayEnhMetaFileの戻り値はInternetExplorerの mshtml!
CImgTaskEmf::Decode:によって破棄される
.text:64162B49callds:__imp__PlayEnhMetaFile@12
.text:64162B4Fordwordptr[ebx+7Ch],0FFFFFFFFh
.text:64162B53leaeax,[esp+4C8h+var_49C]
その他の開示オプション
• 他のインジケータはNtGdiCreateColorSpaceを通したカラース
ペースオブジェクトとして作られる
• (すべての可能性を考慮しても)直接の漏えいは簡単ではない、しか
しサイドチャンネルがあったらどうだろう?
GDI オブジェクト使用時の制限
• Windowsの全てのプロセスは、標準でGDIオブジェクトが最大10,000に制限されている
• 数はレジストリで変更できる、しかしIEのためのものではない
• 10,000のファイルパス付きEMR_CREATECOLORSPACEWレコードを確認したいときには:
• ファイルが存在するとき、10,000のカラースペースオブジェクトはプロセスの限界に達する
• ファイルが存在しないときは、カラースペースを全く持たない
• 限界に達しているかどうかという時、(もうひとつ)ブラシを作成しペイントをすると:
• ファイルが存在するとき、ブラシの作成は失敗し標準のブラシが使用される
• ファイルが存在しないとき、ブラシは作成されペイントに使用される
oracle に示されているGDI オブジェクト限界
BitmapFontPaleAe
ColorspaceColorspaceColorspaceColorspace
...ColorspaceColorspaceColorspaceColorspaceColorspaceColorspaceColorspace
限界
Brush
BrushBitmapFontPaleAe
Brush
Brush
ファイルあり: ファイル無し:
デモ
脆弱性のインパクト
• 任意のファイル存在情報が漏えいし、多くの目的で利用可能:
• 標的型の攻撃の際に、特定のソフトウェア(およびバージョン)がインストー
ルされていることを特定できる
• (既知のファイルに基づいてプロファイルを作成することで)ユーザを追跡
• オフラインドキュメントのオープンした時間を追跡(例としてMicrosoVOfficeで
開く度にSMB経由でリモートサーバにpingを送るなど)
• ユーザが利用可能なネットワーク共有を探し出す
Impact: Memorydisclosure
Record: Mul[plerecords(10)
Exploitablein: InternetExplorer
CVE: CVE-2016-3216
google-security-researchentry: 757
Fixed: MS16-074,14June2016
CVE-2016-3216
デバイス独立ビットマップ (DIBs)
WindowsGDIでは、ラスタビットマップは
メモリ上でDIB形式で格納されている:
• オプションパレットに続いてイメージの基
本的なメタデータを含むショートヘッダが
ある
• 画像データそのもの
BITMAPINFO
BITMAPINFOHEADER
RGBQUADbmiColors[...];
Bitmapdata1114221114221114221114221114221114221114221114221114221114221114221114221114221114221114221114221013211013211013211013211013211013211013211013210F12200F12200F12200F12200F12200F12200F12200
.BMP ファイルも DIBsと同じ
BITMAPINFO
BITMAPINFOHEADER
RGBQUADbmiColors[...];
Bitmapdata1114221114221114221114221114221114221114221114221114221114221114221114221114221114221114221114221013211013211013211013211013211013211013211013210F12200F12200F12200F12200F12200F12200F12200
BITMAPFILEHEADERtypedefstructtagBITMAPFILEHEADER{WORDbfType;DWORDbfSize;WORDbfReserved1;WORDbfReserved2;DWORDbfOffBits;}BITMAPFILEHEADER;
bfOffBits
BITMAPINFOHEADER、些細なヘッダ
typedefstructtagBITMAPINFOHEADER{DWORDbiSize;LONGbiWidth;LONGbiHeight;WORDbiPlanes;WORDbiBitCount;DWORDbiCompression;DWORDbiSizeImage;LONGbiXPelsPerMeter;LONGbiYPelsPerMeter;DWORDbiClrUsed;DWORDbiClrImportant;}BITMAPINFOHEADER;
• 短くてシンプルな構造
• 40バイトの長さ(典型的な形)
• 8個だけが重要なフィールド
そんなに簡単な操作なのか?
• biSizeはサニタイズする必要がある(ほんの1-2個の有効な値になれるだけ)
• biWidth,biHeight,biPlanes,biBitCountは整数オーバーフローを起こす可能性
がある(お互いに掛け合わすので)
• biHeightはボトムアップビットマップを示すために負の値を指定できる
• biPlanesは1でなければならない
• biBitCountは{1,2,4,8,16,24,32}のうちの1つでなければならない
• biBitCount<16の場合,カラーパレットを使用できる
• カラーパレットのサイズはbiClrUsedに影響する
その扱いは本当に些細なのか?
• biCompressionは BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS,...とすることができ
る
• 各圧縮方式は正しく処理されなければならない
• biSizeImageは実際のイメージサイズに対応している必要がある
• パレットは全てのエントリーを格納できる充分な大きさが必要
• ピクセルデータバッファは全てのピクセルを情報を入れる充分な大きさが必要
• エンコードされたピクセルはヘッダの値に対応している必要がある(例えばバレットのサ
イズを超えないなど)
多くの潜在的な問題
1. ヘッダにもとづいてDIBを正しく処理をする決定木(decisiontree)は
非常に複雑
2. 多くのやっかいなケースとしては保護とバグを避ける実装をする必
要がある
3. コードの様々な部分では一貫性のある取り扱いが必要
DIB上で (直接)動作するGDI 関数
イメージデータのポインタ
DIBヘッダのポインタ
DIB上で (直接)動作するGDI 関数
データサニタイズの責任
• 全ての場合において、ヘッダとデータが正しく適切であることをチェックする
のはAPI呼び出し元の責任である
• アプリケーションコードが „クローン” GDIによる DIBハンドリングができるよ
うに、完全にユーザが制御可能な入力データを渡すことは問題がある
• 何だと思う?EMFは組み込みDIBを含む複数のレコードをサポートしている
DIBを含むEMFレコード
• EMR_ALPHABLEND• EMR_BITBLT• EMR_MASKBLT• EMR_PLGBLT• EMR_STRETCHBLT• EMR_TRANSPARENTBLT• EMR_SETDIBITSTODEVICE• EMR_STRETCHDIBITS• EMR_CREATEMONOBRUSH• EMR_EXTCREATEPEN
一般的なスキーム
• ヘッダとビットマップの両方のための2組の (offset,size):
EMFレコードハンドラで必要なチェック
• DIBを扱う各ハンドラでは,必須な整合性チェックが4つある:
1. cbBmiSrcはヘッダ内に収まるように充分に大きい事
2. (offBmiSrc,offBmiSrc+cbBmiSrc)は完全にレコード内に存在する事
3. cbBitsSrcはビットマップデータ内におさまるように充分に大きい
4. (offBitsSrc,offBitsSrc+cbBitsSrc)は完全にレコード内に存在する事
チェックは多くの組み合わせで欠落
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はもっと修正をしている可能性がある
結果
• 欠落のチェックのために、イメージ説明の一部は、他のパーツプロセ
スのアドレス空間からロードできる(例 隣接するヒープの割り当て):
• DIBヘッダ
• カラーパレット
• ピクセルデータ
• 初期化されていないか、境界外のヒープメモリはパレットやピクセル
データにより読み出される
Proof of concept
• ファイルを越えたパレットエントリーの8-bppDIBを含む EMR_STRETCHBLTレコードを使用したPoC
をハックした
• 結果:集められたバイトはイメージとして表示される
• 同じ画像がIEの1行に3回表示されている:
• データはHTML5を使用して漏えいしたモジュールアドレスや他の機密情報などを読むことができる
デモ
ATMFD.DLLの監査 間に合わなかったので、カンファレンス後に公開する完全版のSlideDeckを見てください J
GDI+ の監査
GDI+ は充分なターゲット
• GDI+はEMFと EMF+の両方をサポートする
• 多くの実装は独立しているが,フォーマットのいくつかのパーツはGDIのコー
ドから来ている
• したがっていくつかのGDIバグはGDI+のクライアントに影響を与える
• 最も主要なGDI+クライアントはMicrosoVOffice製品
• もう1度EMFレコードハンドラの全体を手動で監査してみよう
攻撃ポイント(アタックサーフェス)は容易に見つかる
攻撃ポイント(アタックサーフェス)は容易に見つかる
いくつか特定のバグを見てみましょう
Impact: Write-what-where
Record: Allrecordsopera[ngonDIBs
Exploitablein: MicrosoVOffice
CVE: CVE-2016-3301
google-security-researchentry: 824
Fixed: MS16-097,9August2016
CVE-2016-3301
EMF中におけるRLE圧縮されたビットマップ
• 前述のように、複数のEMFレコードはDIBを含む
• DIBは4から8ビットのRLEなどの簡単な方式で圧縮ができる
• ヘッダの biCompressionフィールドに示される
• いくつかのハンドラのコードを読むことで、8-ビットRLEはGDI+でサ
ポートされていることを見つけた
• RLE展開は歴史的にバグが多く見つかっている
コードへの到達
DecodeCompressedRLEBitmap
CopyOnWriteBitmap::CopyOnWriteBitmap
CopyOnWriteBitmap::Create
GpBitmap::GpBitmap
CEmfPlusEnumState::PlgBlt CEmfPlusEnumState::RenderBlt
DecodeCompressedRLEBitmap()の内部
• 2つの値は計算される:columns=abs(biHeight)
bytes_per_row=abs(biWidth*(((biPlanes*biBitCount+31)&0xFFFFFFE0)/8))
• 出力バッファはサイズからヒープが割り当てられる
columns*bytes_per_row
• バッファ長を高度にコントロール
• RLE„プログラム”の解釈と実行が始まる
„最終行” 命令コード
• 出力ポインタを次の行に移す(同じオフセットで)
„最終行” 命令コード
• GDI+では,以下の様に実装:
out_ptr+=bytes_per_row;if(out_ptr>output_buffer_end){//Bailout}
• 境界チェックはあらゆる種類の範囲外のアクセスを防ぐために実装されている
• 64ビットプラットフォーム上で正しく動作するように行われるが,状態は本当に充
分なのか?
不十分な検証
プロセスのアドレス空間の終わり0xffffffff
出力バッファ
トリッキーなポインタ演算
• 非常に広いビットマップの場合、現在の出力ポインタからアドレス空間の終
わりまでの距離を走査線の幅よりも小さくすることができる
• 式:
out_ptr+=bytes_per_row;
その後のチェックが効果がなく,オーバーフローを引き起こす
• その結果,出力ポインタを多くの制御可能なアドレスに設定することができる
例
• biWidth=0x05900000
• biHeight=0x00000017
• biPlanes=0x0001
• biBitCount=0x0008
• その結果、columns=0x17と bytes_per_row=0x590000
• 合計バッファ サイズ=0x7FF00000(およそ2GB)
• 配置アドレスの例:0x7FFFF0020、最終位置:0xFFEF0020
メモリアドレス空間レイアウト
0x00000000 0xFFFFFFFF
0x7FFF0020
メモリアドレス空間レイアウト (EOL #1)
0x00000000 0xFFFFFFFF
0x858F0020
メモリアドレス空間レイアウト (EOL #2)
0x00000000 0xFFFFFFFF
0x8B1F0020
メモリアドレス空間レイアウト (EOL #3-22)
0x00000000 0xFFFFFFFF
…
メモリアドレス空間レイアウト (EOL #23)
0x00000000 0xFFFFFFFF
0xFFEF0020
メモリアドレス空間レイアウト (EOL #24)
0x00000000 0xFFFFFFFF
0x057F0020
(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
…
サマリー
• 要件:PAEが有効な32-ビットプロセス
• 4GBアドレス空間全部をプログラムに使用可能にする必要がある
• 結果:どこに何を書くという条件は、„どこ”以上に高度なコントロールが必要
• 特定の値を達成させるだけでなく、上書きされた領域は元の出力バッファ以下の必要あり
• エクスプロイトの確実さはイメージがロードされた時のアドレス空間の状態に強く
依存する
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
ExtTextOutA() と PolyTextOutA()
EMF レコード内のDx 配列
関数の簡単なバグ
• Dx配列はN個の要素であると想定され、Nは表示されているキャラク
タの数
• 以下はレコードサイズの検証チェック:
if(record_size-offString>=nChars&&(!nChars||record_size-4>=record->emrtext.offDx)){//Validationpassed,continueprocessingtherecord.}
• 何かが欠けていない?
関数の些細なバグ
• コードはDx配列が4バイトを保持するかをチェック
• 4×Nバイトを保持することができれば本当に検証をすべき
• 典型的なヒューマンエラーの整合性チェック
• だから何?入力値検証の問題で外の境界を読み出すだけでは?
• はい、エクストラのロジックのためにコードを呼び出さなければ
拡張機能ロジック
• MultiByteToWideChar()を使用して、stringをwide-charへ変換
• コードページは最後に選択したフォントで指定される
• 全ての文字列が変換されたとき,通常
CEmfPlusEnumState::PlayExtTextOut()が呼び出される
• しかしそうでない場合は…
DBCS (ダブルバイト文字セットの)扱い
• 1バイト以上で構成する文字もサポート
• 以下の様に取り扱いが実装されている:
• EMFレコードの正確なコピーが(同じサイズに)配置される
• Dx配列の項目はオリジナルのレコードから新しいものに書き換えられる,„先
行バイト”(IsDBCSLeadByteEx()がTRUEを返す)のエントリを省略
• 新しいレコードが以降通常として処理される
コードパスに到達
• DBCSをサポートするコードページのフォントが最初に選択されなければならない
• 典型的なものはCJK(中国語,日本語,韓国語)のコードページ,例として
SHIFTJIS_CHARSET
• その後,少なくとも1つの„leadbyte”が含まれる影響を受けたレコードの1つは使用されなけ
ればならない
• その結果、境界を越えて他の配置から読み出す典型的なヒープベースのオー
バーフローになる
• heapmassagingにより,制御した上書きを可能にする
ヒープオーバーフローの仕組み
オリジナルのレコード新しいレコード
ヒープ領域
ヒープオーバーフローの仕組み
オリジナルのレコード新しいレコード
ヒープ領域
Dx配列の書き換え
(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
Impact: Heapmemorydisclosure
Record: AllrecordshandlingDIBs
Exploitablein: MicrosoVOfficeOnline
CVE: ?
google-security-researchentry: 825,829
Fixed: MS16-???,11October2016(?)
GDI+ の情報漏えいバグ
GDI+ vs DIB
• GDIとは異なり,GDI+はビットマップの取り扱いに起因する情報漏えいバ
グを避けなかった
• 具体的に:1. „ビットマップの終わり”のマーカーで始まる、RLE圧縮されたビットマップのデータ
ストリームでは,画像の出力バッファ全体が初期化されていない(ジャンクヒープ
データが含まれる)
2. ビットマップパレットが完全にEMFレコードに収まるようになっているかはチェックさ
れない
はっきりと目に見えるバグ
• PoCコードのピクチャをwordに読み込ませると,はっきりとジャンク
データがピクセルとして表示されているのが見える
リモートからの悪用可能性?
• ピクセルが何かに戻せるのでもないので、ヒープメモリを表示することはそんな
にシリアスな状況ではない。
• インタラクティブに出来ないため、バグの唯一のターゲットはOfficeプログラム
• MicrosoVに報告し、深刻度の評価と、攻撃につながる可能性についての評価を
待った
• MSRCはこの事象を„vNext”としてクローズした(毎月のパッチでは修正せず,次
期バージョンなどのタイミングで修正)
深刻度の評価
• これは私自身が考えていた露呈問題の理解と一致しており,決定に同意
した• P0バグの#825と#829はそれぞれ7/26と8/9に解決とした
• 8月の始めに,IvanFratricがチャットで GDI+/EMFのバグはOfficeOnlineにおいてリモートから攻撃につながる可能性があることを伝えてきた
• 私はこのプログラムの存在を知らなかった
• 攻撃可能ではなかったが,特にGDI+のメモリー漏えいのバグは興味深い
• EMFイメージはドキュメント内に挿入できないが,.docxには埋め込みEMFとして可能
Office オンライン
• 数週間前にチェックをしたら…
Office オンライン
• EMFイメージは毎回異なったレンダリングがされる
• MicrosoVのサーバのレンダリングプロセスからリモートのメモリを読み出
せる
• MSRCに再考を求めるために新しい情報を提供
• 彼らはOfficeOnlineのシナリオは以前には考慮されていなかった,それは
修正に値するバグとされた
• 10月の定例パッチまでに修正される必要があった
VMware Workstadonのハック
プリントスプールのEMF
• EMFファイルはプリントスプールに頻繁に使われる
• これはプリンタドライバ(およびその他関連ソフトウェア)の形式で,
フォーマットに起因する攻撃ベクタとして使用される
• 1つのターゲットとしてVMwareWorksta[onを選定
仮想プリンタ
• これは仮想マシンからホストを通してドキュメントの印刷を可能にする昨日(基本的には
プリンタの共有)
• 実現可能なVM回避の攻撃ベクタ
• T私の知る限りでは,2015年まではデフォルトで有効であったが,現在は有効ではない
(KostyaKortchinskyが報告したバグが役立った)
• いまだ頻繁に使用するオプション
構造
VM#3 VM#2 VM#3poc.exe
VirtualMachines
vmware.exe
COM1
vprintproxy.exe
Windows名前付きパイプ
構造
• 攻撃プロセスは vprintproxy.exeが稼働するホスト
• ゲストシステムで非特権プロセスによって送信され、ほぼそのままのデータ
を受信します
• 通信のチャンネル
• データはEMFSPOOLファイルの形式で送られる
• EMFと同様に,追加オプションを指定して、様々な形式のフォントを埋め込む
ことができる
TPView
• 特に,最も興味深いEMF処理は TPview.dllで行われる
• その他プリンタに関するライブラリは,すべてサードパーティのThinPrintで開
発がされていると思われる
• いくつかのレコードタイプの特殊処理は,GDIに処理が戻る
• 全ては簡単なバグではあったが,Kostyaは(ほぼ)全てを見つけた!
• 他を見ていたら,ダブル・フリーとout-of-boundsmemset()を見つけた,それ
らは(問題#848と#849)に含まれる
JPEG2000 デコード
• 完全に未調査であった最後のカスタムEMFレコード
• ID=0x8000
• デバッグ文字列に基づいて,それらは JPEG2000のデコードに関してのもので
ある
• JPEG2Kの専門家でもないので,コードは手動検査にとっては便利で
はないように見えた
• ファジングしてみる?
ファジングによるアプローチ
• ベストなファジング:Linux上で,スケールで,AddressSani[zerを使用してカバレッ
ジフィードバックを待つ
• いくつかの調査後,JPEG2000デコーダーは別のベンダーのLuraTechによって開
発されていることが分かった
• 商用ライセンス,自由に利用できないソースコード
• そのため,我々はVMwareWorksta[onでラップされたTPview.dllで止まった?
• 継続可能だが,より複雑で,遅くて,先進的でない
さらなる調査
• さらなる調査で,同じベンダーがフリーウェアとして人気のIrfanViewプログ
ラムの用にJPEG2000のデコードプラグインを提供して居ることを見つけた
• JPEG2000.DLL.
• 大まかな分析により同じか非常に近いコードをベースとしていることが分かった
• プラグインインターフェースを使用することは非常に簡単で,次の定義に
似ている
HGLOBALReadJPG2000(INPCHARlpFilename,INDWORDdwUnknown,OUTPCHARlpStatus,OUTPCHARlpFormat,OUTLPDWORDlpWidth,OUTLPDWORDlpHeight);
それにより...
• これのおかげで,我々はVMWareを起動することなく,Windows上の
単一プロセスの実装に対しファジングテストを簡単に実施できた
• DLLをロードするラッパープログラムと関連する関数の呼び出しは<50LOC
long
• しかし,私はこれらがLinuxに実装されていることを好むだろうか...
Linux上でのファジングDLL
• なぜない,本当に?
• 望ましいベースアドレスは0x10000000,アドレス空間で利用可能
• 再配置は必要ではない;セクションはそれぞれのアクセス権限があるところにマップされるべき
• その他のアクション:
• 必要なインポートを解決
• エクスポートされた関数のアドレスを取得
• デコードを実行するためにそれを呼び出す
• 動作するはず!
インポートの解決
• インポートテーブルは面倒なポイントでもある
• WinAPI関数はLinux上では提供されていない
• DLLインポート元は ADVAPI32,KERNEL32,MSVCRT,SHELL32と
USER32
• Cランタイムのインポートは直接libcにリダイレクトされる
• 他の全てのものは書き換えられるか少なくともスタブアウトしなければならな
い
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;}
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);}
動いた!
$./loaderJPEG2000.dlltest.jp2[+]Successfullyloadedimage(9b74ba8),format:JPEG2000-Wavelet,width:4,height:4
ファジングの実行
• 内部的に利用可能なJPEG2000の入力ファイルコーバスを使用
• ミューテーションストラテジのレートは成功/失敗が50/50になるように
調整
• 数日間ファジングを実行させて,そして...
• ...186のクラッシュとユニークなスタックトレースが見つかった
クラッシュの再現
• クラッシュはプラグインDLL上のものであって、まだVMwareWorksta[onの
ものではない点に注意
• vprintproxy.exeはとても便利に使える:名前付きパイプを作成しCOM1に
書かれているデータを正確に読み出すことができる
• もう1度、我々は実際のVMを起動せずにテストケースをチェックすることができる
• ページヒープはよりよいバグの検出と重複の排除を可能にする
最終結果
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
最終結果
• 39のユニークなインストラクションでクラッシュが発生
• 多くのものはそんなに正確なメトリックのところでなく memcpy()のような一般
的の機能の様々なポイントで発生
• 簡単に分類:18の低深刻度,15中深刻度,6高深刻度
• 6月15日にVmwareに報告された
• 9月13日(90日以内)にVMSA-2016-0014として修正された
結論
結論
• メタファイルは複雑で興味深いファイルで、研究の価値があるもの• 様々な攻撃ベクタが有効
• システムAPIについていろいろと教えてくれる(i.e.NamedEscapeインター
フェース)
• いつものことだが,古くて曖昧なフォーマット/実装–バグハンター向け
• 以前の成果からのインスピレーションにももっと目を向けよう
• 適材適所–手動のコード監査 vsファジング
ありがとう!
@j00ru
http://j00ru.vexillium.org/
j00ru.vx@gmail.com
top related