Bohan pac sec_2016_jp
Transcript of Bohan pac sec_2016_jp
Tyler Bohan - @1blankwall1 PacSec 2016
ゾーンの中 : OS X のヒープ エクスプロイテーション
自己紹介
• Tyler Bohan – シニアリサーチエンジニア – Cisco Talos所属
• チーム員 – Aleksandar Nikolich – Ali Rizvi-Santiago – Cory Duplantis – Marcin Noga – Piotr Bania – Richard Johnson – Yves Younan
• Talos の研究開発 – サードパーティーの脆弱性研究
• 過去12ヶ月で170の脆弱性を発見 – Microsoft – Apple – Oracle – Adobe – Google – IBM, HP, Intel – 7zip, libarchive, NTP
– セキュリティツールの開発
• Fuzzers, Crash Triage
– 緩和策の開発
• FreeSentry
なぜこの分野の研究を?
• 画像に関するヒープオーバーフローが見つかり、エクスプロイトに至った
• OS X の標準のmalloc実装についての最新ドキュメントがあまりない
• オーバーフローが意図しない副作用を起こさないと保証する必要がある
なぜこの分野の研究を?
• ヒープスプレーは信頼性がなく、エレガントでもない — 時代遅れ
• ヒープアルゴリズムの深い知識は相対的なチャンク配置を考えるうえで重要である
• すでに解放されたブロックがヘッダを破壊やエラーを起こしながら絶えず実行される
過去の研究 • Insomnia • https://www.insomniasec.com/downloads/
publications/Heaps_About_Heaps.ppt • Immunity
• http://www.slideshare.net/seguridadapple/attacking-the-webkit-heap-or-how-to-write-safari-exploits
• Phantasmal Phantasmagoria • Chris Valasek
• https://media.blackhat.com/bh-us-12/Briefings/ValasekBH_US_12_Valasek_Windows_8_Heap_Internals_Slides.pdf
• Etc.
過去の研究 (OS X)
• OS X Heap Exploitation Techniques - 2005 • Nemo
• Mac OS Xploitation (and others) - 2009
• Dino A. Dai Zovi • Cocoa with Love - How Malloc Works on Mac - 2010
• Matt Gallagher
OS X • El Capitan (10.11.5) での研究が完了
• ツール実装のマイナーチェンジは容易
• 現在のバージョン(10.11.6)はこれまでのところとてもよい 😋 (Sierra ベータ版)
• Scalable Malloc – OS X Hackers Handbookに掲載 • Magazine Malloc - El Capitanでの標準確保方法
ロードマップ
• ヒープ構造 - 退屈 (重要) • ヒープ戦略 – とても楽しい (ユニークな技術)
• エクスプロイト戦略 - 楽しい (全てを一緒に)
ヒープ入門 (?)
ヒープの実装
• Magazine allocator – これから解説 • Scalable allocator – 古いOSX の確保方法 • JEmalloc – Jason Evansによる実装 (bsd) • DLmalloc – Doug Leaによる実装 (glibc) • PTmalloc – Wolfram Glogerによる実装 (newer-glibc) • TCmalloc – Webkitの一般的な確保方法 (google) • Lookaside List – Windowsの実装(以前のもの) • LF Heap – Windowsの実装(最新) • Etc.
ヒープ実装 • DL Malloc, TC Malloc, JE Malloc, etc…
• 最近解放されたキャッシュ、ソートチャンクを使用
• 一般的にはリンクリスト/メタデータ、アリーナなどの間でハイブリット
• チャンクベースのアロケータはメタデータヘッダ付きのチャンクを前に付け、利用可能な異なるチャンクを分割またはナビゲートすることができる。
ヒープの実装方法
Heaps about Heaps - Insomnia
リンクリストのアロケータ:
ヒープ実装
• Magazine Allocator, LFH, BSD malloc etc…
• アリーナベースのアロケータは各ページに同サイズのグループ確保をする傾向がある
• 確保されたオブジェクトは効率的に解放される
ヒープの実装方法
0x100200030(2Q) 0x100200070(4Q) 0x100200100(6Q) 0x100200560(8Q)0x100200010(1Q)0x100200180(1Q)0x1002001A0(1Q)
0x100200180(4Q)
OS X の話に少し逸れて
OS X – CoreFoundat ion
• 下位レベルのAPIに引数を渡すために様々な上位レベルの型が含まれている
• これらには CFDictionary, CFSet, CFStringなどのものが含まれている.
• 参照とガベージコレクションポインタ: CFRetain/
CFRelease
OS X – CoreFoundat ion
• システムのmallocを使用して、このようなハッシュテーブルを確保
• ヒープの状態変更のために、初期化コードが標準ヒープに割り当てられる — 詳しくは後で
• CoreFoundationからヒープオブジェクトの上書きが可能 • WebKit とSafari では様々な確保が使用される
OS X – Magazine Al locator
• ヒープユーティリティを提供 • Guard Malloc
• ページヒープのようなもの • OpenBSD アロケータ — オリジナル
OS X – Magazine Al locator
• Malloc スタックロギング: • デバッグフラグを必要とする - MallocStackLogging • ヒープレイアウトを変更
• LLDB の malloc_info
• lldb.macosx.heap をインポートするスクリプト • malloc_info -s 0x1080715e0
OS X – Magazine Al locator
• Malloc スタックロギング: • ターミナルからのmalloc_history
• 詳細の出力 • プログラムヒストリー全てで、mallocとfreeのための全スタックフレーム
• 現在の割り当てられたスタックフレームだけでなく
OS X – Magazine Al locator
• Malloc スタックロギング:
OS X ヒープ
OS X – Al locators
• Malloc Zones • アプリケーションによって使用される複数のヒープ実装を管理
• 各ゾーンには、識別のためのバージョンと名前が含まれている
• Scalable Allocator (version=5) • Magazine Allocator (version=8) • mmap/munmap でマップ/アンマップをする
OS X – Magazine Al locator
• 使用されている: • デフォルトCRT mallocを呼び出すもの • libsystem_malloc.dylib, CoreFoundation, etc. • プレビュー、ColorSync、Safari、Keynoteなど…これらのコンポーネントを通して到達可能
• 使用されていない:
• Webkit (Objective-c, libxpc, renderersなどのマイナス低レベルのもの)
• ImageIO コピーの内部に実装
OS X – Magazine Al locator
• フリーリストは他アロケータ上でバケットリストと比較 • ポインタ用のクッキー/チェックサムが含まれている
// Because the free list entries are previously freed objects, a misbehaved // program may write to a pointer after it has called free() on that pointer,// either by dereference or buffer overflow from an adjacent pointer. This write// would then corrupt the free list's previous and next pointers, leading to a// crash. In order to detect this case, we take advantage of the fact that // malloc'd pointers are known to be at least 16 byte aligned, and thus have// at least 4 trailing zero bits.//// When an entry is added to the free list, a checksum of the previous and next// pointers is calculated and written to the low four bits of the respective// pointers. Upon detection of an invalid checksum, an error is logged and NULL
OS X – Magazine Al locator
• それぞれの リージョン/アリーナ はコアか“magazine” に決められる
• コアあたり1つのMagazine. “depot” と呼ばれるfreeの領域にある特別なMagazine
• 割り当てサイズは3種類に分けられる (tiny, small, large)
OS X – Magazine Al locator
• Tiny と Small アロケータは “Quantum” (Q)という単位で管理されている
• 各magazineは短期のメモリ確保のための単一割り当てキャッシュを持っている
すなわち
NSNumber* myNumber = [NSNumber alloc]
OS X – Magazine Al locator
• Tiny アロケーション (16Q) – 最大サイズは 1008 • Small アロケーション (512Q) – 最小サイズは 1009 • Large アロケーション (サイズはゾーンで定義され、“hw.memsize“のsysctlに基づいて定義されている)
OS X – Magazine Al locator
• 全ての割り当てはリージョンとして知られるアリーナから来ている
• フリーリストはQの数によってインデックスされたリンクトリスト
• チャンクがフリーリストに移行して結合される
• depot内のリージョンが空の場合、リージョンはOSに戻される
Magazine Al locator – T iny Al locat ions
• チャンクはtinyリージョンによって配置される • 1Q (16 bytes) から 63Q (1008 bytes)までに配置 • リージョンは常に0X100000バイト(0x100ページ)のサイズ
• 64520 のQサイズのブロック割り当てが含まれる • Tinyメタデータは2つのビットマップに記載:
1つはどのブロックがチャンクの始まりか もう1つはチャンクがビジー/フリーであるか
Magazine Al locator – Smal l A l locat ions
• チャンク はsmall リージョン (Q = 512b)から配置 • 1Q (1008 / 512b) から szone.large_threshold までの配置
• リージョンは常に 0x800000 バイト (0x800 ページ) のサイズ
• 16320 のQサイズのブロックが含まれる • メタデータはそれぞれのブロックを表すuint16_t のシンプルなリストで、Qの数は次を示す
• それぞれのuint16_t の高ビットはフリー/ビジーを示す
Magazine Al locator – Large Al locat ions • szone.large_threshold よりも大きい
* sysctl のhw.memsize beingで定義 > 230
• 循環連結リストとキャッシュによって管理される • 特定のフラグメンテーションがしきい値に達するまでキャッシュされる
• フラグメンテーションがしきい値に達すると、OSに戻される
• このプレゼンではこれ以上は追求しない - エクスプロイト目的としては実用的でないので
OS X – Magazine Al locator
• スレッドマイグレーション
• ユーザスペースからカーネルへ移るときにコア間のスレッドは移行する
• カーネルは、異なるコア上でスレッドを呼び出すことができる!
OS X – Magazine Al locator
• スレッドマイグレーション
• コアは magazine を決める • magazine はヒープレイアウトを決める
• コアに移行するときは正確なヒープの操作が困難、または不可能になる
OS X – Magazine Al locator
• スレッドマイグレーション
• 特許によって保留された情報について
OS X – Magazine Al locator
• スレッドマイグレーション – どのように扱う?
• スレッドを占有してコア切り替えを防ぐようにする • すなわち タイトループなど…
OS X – Magazine Al locator
• スレッドマイグレーション – どのように扱う? • 5つのイテレーションの 利用可能対ブロッキングの差
• 利用可能 = ~460,000 イテレーション
• ブロッキング = ~860,000 イテレーション
Magazine Allocator の構造
Magazine Al locator
• 三つの異なる割り当てタイプを管理するために様々な構造によって結ばれている
• 任意の割り当てのために、リージョンに付随するmagazineをそれぞれのコアに関連づける試み
• OSに戻すためにアリーナとリージョンが空になることを追跡
• 大規模にキャッシュされた領域を再利用するために、大規模な割り当てと断片化を追跡
Magazine Al locator
• 各magazine は非常に短時間の割り当てに使われる単一キャッシュを確保する
• 各 magazine はすぐにリージョン内のフリーチャンクを識別するためにQによってインデックスされたフリーリストが含まれている
• フリーチャンクは前方、後方のまとめ(Coalescing)を支援するためにメタデータを含んでいる
• リージョンはそれがどれくらい使用しているか、使用中であるかを表現するためのメタデータを含んでいる
Malloc ゾーン
Magazine Al locator – mal loc_zones
• ゾーン: • バージョンの種類
• 一つのコンテナーにおいて複数の異なるmallocをサポートする機能
• 主な機能は拡張性 • 多くの割り当て方式を扱うことができる • Safariが可能とするようなプラットフォームを作る
Magazine Al locator – mal loc_zone_t
struct malloc_zone_t {… funcptr_t* malloc; funcptr_t* calloc;… const char* zone_name;… struct malloc_introspection_t* introspect; unsigned version;…}
struct malloc_introspection_t {… funcptr_t* check; funcptr_t* print; funcptr_t* log;… funcptr_t* statistics;…}
Magazine Al locator – mal loc_zone_t
• 一般系な構造は各mallocを識別するために使用される • Zone_Name – 識別子を持つ文字列へのポインタ • Version – uint32_t アロケータの種類を識別する • 異なるため、関数ポインタが含まれる
• エントリーポイント: malloc, free, calloc, etc • イントロスペクション: size, memalign,
pressure_relief, etc • Szone_t はPhrackの記事でNemoが攻撃
Magazine Al locator – mal loc_zone_t
• Phrack の余談
• Szone_t 上書き - 新しいszoneの作成が必要で有り実用的でない
• バグが包まれる - 64bit環境ではクラッシュする
• ダブル・フリー - もう1度チェック
Magazine Al locator – szone_t
struct szone_t { malloc_zone_t basic_zone;… unsigned debug_flags; …tiny allocations... …small allocations... unsigned num_small_slots; …large allocations... unsigned is_largemem; unsigned large_threshold; uintptr_t cookie;...}
• ポインタ・サイズと、難読化が意図されているポインタはxorをとる
Magazine Al locator – szone_t
• エンコードされたポインタはポインタの上位4ビットの内の4ビットのチェックサムが含まれる
• 難読化されたPTRは、チェックサムptrを介して変換される:
csum := pointer ^ cookie • ポインタを経由してチェックサムを抽出: rol(csum,4) &
0xF
Magazine Al locator – szone_t static INLINE uintptr_tfree_list_checksum_ptr(szone_t *szone, void *ptr) { uintptr_t p = (uintptr_t)ptr; return (p >> NYBBLE) | (free_list_gen_checksum(p ^ szone->cookie) << ANTI_NYBBLE); // compiles to rotate instruction}
0x100103310 0x233688 0x100330598^ = 0x100330598Checksum( ) = 1
,4) | Checksum(…) =0x100103310ror( 1000000010010331
struct szone_t {... size_t num_tiny_regions;... region_hash_generation_t* tiny_region_generation; region_hash_generation_t[2] trg;
int num_tiny_magazines;... magazine_t* tiny_magazines;... unsigned num_small_slots;… region_t[64] initial_tiny_regions;…}
64
Magazine Al locator – t iny szone_t
struct region_hash_generation_t { size_t num_regions; size_t num_regions_shift; region_t*[num_regions] hash_regions; region_hash_generation_t* nextgen;}
Magazine Al locator – smal l szone_t struct szone_t {... size_t num_small_regions;... region_hash_generation_t* small_region_generation; region_hash_generation_t[2] srg;
int num_small_magazines;... magazine_t* small_magazines;… unsigned large_threshold;… region_t[64] initial_small_regions;…}
struct region_hash_generation_t { size_t num_regions; size_t num_regions_shift; region_t*[num_regions] hash_regions; region_hash_generation_t* nextgen;}
Magazine Al locator – large szone_t struct szone_t {... unsigned num_large_objects_in_use; unsigned num_large_entries; large_entry_t* large_entries; size_t num_bytes_in_large_objects;... int large_entry_cache_oldest, large_entry_cache_newest; large_entry_t[16] large_entry_cache;... unsigned large_threshold;...}
Magazine_T
Magazine Al locator – magazine_t
• 1つのmagazineはコア毎に割り当てられる. “depot”のための+1. • depotはプレースホルダーmagazineとして使用 • スロット -1 にインデックス • 使われることはなく、解放されたリージョンのキャッシュに使われる
• コアにローカルリージョンをバインドするために使用
• depotのために解放された後で、リージョンはmagazine間を移動する
Magazine Al locator – magazine_t
• チャンクキャッシュ、ビットマップフリーリスト、割り当てに使われるための最後のリージョン、全リージョンのリンクリストが含まれる
• 現在のリージョンから割り当てを管理するための使用統計情報を監視
struct magazine_t {... void* mag_last_free; region_t mag_last_free_rgn;... free_list_t*[256] mag_free_list; unsigned[8] mag_bitmap;... size_t mag_bytes_free_at_end, mag_bytes_free_at_start; region_t mag_last_region;... unsigned mag_num_objects; size_t mag_num_bytes_in_objects, num_bytes_in_magazine;... unsigned recirculation_entries; region_trailer_t* firstNode, *lastNode;...}
Magazine Al locator – magazine_t
1110000000011001110001100001111XXX
Linked list of all regions
Local magazine cache
Magazine Al locator – magazine_t
• 統計 • Mag_bytes_free_at_Start
• Mag_num_objects
• 利用可能な連続スロット数 - それぞれ フリーとビジーで
使用 利用可能
リージョンmag_bytes_free_at_endmag_bytes_free_at_start
Magazine Al locator – magazine_t
• mag_last_free cache – 短期割り当て= • Qサイズはポインタとともにエンコードされる • Tiny Q=16, 下位4ビットは、Qサイズを表す • Small Q=512, 下位 9ビットは 、Qサイズを表す • 残りのビットはチャンクとポインタが含まれる
0x100101436 Pointer: 0x100101430Quantum: 6Q = 96 bytes
0x100f09ee1f Pointer: 0x100f09ee00Quantum: 31Q = 15872 bytes
tiny
small
Magazine Al locator – magazine_t Mag_free_bitmap 追加されるフリーエントリーが表される
Mag_free_list
フリーチャンクの循環リストが示される
Magazine Al locator – magazine_t
• Magazine フリーリスト • 全てのフリーチャンクの循環リストを示す • 次とフリーのポインターがチェックされる • チェックサムはポインタ上位4ビットで符号化 • ポインタは右に4ビットローテートされ、その後
4ビットチェックサムとOR演算 • チャンクが結合中の場合はチェックサムはチェックされない
0x300000001002032b 0x1002032b0Next Pointer in Chunk Actual Pointer
Magazine Al locator – magazine_t
• チャンクがキャッシュからフリーリストに遷移時(?) • 循環リンクリストはチャンクに書かれる • チャンクが>1Qのとき(Q)のサイズはチャンクの末尾に書かれる。
• 前後でまとめる(Coalescing)時に使用
Magazine Al locator – t iny magazine_t
• フリーリストは256スロットを所有し、64のみ使用 • szone.num_small_slots によって定義
• いくつかのデットスペースは最大1008まで
• NUM_SMALL_SLOTS = 64
Magazine Al locator – smal l magazine_t
• フリーリストは使用可能な256スロット全てを使用 • 大きなしきい値に基づいて • 一般的に 0x1fc00 / 512 == 254
Region_T
Magazine Al locator – region_t
• 2つの異なるタイプ “tiny” と “small” のアロケータ
• チャンクはQ上で分割されたチャンク数で構成: Tiny = 16 bytes, Small = 512 bytes.
• リージョン+メタデータ+リージョントレイラーのサイズがベースとして計算されたQサイズブロックの数が含まれる
Magazine Al locator – region_t
• メタデータはチャンクサイズ、チャンクがビジーかフリーかを示す情報を持っている
• Tiny メタデータはheader/in-useの各ビットからリージョンブロックマッピングしている
• Small メタデータは各uint16_t からブロックを直接マッピングしている
Magazine Al locator – region_t typedef uint8_t[Q] Quantum_t;
struct region_t { Quantum_t[NUM_BLOCKS] blocks; region_trailer_t trailer; metadata_t metadata;}
struct tiny_metadata_t { tiny_header_inuse_pair_t[NUM_BLOCKS / sizeof(uint32_t)] blocks;}
struct small_metadata_t { uint16_t[NUM_BLOCKS] msize;}
struct tiny_header_inuse_pair_t { uint32_t header, inuse;}
* メタデータはregion_tのブロックと直接相関している
Magazine Al locator – t iny region_t
• Tiny メタデータ – 2つのuint32_tと構造体の配列 1. ブロックはチャンクの始まりであるかどうかをビットで示す (Qでチャンクサイズを計算するために使用).
2. ビットはチャンク全体がbusy(1) か free(0)かを示す
Magazine Al locator – smal l region_t
• Small メタデータ – エンコードされた uint16_t 配列 • 高ビットはbusy(0) か free(1)を示す • 残りのビットはチャンクのためのQの数を示す • Qは、次のチャンクまでいくつの要素をスキップするかを示す
Magazine Al locator – large regions
• Large リージョン • シンプル、ただアドレスとそのサイズ • ひどく断片化するまでアンマップされない • キャッシュに格納
typedef struct large_entry_t { vm_address_t address; vm_size_t size; boolean_t did_madvise_reusable;}
Magazine Al locator – region_tra i ler_t
• 各リージョンはmagazineがどれに連携するか知っている • magazine_tがトレイラーを指し、magazineが全てのリージョンへの繰り返しを許すようにナビゲートする
struct region_trailer_t { struct region_trailer* prev, *next; boolean_t recirc_suitable; int pinned_to_depot; unsigned bytes_used; mag_index_t mag_index;}
depot magazine?
Linked list of all magazines in a region
Magazine whom retains ownership
戦略
Strategies – for cache
• Mac Heapと呼ぶツール • LLDB python スクリプトで全ての情報にアクセスできる • オープンソース 🤑
Strategies
• ポジショニング • 戦略的なブロック配置、キャッシュ管理
• オーバーライト • ブロックをFree (解放)の前か後のチャンク、busy (使用中)のチャンクに配置
• メタデータ • Unlinking attacks
Strategies – for cache
• キャッシュ • キャッシュを空に
• キャッシュオブジェクトとしてのMallocの正確なサイズ
• キャッシュからフリーリストへ
• 256b(tiny)未満の他のフリーオブジェクト • 新しいオブジェクトをキャッシュへ、キャッシュオブジェクトからフリーリストへ移動
Strategies – for f ree l is t
• フリーリスト • リンクリスト • Quantum(Q)サイズ毎にインデックス化されている • Tiny - 64 slots — Small - 256 slots • Smallの最小サイズである1009では、割り当て不可能なため1Qを使用することができない
• Q = 512 - 512という1Qのtinyリージョンへの割り当ては"dead"になる
• まとめる(Coalescing) – チャンクがフリーリストに移動された場合 • ForwardQ/BackwardQ – >1Q のチャンクへ書かれたとき
• ForwardQ か BackwardQ が上書きされたとき、特定のカウントはフリーチャンクを指す必要がある
• フリーリストにチャンク全体を追加する(任意の使用ずみチャンク間での使用を含む)
St rategies – mag_free_l is t
11111111111011110011000111111111111111111111111111111111111111111111111111111111
Strategies – mag_free_l is t – Coalesce
Overwrite chunk with 2Q + 3Q bytes data.Set BackwardQ to 12 (3+2+7).
Freeing Busy chunk will coalesce with 3Q Chunk and use overwritten BackwardQ of 12 joining 2Q chunk with 7Q chunk.
Due to BackwardQ being 12. Freeing 5Q chunk will read BackwardQ and add 7Q+2Q+3Q (12Q) to free list
whilst chunk still being by program.
111111111101111001100000000111111111111111111111111111111111111111111111111
Strategies – mag_free_l is t
• Forwards まとめ(Coalesce) – realloc() かキャッシュがフリーリストに移行するとき • フリーチャンクのForwardQは、まとめにどれだけ遠いか、 reallocにどれだけ遠いかを決めているように見える...
• 完了時、フリーリストに追加される
111111111111111110000001110111111111111111111111111111111111
Strategies – mag_free_l is t – Coalesce
Overwrite Busy with 2Q data to get to Free. Write 4+4 (8Q) into Free’s ForwardQ.
If Busy Chunk gets free’d, 2Q+4Q+4Q (10Q) gets added to free list. 3Q still in use by program.
Similarly if Busy Chunk gets realloc’d, The different of 8Q and the new allocation size gets added to the free list where 3Q chunk is still in use.
111111111111111111100001110111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111
Strategies – mag_free_l is t
• 解放されたチャンクの先頭にリンクリストを上書き • アンリンクによるWrite 4- 全く使えないASLR - 正しいチェックサムは大体7%の確率になる
• リンクリストのポインタがNULLの場合、チェックサムは0になる. 残念ながら、mag_bitmapのビットはクリアされる.
• ビットマップにビットをセット、まとめたエントリーへのアクセスを回復には、他のチャンクからフリーリストへ移る必要がある.
Strategies – mag_free_l is t
• フリーリストからの割り当て - 4Q
101001100001111111110000001010111111111111111111111111000011111111111111111111111111111111000000000111111
Region_t – 0x100200000
0x100200030(2Q) 0x100200070(4Q) 0x100200100(6Q) 0x100200560(8Q)0x100200010(1Q)0x100200180(1Q)0x1002001A0(1Q)
0x100200180(4Q)
Strategies – for f ree l is t
キャッシュを見て、きちっと一致?
yes? 割り当て
フリーリストインデックス, Q-1, 合致?
yes?
フリーリストから, スロットが見つかる?
yes?
リージョンからの割り当て
Strategies – for region
• リージョンからの割り当て • 現在の使用されているバイト数を計算 • リージョンベースアドレスへ追加 • 必要なスペースを確保 • freeされたものはフリーリストに戻る
使用 利用可能
リージョンmag_bytes_free_at_endmag_bytes_free_at_start
デモ
• シングルコアスクリプト
script import onemagbreakpoint set -N singlemag1 -s libsystem_malloc.dylib -a 0x262abreakpoint set -N singlemag2 -s libsystem_malloc.dylib -a 0x2a6abreakpoint set -N singlemag3 -s libsystem_malloc.dylib -a 0xb95dbreakpoint set -N singlemag4 -s libsystem_malloc.dylib -a 0xbd43breakpoint command add -F onemag.cont singlemag1breakpoint command add -F onemag.cont singlemag2breakpoint command add -F onemag.cont2 singlemag3breakpoint command add -F onemag.cont2 singlemag4
Strategies – for region
• リージョンビットマップ • ビットマップフィッティング
• リージョンビットマップ内部の単一で少量のスロットを埋め、リージョンビットマップになる
• 利用リージョンの終わりに次のスロットを割り当て • ともにスロットを割り当て
Strategies – for region Fragmented BitmapIn Use = 1 Free = 0
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110100110000111111000000111111000000001111111111111111111111111111000000000000000000000011111111111111111111000000000000011111111111111111111111111111111111
>>>region.getoffset()0x100200000>>>region.bitmap()
>>> len(region.bitmap())901
Strategies – for region >>> print magazine.dump()[1] 0x100202eb0[2] 0x100202ed0[4] 0x100202f10[6] 0x100202fb0[8] 0x100203070[13] 0x100203550[22] 0x1002032b0
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110100110000111111000000111111000000001111111111111111111111111111000000000000000000000011111111111111111111000000000000011111111111111111111111111111111111
>>>region.getoffset()0x100200000>>>region.bitmap()
Strategies – for region
>>>t['mag_free_list'].quantum()56
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110100110000111111000000111111000000001111111111111111111111111111000000000000000000000011111111111111111111000000000000011111111111111111111111111111111111
Strategies – for region
56の単一で少量の割り当てがビットマップを平坦にする
Strategies – for region Fragmented BitmapIn Use = 1 Free = 0
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
region.bitmap()
>>> len(region.bitmap())901
Strategies – for region
次の割り当てがビットマップを必要な量にする(その後、リージョンも)
Strategies – for region Fragmented BitmapIn Use = 1 Free = 0
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
region.bitmap()
>>> len(region.bitmap())925
Strategies – Scoping bugs(?)
• ダブルフリー
• メタデータとキャッシュに対し明示的にチェックしているのでフリーできない
Strategies – Scoping bugs(?)
• ヒープスプレー
• 境界の先頭にブロック (0x100000 - tiny) (0x800000 - small)
• 0xXXXFC080 から 0xXXXFFFFF - tiny 構造体
• 0xXX800000 から 0xXXFF8000 - small 構造体
デバッグの戦略
LLDB In i t
• LLDBは機能性に欠ける • ページプロテクションを見る • メモリをダンプする • 式の取り扱い • etc
LLDB In i t
• 詳細すぎるコマンド(限定された機能)
• breakpoint set -a `(void()) main`
• breakpoint command add -o “x/x $rax” 1
LLDB In i t
• LLDBは機能性に欠ける • 難しかったり扱いにくいようないくつかのコマンド
• LLDB内部のPythonの機能は非常に面倒
LLDB In i t
• 機能を追加する一般的な方法が提供 • エイリアスとブレイクポイント管理
• 内蔵されている完全なパーサは、WinDBGのようなブレイクポイント管理やコマンドを提供
• ie. poi(main+$rax+local_1)
エクスプロイトの戦略
Safar i • 5つの mallocゾーン
• Default Malloc - version 8 (magazine alloc)
• GFX Malloc - version 8 (magazine alloc) • WebKit Malloc - version 4 (bmalloc)
• Quartz Core Malloc - version 5(scalable alloc) • Default Purgeable Malloc - version 8(magazine alloc)
Safar i
• 5つの malloc ゾーン
脆弱性の詳細
• 画像ベースのヒープオーバーフロー
• Core Foundation -> ImageIO
• Default malloc ゾーン
• ImageIO は独自の mallocを持っている (ImageIOMalloc) – ほとんどに使われている :)
Explo i tat ion Strategy
• ヒープベースのオーバーフロー • 基本的に必要なもの:
• 情報の搾取 • オブジェクトの上書き
• ここでゾーンの問題が浮上する…
エクスプロイトの戦略
• 大半の制御可能な配置はWebKitのmallocに管理されている
• しかし、新規にデフォルトゾーンを呼び出す
• 上書きするかなり多くのオブジェクトを開く • 情報のリークはまだ必要
Explo i tat ion Strategy
• JavascriptでCoreFoundationを操作するHeap改竄方法が見つかった
• AudioContextオブジェクトは、高確率でデフォルトの
mallocゾーンに配置 • 複数のイメージは適切な配置のヒープ領域が必要とする、CoreFoundationsがデフォルトのヒープへ配置するために初期化とセットアップをする - CSSは適切なロードに使用
Explo i tat ion Strategy
• さらなる解析によりデフォルトゾーンに配置された文字列を見つけた
• Date.prototype.ToLocale • オーバーフローによって上書きができて、Javascriptからのアクセスも可能となる
Explo i tat ion Strategy
• Date.prototype.ToLocale … — 3つのアロケーション • ロケールの後quantumを空にする • メタデータの上書き -> 後方への結合(coalesce) • チャンクの解放 -> リージョンビットマップのクリア • 次の割り当てはロケール文字列の途中に配置 • ヌル終端文字を取り除く • 日付を読み出す
Explo i tat ion Strategy
• 情報搾取が成功 • オブジェクトの上書き
• コード実行 👻
Conclus ion
• https://github.com/blankwall/MacHeap • MacHeap tool • libsystem_malloc.idb
• https://github.com/blankwall/LLDBInit
• @1blankwall1