More Related Content
Similar to Jurczyk windows metafile_pacsec_jp3 (20)
Jurczyk windows metafile_pacsec_jp3
- 7. どのように描画するか
2. 描画機能を使用
Ellipse(hdc, 100, 100, 500, 300); RoundRect(hdc, 100, 100, 500, 500, 100, 100);
- 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
- 11. Windows メタファイル
• 長所:
• GDI関数が与えられたパラメータで呼び出された時だけ、ラスタライズ処理の計算は
ほとんど必要とされない
• GDIが再現可能な画像を操作するための公式な方法を提供
• ベクター形式、ラスター形式また両方の形式として動作する
• 短所:
• サポートされているグラフィックのGDI操作が外部に完全に実装されていない場合
は、Windows上でのみ動作する
- 12. First version: WMF
• 最初のメタファイル (WMF = Windows MetaFiles).
• 1990年のWindows 3.0 で導入された
• GDIそれ自体のほどではないが、同じくらい古典的
• はじめてドキュメント化されたのは Windows 3.1 SDK (1994年, volume 4)
• 改訂され、より完全な仕様は2006年にリリース、それ以来メンテされ続けている
• 全てのレコードや構造はMS-WMFドキュメントに記載されている
- 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
- 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)}
...
- 20. 次に来たもの: EMF (Enhanced MetaFiles:
拡張メタファイル)
• すでに1993年に、マイクロソフトはEMFと呼ばれる改良版のイメージフォー
マットをリリース
• 公式のMS-EMF仕様としてドキュメント化されている
• 多くの方法でWMFを上回る:
• 16ビットではなく、32ビットのデータ/オフセット長を使用
• デバイスに依存しない
• 古いレコードとの下位互換性を維持しながら、いくつかの新しいGDIコールをサポート
- 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}
...
- 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)
- 37. メタファイルのバグのタイプ
1. メモリ破損のバグ
• バッファオーバーフローなど特定レコードの誤った取り扱いによるもの
• レンダリングのいずれかのタイプのエクスプロイトの可能性
• 影響: 典型的なリモートからのコード実行(RCE)
2. メモリ漏えいのバグ
• 初期化されていないレンダリング、境界外のヒープメモリーをイメージとして扱う
• 画像のみを表示するコンテキストでは裏を読むことができる (Webブラウザ、リモートレンダラー)
• 影響: 情報漏えい (秘密情報を盗む、ASLRの突破など)
3. OSとGDIオブジェクトの誤った管理による不正な相互作用
• 影響、悪用可能性 = ???、バグの種類による
- 41. SetAbortProc WMF バグ (CVE-2005-4560)
• 2005/12/27に見つかり、 2006/1/5に修正された
• 致命的なバグであり、GDIを使ったエクスプロイトを動かすと100%確実に
RCEが出来た (例えば Internet Explorer上)
• „Windows メタファイルの 脆弱性”と呼ばれ Pwnie Award 2007を受賞
• メモリー破損は関係無く、WMFの文書化された機能を使用
• なにがバグだった?
- 47. EMF バグとは?
• „emf vulnerability”の検索でより多彩な結果が見つかる
• 最新のもの: Hossein LoViによる„Yet Another Windows GDI Story”
• MS15-035の一部として2015年4月に修正、CVE-2015-1645が割り当てられた
• レコードの1つ(SETDIBITSTODEVICE) の入力である „size”の未検証による、
ヒープベースのバッファオーバーフロー
• EMFセキュリティを見るには大部分はインスピレーション(が必要)
- 53. マイナーバグ #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バイトの範囲外を読み込む
- 54. マイナーバグ #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.
}
- 55. マイナーバグ #2 in EMR_CREATECOLORSPACEW
• 2つの問題がここに:
1. 明らかな整数オーバーフローにより、大きな.cbDataがチェックを通過
する
2. なぜレコード長は、宣言されたデータよりも小さいのだろうか?それ
は大きくあるべきだ!
• データはそれ以降の処理で使用されていないので、幸いそんなに大
きな問題にはなっていない
- 56. マイナーバグ #3 in EMR_CREATECOLORSPACEW
• ユーザ定義 LOGCOLORSPACEW 構造体の .lcsFilename バッ
ファーはヌル終端のチェックをしていない
• 文字列のアクセス中に範囲外を読みだされる可能性がある
• あきらかなように、多くの未チェックの前提データが多く実装されてお
り、これまではマイナーという扱いであった
• これらはより深刻ななにかにつながるという予測
- 63. 直感的な方法: 戻り値をリーク
• 残念ながら不可能
• 関数 (PlayEnhMetaFile 自身によって呼び出される) gdi32!
_bInternalPlayEMF は1つのレコードが失敗した時にレコード処理は中
断しない
• „success” のフラグが FALSEにセットされ, 機能が次のプロセスに進む
• 全てのレコードが常に実行され、戻り値は少なくともプロセス中の1つのレ
コードの失敗したかどうかのフラグを示している
- 66. GDI オブジェクト使用時の制限
• Windowsの全てのプロセスは、標準で GDIオブジェクトが最大 10,000に制限されている
• 数はレジストリで変更できる、しかしIEのためのものではない
• 10,000のファイルパス付きEMR_CREATECOLORSPACEWレコードを確認したいときには:
• ファイルが存在するとき、10,000のカラースペースオブジェクトはプロセスの限界に達する
• ファイルが存在しないときは、カラースペースを全く持たない
• 限界に達しているかどうかという時、(もうひとつ)ブラシを作成しペイントをすると:
• ファイルが存在するとき、ブラシの作成は失敗し標準のブラシが使用される
• ファイルが存在しないとき、ブラシは作成されペイントに使用される
- 74. そんなに簡単な操作なのか?
• biSize はサニタイズする必要がある (ほんの1-2個の有効な値になれるだけ)
• biWidth, biHeight, biPlanes, biBitCount は整数オーバーフローを起こす可能性
がある (お互いに掛け合わすので)
• biHeight はボトムアップビットマップを示すために負の値を指定できる
• biPlanes は1でなければならない
• biBitCount は {1, 2, 4, 8, 16, 24, 32}のうちの1つでなければならない
• biBitCount < 16の場合,カラーパレットを使用できる
• カラーパレットのサイズはbiClrUsedに影響する
- 85. Proof of concept
• ファイルを越えたパレットエントリーの8-bpp DIB を含む EMR_STRETCHBLTレコードを使用したPoC
をハックした
• 結果: 集められたバイトはイメージとして表示される
• 同じ画像がIEの1行に3回表示されている:
• データはHTML5を使用して漏えいしたモジュールアドレスや他の機密情報などを読むことができる
- 89. GDI+ は充分なターゲット
• GDI+ はEMF と EMF+の両方をサポートする
• 多くの実装は独立しているが, フォーマットのいくつかのパーツはGDIのコー
ドから来ている
• したがっていくつかのGDIバグはGDI+のクライアントに影響を与える
• 最も主要な GDI+クライアントはMicrosoV Office 製品
• もう1度EMFレコードハンドラの全体を手動で監査してみよう
- 122. GDI+ vs DIB
• GDIとは異なり, GDI+ はビットマップの取り扱いに起因する情報漏えいバ
グを避けなかった
• 具体的に:
1. „ビットマップの終わり”のマーカーで始まる、RLE圧縮されたビットマップのデータ
ストリームでは , 画像の出力バッファ全体が初期化されていない (ジャンクヒープ
データが含まれる)
2. ビットマップパレットが完全にEMFレコードに収まるようになっているかはチェックさ
れない
- 133. TPView
• 特に, 最も興味深いEMF処理は TPview.dllで行われる
• その他プリンタに関するライブラリは, すべてサードパーティのThinPrintで開
発がされていると思われる
• いくつかのレコードタイプの特殊処理は, GDIに処理が戻る
• 全ては簡単なバグではあったが, Kostya は(ほぼ)全てを見つけた!
• 他を見ていたら, ダブル・フリーと out-of-bounds memset()を見つけた, それ
らは (問題 #848 と #849)に含まれる
- 146. 最終結果
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