macOS Thread Injection via Task port
Code
1. Thread Hijacking
最初に、task_threads()
関数がタスクポートで呼び出され、リモートタスクからスレッドリストを取得します。ハイジャックするスレッドが選択されます。このアプローチは、thread_create_running()
をブロックする新しい緩和策により、新しいリモートスレッドを作成することが禁止されているため、従来のコードインジェクション手法とは異なります。
スレッドを制御するために、thread_suspend()
が呼び出され、その実行が停止されます。
リモートスレッドで許可される唯一の操作は、停止と開始、レジスタ値の取得と変更です。リモート関数呼び出しは、レジスタ x0
から x7
を引数に設定し、pc
をターゲット関数に設定し、スレッドをアクティブにすることで開始されます。戻り後にスレッドがクラッシュしないようにするためには、戻りを検出する必要があります。
1つの戦略は、thread_set_exception_ports()
を使用してリモートスレッドのために例外ハンドラを登録することです。関数呼び出しの前にlr
レジスタを無効なアドレスに設定します。これにより、関数実行後に例外がトリガーされ、例外ポートにメッセージが送信され、スレッドの状態を検査して戻り値を回復できるようになります。あるいは、Ian Beerのtriple_fetchエクスプロイトから採用された方法として、lr
を無限ループに設定します。スレッドのレジスタは、pc
がその命令を指すまで継続的に監視されます。
2. Mach ports for communication
次の段階は、リモートスレッドとの通信を促進するためにMachポートを確立することです。これらのポートは、タスク間で任意の送信および受信権を転送するのに重要です。
双方向通信のために、2つのMach受信権が作成されます:1つはローカルタスクに、もう1つはリモートタスクに作成されます。その後、各ポートの送信権が対となるタスクに転送され、メッセージの交換が可能になります。
ローカルポートに焦点を当てると、受信権はローカルタスクによって保持されます。ポートはmach_port_allocate()
で作成されます。このポートに送信権をリモートタスクに転送することが課題です。
戦略の1つは、thread_set_special_port()
を利用して、リモートスレッドのTHREAD_KERNEL_PORT
にローカルポートへの送信権を配置することです。その後、リモートスレッドにmach_thread_self()
を呼び出して送信権を取得するよう指示します。
リモートポートの場合、プロセスは基本的に逆になります。リモートスレッドは、mach_reply_port()
を介してMachポートを生成するよう指示されます(mach_port_allocate()
はその返却メカニズムのため不適切です)。ポートが作成されると、mach_port_insert_right()
がリモートスレッドで呼び出され、送信権が確立されます。この権利は、その後、thread_set_special_port()
を使用してカーネルに保存されます。ローカルタスクに戻ると、thread_get_special_port()
がリモートスレッドで使用され、リモートタスクに新しく割り当てられたMachポートへの送信権を取得します。
これらのステップを完了すると、Machポートが確立され、双方向通信の基盤が整います。
3. Basic Memory Read/Write Primitives
このセクションでは、基本的なメモリの読み書きプリミティブを確立するために、executeプリミティブを利用することに焦点を当てます。これらの初期ステップは、リモートプロセスに対するより多くの制御を得るために重要ですが、この段階でのプリミティブはあまり役に立ちません。すぐに、より高度なバージョンにアップグレードされます。
Memory Reading and Writing Using Execute Primitive
メモリの読み書きを特定の関数を使用して行うことが目標です。メモリを読み取るためには、以下の構造に似た関数が使用されます:
メモリへの書き込みには、この構造に似た関数が使用されます:
これらの関数は、指定されたアセンブリ命令に対応しています:
適切な関数の特定
一般的なライブラリのスキャンにより、これらの操作に適した候補が明らかになりました:
メモリの読み取り:
property_getName()
関数は、Objective-C ランタイムライブラリ からメモリを読み取るための適切な関数として特定されました。関数の概要は以下の通りです:
この関数は、objc_property_t
の最初のフィールドを返すことによって、実質的にread_func
のように機能します。
メモリの書き込み: メモリを書き込むための事前構築された関数を見つけることは、より困難です。しかし、libxpcの
_xpc_int64_set_value()
関数は、以下の逆アセンブルを持つ適切な候補です:
特定のアドレスに64ビットの書き込みを行うために、リモートコールは次のように構成されます:
これらのプリミティブが確立されると、共有メモリを作成するための準備が整い、リモートプロセスの制御において重要な進展が見られます。
4. 共有メモリの設定
目的は、ローカルタスクとリモートタスク間で共有メモリを確立し、データ転送を簡素化し、複数の引数を持つ関数の呼び出しを容易にすることです。このアプローチは、Machメモリエントリに基づいて構築されたlibxpc
とそのOS_xpc_shmem
オブジェクトタイプを活用することを含みます。
プロセスの概要:
メモリの割り当て:
mach_vm_allocate()
を使用して共有用のメモリを割り当てます。xpc_shmem_create()
を使用して、割り当てられたメモリ領域のためのOS_xpc_shmem
オブジェクトを作成します。この関数は、Machメモリエントリの作成を管理し、OS_xpc_shmem
オブジェクトのオフセット0x18
にMach送信権を格納します。
リモートプロセスでの共有メモリの作成:
リモートプロセスで
malloc()
へのリモート呼び出しを使用してOS_xpc_shmem
オブジェクトのためのメモリを割り当てます。ローカルの
OS_xpc_shmem
オブジェクトの内容をリモートプロセスにコピーします。ただし、この初期コピーはオフセット0x18
で不正なMachメモリエントリ名を持っています。
Machメモリエントリの修正:
thread_set_special_port()
メソッドを利用して、リモートタスクにMachメモリエントリの送信権を挿入します。リモートメモリエントリの名前でオフセット
0x18
のMachメモリエントリフィールドを上書きして修正します。
共有メモリ設定の最終化:
リモートの
OS_xpc_shmem
オブジェクトを検証します。xpc_shmem_remote()
へのリモート呼び出しで共有メモリマッピングを確立します。
これらの手順に従うことで、ローカルタスクとリモートタスク間の共有メモリが効率的に設定され、データ転送が簡単になり、複数の引数を必要とする関数の実行が可能になります。
追加のコードスニペット
メモリの割り当てと共有メモリオブジェクトの作成について:
リモートプロセス内で共有メモリオブジェクトを作成および修正するには:
Machポートとメモリエントリ名の詳細を正しく扱い、共有メモリのセットアップが適切に機能するようにしてください。
5. 完全な制御の達成
共有メモリを確立し、任意の実行能力を獲得することに成功すると、実質的にターゲットプロセスに対する完全な制御を得たことになります。この制御を可能にする主要な機能は次のとおりです。
任意のメモリ操作:
memcpy()
を呼び出して共有領域からデータをコピーすることで、任意のメモリ読み取りを実行します。memcpy()
を使用して共有領域にデータを転送することで、任意のメモリ書き込みを実行します。
複数引数を持つ関数呼び出しの処理:
8つ以上の引数を必要とする関数の場合、呼び出し規約に従って追加の引数をスタックに配置します。
Machポートの転送:
以前に確立されたポートを介してMachメッセージを通じてタスク間でMachポートを転送します。
ファイルディスクリプタの転送:
Ian Beerが
triple_fetch
で強調した技術を使用して、ファイルポートを介してプロセス間でファイルディスクリプタを転送します。
この包括的な制御は、threadexecライブラリにカプセル化されており、被害者プロセスとのインタラクションのための詳細な実装とユーザーフレンドリーなAPIを提供します。
重要な考慮事項:
システムの安定性とデータの整合性を維持するために、メモリの読み取り/書き込み操作に
memcpy()
を適切に使用してください。Machポートやファイルディスクリプタを転送する際は、適切なプロトコルに従い、リソースを責任を持って扱い、漏洩や意図しないアクセスを防いでください。
これらのガイドラインに従い、threadexec
ライブラリを利用することで、プロセスを効率的に管理し、細かいレベルでインタラクションを行い、ターゲットプロセスに対する完全な制御を達成できます。
参考文献
Last updated