Interactive CTF Exploration Tool
Just want to test the SYSTEM exploit? Click here.
An Interactive CTF Exploration Tool
ctftool, an interactive command line tool to experiment with CTF, alittle-known protocol used on Windows to implement Text Services. This mightbe useful for studying Windows internals, debugging complex issues with TextInput Processors and analyzing Windows security.
It is possible to write simple scripts with
ctftool for automating interactionwith CTF clients or servers, or perform simple fuzzing.
There is a blog post that accompanies the release of this tool available here.
ctftool has been tested on Windows 7, Windows 8 and Windows 10. Both 32-bitand x64 versions are supported, but x64 has been tested more extensively.
There is online help for most commands, simply type
help to see a list ofcommands, and
help to see detailed help for a particular command.
$ ./ctftool.exeAn interactive ctf exploration tool by @taviso.Type "help" for available commands.Most commands require a connection, see "help connect".ctf> helpTypehelp ` 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>```
The first thing you will want to do is connect to a session, and see whichclients are connected.
ctf> connectThe ctf server port is located at \BaseNamedObjects\msctf.serverDefault1NtAlpcConnectPort("\BaseNamedObjects\msctf.serverDefault1") => 0Connected to CTF server@\BaseNamedObjects\msctf.serverDefault1, Handle 00000264ctf> scanClient 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)
You can then experiment by sending and receiving commands to the server, or anyof the connected clients.
If you don't want to build it yourself, check out the releases tab
I used GNU make and VisualStudio 2019 to develop
ctftool. Only 32-bit builds are supported, as thisallows the tool to run on x86 and x64 Windows.
If all the dependencies are installed, just typing
make in a developer commandprompt should be enough.
I use the "Build Tools" variant of Visual Studio, and the only components I haveselected are MSVC, MSBuild, CMake and the SDK.
This project uses submodules for some of the dependencies, be sure that you'reusing a command like this to fetch all the required code.
git submodule update --init --recursive
The examples only work on Windows 10 x64. All platforms and versions since Windows XP are affected, but no PoC is currently implemented.
This tool was used to discover many critical security problem with the CTFprotocol that have existed for decades.
If you just want to test an exploit on Windows 10 x64 1903, run or double-click
ctftool.exe and enter this command:
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
This will wait for the UAC dialog to appear, compromise it and start a shell.
In fact, the exploit code is split into two stages that you can useindependently. For example, you might want to compromise a process belonging toa user on a different session using the optional parameters to
Most CTF clients can be compromised, as the kernel forces applications that drawwindows to load the vulnerable library.
Simply connect to a session, select a client to compromise (use the
thread commands, or just
ctf> script .\scripts\ctf-exploit-common-win10.ctf
Building a CFG jump chain that worked on the majority of CTF clients was quitechallenging. There are two primary components to the final exploit, an arbitrarywrite primitive and then setting up our registers to call
You can use
dumpbin /headers /loadconfigto dump the whitelisted branch targets.
I need an arbitrary write gadget to create objects in a predictable location.The best usable gadget I was able to find was an arbitrary dword decrement in
This means rather than just setting the values we want, We have to keepdecrementing until the LSB reaches the value we want. This is a lot of work,but we never have to do more than
(2^8 - 1) * len decrements.
Using this primitive, I build an object like this in some unused slack spacein kernel32
.data section. It needs to be part of an image so that I canpredict where it will be mapped, as image randomization is per-boot on Windows.
There were (of course) lots of arbitrary write gadgets, the problem wasregaining control of execution after the write. This proved quite challenging,and that's the reason I was stuck with a dword decrement instead of somethingsimpler.
MSCTF catches all exceptions, so the challenge was finding an arbitrary writethat didn't mess up the stack so that SEH survived, or crashed really quicklywithout doing any damage.
msvcrt!_init_time gadget was the best I could find, within a fewinstructions it dereferences NULL without corrupting any more memory. This meanswe can repeat it ad infinitum.
I found two useful gadgets for adjusting registers, The first was:
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]
And the second was:
MSCTF!CCompartmentEventSink::OnChange: mov rax,qword ptr [rcx+30h] mov rcx,qword ptr [rcx+38h] jmp qword ptr [MSCTF!_guard_dispatch_icall_fptr]
By combining these two gadgets with the object we formed with our write gadget,we can redirect execution to
kernel32!LoadLibraryA by bouncing between them.
This was complicated, but the jump sequence works like this:
If you're interested, I recommend watching it in a debugger. Note that you willneed to use the command
sxd av and
sxd bpe or the debugger will stop forevery write!
Edit Session Attacks
Apart from memory corruption, a major vulnerability class exposed by CTF areedit session attacks. Normally, an unprivileged process (for example, lowintegrity) would not be permitted to send input or read data from a highprivileged process. This security boundary is called UIPI, User InterfacePrivilege Isolation.
CTF breaks these assumptions, and allows unprivileged processes to send inputto privileged processes.
There are some requirements for this attack to work, as far as I'm aware itwill only work if you have a display language installed that uses an OoP TIP,out-of-process text input processor. Users with input languages that use IMEs (Chinese, Japanese, Korean, and so on) and users with a11y tools fall into thiscategory.
Example attacks include...
- Sending commands to an elevated command window.
- Reading passwords out of dialogs or the login screen.
- Escaping IL/AppContainer sandboxes by sending input to unsandboxed windows.
There is an example script in the scriptsdirectory that will send input to a notepad window to demonstrate how editsessions work.
Because there is no authentication involved between clients and servers in theCTF protocol, an attacker with the necessary privileges to write to
\BaseNamedObjects can create the CTF ALPC port and pretend to be the monitor.
This allows any and all restrictions enforced by the monitor to be bypassed.
If you want to experiment with this attack, try the
hijack command in
An interactive ctf exploration tool by @taviso.Type "help" for available commands.ctf> hijack Default 1NtAlpcCreatePort("\BaseNamedObjects\msctf.serverDefault1") => 0 00000218NtAlpcSendWaitReceivePort("\BaseNamedObjects\msctf.serverDefault1") => 0 00000218000000: 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: 00020180NtAlpcSendWaitReceivePort("\BaseNamedObjects\msctf.serverDefault1") => 0 00000218000000: 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: 00010110NtAlpcSendWaitReceivePort("\BaseNamedObjects\msctf.serverDefault1") => 0 00000218000000: 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...
Cross Session Attacks
There is no session isolation in the CTF protocol, any process can connect toany CTF server. For example, a Terminal Services user can interact with theprocesses of any other user, even the Administrator.
connect command in
ctftool supports connecting to non-default sessionsif you want to experiment with this attack.
```An interactive ctf exploration tool by @taviso.Type "help" for available commands.Most commands require a connection, see "help connect".ctf> help connectConnect to CTF ALPC Port.
Usage: connect [DESKTOPNAME SESSIONID]Without any parameters, connect to the ctf monitor for the currentdesktop and session. All subsequent commands will use this connectionfor 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 monitorfor another desktop and session are opened, if it exists.If the specified port does not exist, wait until it does exist. This isso that you can wait for a session that hasn't startedyet in a script.Examples Connect to the monitor for current desktop ctf> connect Connect to a specific desktop and session. ctf> connect Default 1Most commands require a connection, see "help connect".```
At the time of writing, it is unknown how Microsoft will change the CTFprotocol in response to the numerous design flaws this tool helped expose.
For that reason, consider this tool to be in proof-of-concept state.
Supported Versions and Platforms
All versions of Windows since Windows XP use CTF, on all supported platforms.
While not part of the base system until XP, versions as early as Windows 98 andNT4 would use CTF if you installed Microsoft Office.
ctftool supports Windows 7 and later on x86 and x64, but earlier versions andother platforms could be supported, and contributions would be appreciated.
Microsoft doesn't document what CTF stands for, it's not explained in anyof the Text Services documentation, SDK samples, symbol names, header files,or anywhere else. My theory is it's from
CTextFramework, what you might namethe class in hungarian notation.
There are some websites that claim
ctfmonhas something to do with Clear Type Fonts or the Azure Collaborative Translation Framework. They're mistaken.
Tavis Ormandy firstname.lastname@example.org
All original code is Apache 2.0, See LICENSE file for details.
The following components are imported third party projects.
- pe-parse, by Andrew Ruef et al.
- pe-parse is used to implement a
GetProcAddress()for 64-bit modules from a32-bit process. This is used in the
symbolcommand, and allows the samebinary to work on x64 and x86.
- pe-parse is used to implement a
- wineditline, by Paolo Tosco.
- wineditline is used to implement user friendly command-line input andhistory editing.
- dynamorio, by Derek Bruening et al.
- I borrowed some of the prototypes and type definitions from DR.
- ntdll.h, by Ladislav Zezula.
- Ladislav collected some structure definitions and prototoypes fromvarious WDK, DDK, SDK releases into one convenient file.
To restore the repository download the bundle
git clone taviso-ctftool_-_2019-08-14_14-09-08.bundle
Upload date: 2019-08-14
- 2019-08-14 14:09:08
- Internet Archive Python library 1.8.1
- iagitup - v1.6.2