
BOF POC du projet DSCourier / invocation de WinGet via COM
Ceci est une implémentation BOF du projet DSCourier de Dylan Davis et Matthew Schramm. Elle utilise l'interface COM de WinGet pour exécuter du code PowerShell arbitraire dans un processus signé et approuvé par Microsoft. Leur article de recherche complet est disponible ici.
Contrairement à la plupart des projets que je publie, ce n'est PAS un outil opérationnel mais plutôt une preuve de concept. J'ai choisi de ne pas poursuivre plus loin après avoir découvert plusieurs problèmes qui empêchent d'en faire un BOF facilement déployable. Le code a été presque entièrement généré par IA. Plusieurs problèmes restent non résolus et sont discutés ci-dessous.
Placez votre code PowerShell arbitraire dans le fichier dist/rev.yml. Par défaut, il contient un simple reverse shell PowerShell provenant du dépôt original. Si vous choisissez de l'utiliser, assurez-vous de remplacer l'IP dans l'exemple existant par votre IP souhaitée.
Exemple d'utilisation du reverse shell PowerShell :


Sans ordre particulier, voici quelques problèmes/limitations de cet outil.
Microsoft.Management.Configuration.winmd doit être présent dans le même répertoire que l'exécutable effectuant les appels COM. Cela pose un problème immédiat lorsqu'on exécute un Beacon depuis un processus system32 déshabillé, par exemple, où les utilisateurs normaux n'ont pas les droits d'écriture. Pour contourner cela, le fichier est plutôt déposé dans %APPDATA%\temp et la fonction WinTypes!RoGetMetaDataFile qui récupère le chemin du fichier winmd est hookée avec un hook inline afin que nous puissions fournir le chemin du dossier temporaire. Cela permet de lire le fichier winmd / de faire réussir les appels COM, mais entraîne des appels VirtualProtect et une réécriture de la mémoire DLL, créant des IOCs.conhost.exe est créé sous ConfigurationRemotingServer.exe. Claude a suggéré qu'il serait possible de charger un module binaire personnalisé comme ressource au lieu d'invoquer pwsh, ce qui résoudrait le problème du conhost, mais cela nécessite de déposer des fichiers supplémentaires sur le disque et je n'ai pas réussi à le faire fonctionner. Cela n'est peut-être pas possible. Si cela l'était, cela ouvrirait la porte au dépôt d'une DLL .NET générique sur le disque qui pourrait être chargée par ConfigurationRemotingServer.exe et exécuter du shellcode/paramètres/etc. passés.Cet outil a été écrit sans utiliser les déclarations d'API BOF normales (par exemple, un fichier bofdefs.h). Comme indiqué dans cet article de blog par Matt Ehrnschwender, il est possible d'utiliser objcopy pour corriger les symboles appropriés de format DLL$API dans le BOF après compilation.
J'ai écrit un outil appelé BOFPatcher qui automatise ce processus. Cela permet aux utilisateurs d'écrire des BOF comme du C normal sans se soucier des déclarations d'API fastidieuses :

Cet outil est disponible pour ceux qui achètent mon cours BOF Development and Tradecraft.
Bien que l'outil BOFPatcher ne soit pas inclus dans ce dépôt, le Makefile de cet outil appelle objcopy en passant un fichier imports_dscourier64.txt contenant les remplacements de symboles appropriés, ce qui rend le BOF utilisable.
ConfigurationRemotingServer.exe soit terminé ; avec l'exemple simple de reverse shell, cela signifierait que Beacon ne se reconnecterait pas tant que le shell n'est pas tué. Passer aux interfaces asynchrones évite ce problème, mais introduit des problèmes de synchronisation. Un délai d'attente codé en dur de 3 secondes a fonctionné en pratique pour espacer certains appels, mais ce n'est bien sûr pas la bonne façon de procéder.winmdidl.exe a ensuite été utilisé pour extraire les fichiers IDL. midlrt.exe a ensuite été utilisé pour convertir l'IDL en en-têtes/fichiers .c, qui ont ensuite été réduits par Claude pour ne contenir que les définitions nécessaires. C'est toujours un fouillis de code. Ce lien Microsoft sera probablement utile pour mieux comprendre ce processus.winget configure --enable doit être exécutée au moins une fois sur une machine cible avant que le BOF ne réussisse. J'ai retracé la raison de cela au fait que le répertoire DotNet contenant ConfigurationRemotingServer.exe n'existe même pas avant que la commande n'ait été exécutée / que le binaire ne soit téléchargé. Ces fichiers se trouvent dans C:\Program files\WindowsApps\... et ne sont donc pas accessibles en écriture par un utilisateur peu privilégié, donc nous ne pouvons même pas déposer ces fichiers nous-mêmes avec le BOF pour que les choses fonctionnent.configure --enable n'a pas été exécutée, vous êtes bloqué. Pour du post-exploitation, cela pourrait avoir de la valeur, mais vous êtes quelque peu contraint : c'est un processus fixe qui va lancer/exécuter votre code, et comme il s'agit de pwsh, AMSI est en jeu.