{"id":13438716,"url":"https://github.com/taviso/ctftool","last_synced_at":"2025-05-16T04:03:40.443Z","repository":{"id":45826313,"uuid":"190683905","full_name":"taviso/ctftool","owner":"taviso","description":"Interactive CTF Exploration Tool","archived":false,"fork":false,"pushed_at":"2021-09-17T21:02:25.000Z","size":1765,"stargazers_count":1655,"open_issues_count":15,"forks_count":269,"subscribers_count":58,"default_branch":"master","last_synced_at":"2025-04-08T14:07:04.524Z","etag":null,"topics":["reverse-engineering","security","windows","windows-internals"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/taviso.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-07T03:39:10.000Z","updated_at":"2025-04-08T12:52:37.000Z","dependencies_parsed_at":"2022-09-15T02:22:51.564Z","dependency_job_id":null,"html_url":"https://github.com/taviso/ctftool","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taviso%2Fctftool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taviso%2Fctftool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taviso%2Fctftool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taviso%2Fctftool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taviso","download_url":"https://codeload.github.com/taviso/ctftool/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254464891,"owners_count":22075570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["reverse-engineering","security","windows","windows-internals"],"created_at":"2024-07-31T03:01:07.830Z","updated_at":"2025-05-16T04:03:38.083Z","avatar_url":"https://github.com/taviso.png","language":"C","readme":"# CTFTOOL\r\n\r\n\u003e\r\n\u003e Just want to test the SYSTEM exploit? [Click here](#Exploit).\r\n\u003e\r\n\r\n[![Video of Exploit](docs/thumb.png)](https://www.youtube.com/watch?v=r3vrzzDpmhc)\r\n\r\n## An Interactive CTF Exploration Tool\r\n\r\nThis is `ctftool`, an interactive command line tool to experiment with CTF, a\r\nlittle-known protocol used on Windows to implement Text Services. This might\r\nbe useful for studying Windows internals, debugging complex issues with Text\r\nInput Processors and analyzing Windows security.\r\n\r\nIt is possible to write simple scripts with `ctftool` for automating interaction\r\nwith CTF clients or servers, or perform simple fuzzing.\r\n\r\n## Background\r\n\r\nThere is a blog post that accompanies the release of this tool available here.\r\n\r\nhttps://googleprojectzero.blogspot.com/2019/08/down-rabbit-hole.html\r\n\r\n## Usage\r\n\r\n`ctftool` has been tested on Windows 7, Windows 8 and Windows 10. Both 32-bit\r\nand x64 versions are supported, but x64 has been tested more extensively.\r\n\r\nThere is online help for most commands, simply type `help` to see a list of\r\ncommands, and `help \u003ccommand\u003e` to see detailed help for a particular command.\r\n\r\n```\r\n$ ./ctftool.exe\r\nAn interactive ctf exploration tool by @taviso.\r\nType \"help\" for available commands.\r\nMost commands require a connection, see \"help connect\".\r\nctf\u003e help\r\nType `help \u003ccommand\u003e` for help with a specific command.\r\nAny line beginning with # is considered a comment.\r\n\r\nhelp            - List available commands.\r\nexit            - Exit the shell.\r\nconnect         - Connect to CTF ALPC Port.\r\ninfo            - Query server informaiton.\r\nscan            - Enumerate connected clients.\r\ncallstub        - Ask a client to invoke a function.\r\ncreatestub      - Ask a client to instantiate CLSID.\r\nhijack          - Attempt to hijack an ALPC server path.\r\nsendinput       - Send keystrokes to thread.\r\nsetarg          - Marshal a parameter.\r\ngetarg          - Unmarshal a parameter.\r\nwait            - Wait for a process and set it as the default thread.\r\nthread          - Set the default thread.\r\nsleep           - Sleep for specified milliseconds.\r\nforget          - Forget all known stubs.\r\nstack           - Print the last leaked stack ptr.\r\nmarshal         - Send command with marshalled parameters.\r\nproxy           - Send command with proxy parameters.\r\ncall            - Send command without appended data.\r\nwindow          - Create and register a message window.\r\npatch           - Patch a marshalled parameter.\r\nmodule          - Print the base address of a module.\r\nmodule64        - Print the base address of a 64bit module.\r\neditarg         - Change the type of a marshalled parameter.\r\nsymbol          - Lookup a symbol offset from ImageBase.\r\nset             - Change or dump various ctftool parameters.\r\nshow            - Show the value of special variables you can use.\r\nlock            - Lock the workstation, switch to Winlogon desktop.\r\nrepeat          - Repeat a command multiple times.\r\nrun             - Run a command.\r\nscript          - Source a script file.\r\nprint           - Print a string.\r\nconsent         - Invoke the UAC consent dialog.\r\nreg             - Lookup a DWORD in the registry.\r\ngadget          - Find the offset of a pattern in a file.\r\nsection         - Lookup property of PE section.\r\nMost commands require a connection, see \"help connect\".\r\nctf\u003e\r\n```\r\n\r\nThe first thing you will want to do is connect to a session, and see which\r\nclients are connected.\r\n\r\n```\r\nctf\u003e connect\r\nThe ctf server port is located at \\BaseNamedObjects\\msctf.serverDefault1\r\nNtAlpcConnectPort(\"\\BaseNamedObjects\\msctf.serverDefault1\") =\u003e 0\r\nConnected to CTF server@\\BaseNamedObjects\\msctf.serverDefault1, Handle 00000264\r\nctf\u003e scan\r\nClient 0, Tid 3400 (Flags 0x08, Hwnd 00000D48, Pid 8696, explorer.exe)\r\nClient 1, Tid 7692 (Flags 0x08, Hwnd 00001E0C, Pid 8696, explorer.exe)\r\nClient 2, Tid 9424 (Flags 0x0c, Hwnd 000024D0, Pid 9344, SearchUI.exe)\r\nClient 3, Tid 12068 (Flags 0x08, Hwnd 00002F24, Pid 12156, PROCEXP64.exe)\r\nClient 4, Tid 9740 (Flags 0000, Hwnd 0000260C, Pid 3840, ctfmon.exe)\r\n```\r\n\r\nYou can then experiment by sending and receiving commands to the server, or any\r\nof the connected clients.\r\n\r\n## Building\r\n\r\n\u003e If you don't want to build it yourself, check out the [releases](https://github.com/taviso/ctftool/releases) tab\r\n\r\nI used [GNU make](http://gnuwin32.sourceforge.net/packages/make.htm) and Visual\r\nStudio 2019 to develop `ctftool`. Only 32-bit builds are supported, as this\r\nallows the tool to run on x86 and x64 Windows.\r\n\r\nIf all the dependencies are installed, just typing `make` in a developer command\r\nprompt should be enough.\r\n\r\nI use the \"Build Tools\" variant of Visual Studio, and the only components I have\r\nselected are MSVC, MSBuild, CMake and the SDK.\r\n\r\nThis project uses submodules for some of the dependencies, be sure that you're\r\nusing a command like this to fetch all the required code.\r\n\r\n```\r\ngit submodule update --init --recursive\r\n```\r\n\r\n## Exploit\r\n\r\n\u003e The examples only work on Windows 10 x64. All platforms and versions since\r\n\u003e Windows XP are affected, but no PoC is currently implemented.\r\n\r\nThis tool was used to discover many critical security problem with the CTF\r\nprotocol that have existed for decades.\r\n\r\nIf you just want to test an exploit on Windows 10 x64 1903, run or double-click\r\n`ctftool.exe` and enter this command:\r\n\r\n```\r\nAn interactive ctf exploration tool by @taviso.\r\nType \"help\" for available commands.\r\nMost commands require a connection, see \"help connect\".\r\nctf\u003e script .\\scripts\\ctf-consent-system.ctf\r\n```\r\n\r\nThis will wait for the UAC dialog to appear, compromise it and start a shell.\r\n\r\nIn fact, the exploit code is split into two stages that you can use\r\nindependently. For example, you might want to compromise a process belonging to\r\na user on a different session using the optional parameters to `connect`.\r\n\r\nMost CTF clients can be compromised, as the kernel forces applications that draw\r\nwindows to load the vulnerable library.\r\n\r\nSimply connect to a session, select a client to compromise (use the `scan` and\r\n`thread` commands, or just `wait`), then:\r\n\r\n```\r\nctf\u003e script .\\scripts\\ctf-exploit-common-win10.ctf\r\n```\r\n\r\n### Exploitation Notes\r\n\r\nBuilding a CFG jump chain that worked on the majority of CTF clients was quite\r\nchallenging. There are two primary components to the final exploit, an arbitrary\r\nwrite primitive and then setting up our registers to call `LoadLibrary()`.\r\n\r\n\u003e You can use `dumpbin /headers /loadconfig` to dump the whitelisted branch\r\n\u003e targets.\r\n\r\n#### Arbitrary Write\r\n\r\nI need an arbitrary write gadget to create objects in a predictable location.\r\nThe best usable gadget I was able to find was an arbitrary dword decrement in\r\n`msvcrt!_init_time`.\r\n\r\nThis means rather than just setting the values we want, We have to keep\r\ndecrementing until the LSB reaches the value we want. This is a lot of work,\r\nbut we never have to do more than `(2^8 - 1) * len` decrements.\r\n\r\n![Decrement Write](docs/decrement-arbitrary-value.gif)\r\n\r\nUsing this primitive, I build an object like this in some unused slack space\r\nin kernel32 `.data` section. It needs to be part of an image so that I can\r\npredict where it will be mapped, as image randomization is per-boot on Windows.\r\n\r\n![Object Layout](docs/fake-object-layout.png)\r\n\r\nThere were (of course) lots of arbitrary write gadgets, the problem was\r\nregaining control of execution *after* the write. This proved quite challenging,\r\nand that's the reason I was stuck with a dword decrement instead of something\r\nsimpler.\r\n\r\nMSCTF catches all exceptions, so the challenge was finding an arbitrary write\r\nthat didn't mess up the stack so that SEH survived, or crashed really quickly\r\nwithout doing any damage.\r\n\r\nThe `msvcrt!_init_time` gadget was the best I could find, within a few\r\ninstructions it dereferences NULL without corrupting any more memory. This means\r\nwe can repeat it ad infinitum.\r\n\r\n#### Redirecting Execution\r\n\r\nI found two useful gadgets for adjusting registers, The first was:\r\n\r\n```\r\ncombase!CStdProxyBuffer_CF_AddRef:\r\n      mov     rcx,qword ptr [rcx-38h]\r\n      mov     rax,qword ptr [rcx]    \r\n      mov     rax,qword ptr [rax+8]  \r\n      jmp     qword ptr [combase!__guard_dispatch_icall_fptr]\r\n```\r\n\r\nAnd the second was:\r\n\r\n```\r\nMSCTF!CCompartmentEventSink::OnChange:\r\n      mov     rax,qword ptr [rcx+30h]\r\n      mov     rcx,qword ptr [rcx+38h]\r\n      jmp     qword ptr [MSCTF!_guard_dispatch_icall_fptr]\r\n```\r\n\r\nBy combining these two gadgets with the object we formed with our write gadget,\r\nwe can redirect execution to `kernel32!LoadLibraryA` by bouncing between them.\r\n\r\nThis was complicated, but the jump sequence works like this:\r\n\r\n![Exploit Chain Sequence](docs/exploit-chain-sequence.png)\r\n\r\nIf you're interested, I recommend watching it in a debugger. Note that you will\r\nneed to use the command `sxd av` and `sxd bpe` or the debugger will stop for\r\nevery write!\r\n\r\n## Edit Session Attacks\r\n\r\nApart from memory corruption, a major vulnerability class exposed by CTF are\r\n*edit session attacks*. Normally, an unprivileged process (for example, low\r\nintegrity) would not be permitted to send input or read data from a high\r\nprivileged process. This security boundary is called UIPI, *User Interface\r\nPrivilege Isolation*.\r\n\r\nCTF breaks these assumptions, and allows unprivileged processes to send input\r\nto privileged processes.\r\n\r\nThere are some requirements for this attack to work, as far as I'm aware it\r\nwill only work if you have a display language installed that uses an OoP TIP,\r\n*out-of-process text input processor*. Users with input languages that use IMEs \r\n(Chinese, Japanese, Korean, and so on) and users with a11y tools fall into this\r\ncategory.\r\n\r\nExample attacks include...\r\n\r\n * Sending commands to an elevated command window.\r\n * Reading passwords out of dialogs or the login screen.\r\n * Escaping IL/AppContainer sandboxes by sending input to unsandboxed windows.\r\n\r\nThere is an example [script](scripts/ctf-demo-editsession.ctf) in the scripts\r\ndirectory that will send input to a notepad window to demonstrate how edit\r\nsessions work.\r\n\r\n[![Edit Session Screenshot](docs/edit-thumb.png)](docs/edit-session-full.png)\r\n\r\n## Monitor Hijacking\r\n\r\nBecause there is no authentication involved between clients and servers in the\r\nCTF protocol, an attacker with the necessary privileges to write to\r\n`\\BaseNamedObjects` can create the CTF ALPC port and pretend to be the monitor.\r\n\r\nThis allows any and all restrictions enforced by the monitor to be bypassed.\r\n\r\nIf you want to experiment with this attack, try the `hijack` command in `ctftool`.\r\n\r\n```\r\nAn interactive ctf exploration tool by @taviso.\r\nType \"help\" for available commands.\r\nctf\u003e hijack Default 1\r\nNtAlpcCreatePort(\"\\BaseNamedObjects\\msctf.serverDefault1\") =\u003e 0 00000218\r\nNtAlpcSendWaitReceivePort(\"\\BaseNamedObjects\\msctf.serverDefault1\") =\u003e 0 00000218\r\n000000: 18 00 30 00 0a 20 00 00 00 11 00 00 44 11 00 00  ..0.. ......D...\r\n000010: a4 86 00 00 b7 66 b8 00 00 11 00 00 44 11 00 00  .....f......D...\r\n000020: e7 12 01 00 0c 00 00 00 80 01 02 00 20 10 d6 05  ............ ...\r\nA a message received\r\n        ProcessID: 4352, SearchUI.exe\r\n        ThreadId: 4420\r\n        WindowID: 00020180\r\nNtAlpcSendWaitReceivePort(\"\\BaseNamedObjects\\msctf.serverDefault1\") =\u003e 0 00000218\r\n000000: 18 00 30 00 0a 20 00 00 ac 0f 00 00 0c 03 00 00  ..0.. ..........\r\n000010: ec 79 00 00 fa 66 b8 00 ac 0f 00 00 0c 03 00 00  .y...f..........\r\n000020: 12 04 01 00 08 00 00 00 10 01 01 00 00 00 00 00  ................\r\nA a message received\r\n        ProcessID: 4012, explorer.exe\r\n        ThreadId: 780\r\n        WindowID: 00010110\r\nNtAlpcSendWaitReceivePort(\"\\BaseNamedObjects\\msctf.serverDefault1\") =\u003e 0 00000218\r\n000000: 18 00 30 00 0a 20 00 00 ac 0f 00 00 0c 03 00 00  ..0.. ..........\r\n000010: fc 8a 00 00 2a 67 b8 00 ac 0f 00 00 0c 03 00 00  ....*g..........\r\n000020: 12 04 01 00 08 00 00 00 10 01 01 00 58 00 00 00  ............X...\r\nA a message received\r\n        ProcessID: 4012, explorer.exe\r\n        ThreadId: 780\r\n...\r\n```\r\n\r\n## Cross Session Attacks\r\n\r\nThere is no session isolation in the CTF protocol, any process can connect to\r\nany CTF server. For example, a Terminal Services user can interact with the\r\nprocesses of any other user, even the Administrator.\r\n\r\nThe `connect` command in `ctftool` supports connecting to non-default sessions\r\nif you want to experiment with this attack.\r\n\r\n```\r\nAn interactive ctf exploration tool by @taviso.\r\nType \"help\" for available commands.\r\nMost commands require a connection, see \"help connect\".\r\nctf\u003e help connect\r\nConnect to CTF ALPC Port.\r\n\r\nUsage: connect [DESKTOPNAME SESSIONID]\r\nWithout any parameters, connect to the ctf monitor for the current\r\ndesktop and session. All subsequent commands will use this connection\r\nfor communicating with the ctf monitor.\r\n\r\nIf a connection is already open, the existing connection is closed first.\r\n\r\nIf DESKTOPNAME and SESSIONID are specified, a connection to ctf monitor\r\nfor another desktop and session are opened, if it exists.\r\nIf the specified port does not exist, wait until it does exist. This is\r\nso that you can wait for a session that hasn't started\r\nyet in a script.\r\nExamples\r\n Connect to the monitor for current desktop\r\n  ctf\u003e connect\r\n Connect to a specific desktop and session.\r\n  ctf\u003e connect Default 1\r\nMost commands require a connection, see \"help connect\".\r\n```\r\n\r\n## Status\r\n\r\nAt the time of writing, it is unknown how Microsoft will change the CTF\r\nprotocol in response to the numerous design flaws this tool helped expose.\r\n\r\nFor that reason, consider this tool to be in proof-of-concept state.\r\n\r\n### Supported Versions and Platforms\r\n\r\nAll versions of Windows since Windows XP use CTF, on all supported platforms.\r\n\r\nWhile not part of the base system until XP, versions as early as Windows 98 and\r\nNT4 would use CTF if you installed Microsoft Office.\r\n\r\n`ctftool` supports Windows 7 and later on x86 and x64, but earlier versions and\r\nother platforms *could* be supported, and contributions would be appreciated.\r\n\r\n## Acronym\r\n\r\nMicrosoft doesn't document what CTF stands for, it's not explained in any\r\nof the Text Services documentation, SDK samples, symbol names, header files,\r\nor anywhere else. My theory is it's from `CTextFramework`, what you might name\r\nthe class in [hungarian notation](http://web.mst.edu/~cpp/common/hungarian.html).\r\n\r\n\u003e There are some websites that claim `ctfmon` has something to do with Clear\r\n\u003e Type Fonts or the Azure Collaborative Translation Framework. They're mistaken.\r\n\r\n\u003e Update: [Jake Nelson](https://twitter.com/JakeNelsonMN/status/1161513319049703424) finds\r\n\u003e evidence for \"[Common Text Framework](https://patents.google.com/patent/US20040150670#P-0091)\"\r\n\r\n## Authors\r\n\r\nTavis Ormandy \u003ctaviso@gmail.com\u003e\r\n\r\n## License\r\n\r\nAll original code is Apache 2.0, See LICENSE file for details.\r\n\r\nThe following components are imported third party projects.\r\n\r\n* [pe-parse](https://github.com/trailofbits/pe-parse), by Andrew Ruef et al.\r\n  * pe-parse is used to implement a `GetProcAddress()` for 64-bit modules from a\r\n    32-bit process. This is used in the `symbol` command, and allows the same\r\n    binary to work on x64 and x86.\r\n* [wineditline](http://mingweditline.sourceforge.net/), by Paolo Tosco.\r\n  * wineditline is used to implement user friendly command-line input and\r\n    history editing.\r\n* [dynamorio](https://www.dynamorio.org/), by Derek Bruening et al.\r\n  * I borrowed some of the prototypes and type definitions from DR.\r\n* [ntdll.h](http://www.zezula.net/en/prog/lpc.html), by Ladislav Zezula.\r\n  * Ladislav collected some structure definitions and prototoypes from\r\n    various WDK, DDK, SDK releases into one convenient file.\r\n","funding_links":[],"categories":["C","Tools","\u003ca id=\"c7f35432806520669b15a28161a4d26a\"\u003e\u003c/a\u003eCTF\u0026\u0026HTB","Windows Utilities","C (61)","C (286)","Operating Systems","CTFs"],"sub_categories":["Others","\u003ca id=\"e64cedb2d91d06b3eeac5ea414e12b27\"\u003e\u003c/a\u003eCTF","Web Exploitation Books","Windows","API"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaviso%2Fctftool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaviso%2Fctftool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaviso%2Fctftool/lists"}