1 points par GN⁺ 2025-05-13 | 1 commentaires | Partager sur WhatsApp
  • defendnot, créé lors d’un voyage à Séoul, était un outil visant à désactiver Windows Defender en appelant directement l’API du service Windows Security Center (WSC), ce qui a mené à plusieurs jours de rétro-ingénierie
  • L’ancien outil no-defender utilisait du code d’un antivirus existant pour enregistrer auprès de WSC la présence d’un autre antivirus ; après avoir obtenu environ 1,5k étoiles GitHub, il a été supprimé à la suite d’une demande DMCA de l’éditeur de l’antivirus
  • Au départ, les appels à l’API COM de WSC ont été reproduits en environ une heure, mais WSC vérifiant le processus appelant, l’accès était refusé depuis un processus ordinaire
  • L’analyse a montré que WSC vérifiait le SID WinDefend, les droits administrateur, la signature et le drapeau ForceIntegrity dans les DllCharacteristics du PE ; l’implémentation finale a utilisé Taskmgr.exe
  • Dans un environnement impliquant un MacBook arm64, un PC distant aux États-Unis, une latence Parsec de 210 ms et une VM Shadow.tech, l’implémentation a été finalisée en corrigeant une erreur de chemin ctx.bin et un problème de conditions d’alimentation pour l’autorun

Contexte de la création de defendnot

  • defendnot est un outil qui utilise directement l’API du service Windows Security Center pour désactiver Windows Defender
  • Le point clé de l’implémentation n’était pas tant l’appel à WSC lui-même que le contournement, un par un, des conditions de vérification qui le bloquaient et d’un environnement de travail inconfortable
  • Une documentation technique plus détaillée sur WSC sera publiée ultérieurement par quelqu’un d’autre

no-defender et le DMCA un an plus tôt

  • no-defender, publié il y a environ un an, utilisait une API Windows destinée aux antivirus pour désactiver Windows Defender
  • Cette API servait à indiquer au système qu’« un autre antivirus est présent, il n’est donc pas nécessaire d’exécuter l’analyse de Defender »
  • Le composant système qui gère cette zone est Windows Security Center (WSC)
  • no-defender fonctionnait en utilisant du code tiers d’un antivirus existant afin de forcer l’enregistrement de cet antivirus auprès de WSC
  • Quelques semaines après sa publication, il avait obtenu environ 1,5k stars, puis le contenu du dépôt a été supprimé lorsque l’éditeur de l’antivirus utilisé a déposé une demande de retrait DMCA

Reprise de l’analyse de WSC lors d’un voyage à Séoul

  • Alors que je séjournais dans un Airbnb à Séoul, MrBruh, qui examinait no-defender, m’a envoyé un message disant qu’il cherchait s’il était possible de réaliser une implémentation « propre », sans binaire d’antivirus
  • Pour les CTF ou le reverse x86, j’emporte d’habitude un ordinateur portable x86 séparé, mais pour ce voyage je n’avais pris que mon M4Pro MacBook
  • Même dans ces conditions défavorables, sans machine dédiée au reverse x86, j’ai commencé l’analyse de WSC pendant les moments disponibles avant que mes amis ne se réveillent

Jour 1 : reproduction de l’API COM de WSC et premier refus d’accès

  • MrBruh a fourni les derniers binaires de WSC, et l’implémentation d’enregistrement WSC de l’antivirus utilisé précédemment a servi de référence
  • WSC expose une API COM utilisée par les antivirus, et les appels effectués par l’antivirus existant ont été reproduits en environ une heure
  • Les tests ont été lancés en démarrant Windows arm64 dans Parallels, mais le résultat a été access denied
  • D’après l’expérience précédente, je savais que WSC validait le processus appelant l’API, et j’ai d’abord soupçonné une vérification de signature
  • En injectant du code dans le processus que l’antivirus existant utilisait pour les opérations WSC, les appels COM d’enregistrement d’un nouvel antivirus et de mise à jour d’état ont fonctionné correctement

Tentative de suppression du binaire antivirus

  • Pour éviter qu’un nouveau projet ne fasse à nouveau l’objet d’une réclamation de la part de l’éditeur d’antivirus existant, l’objectif était d’utiliser un binaire fourni par le système plutôt qu’un binaire d’antivirus
  • Le premier processus cible choisi a été cmd.exe, mais les appels à l’API WSC ont été refusés
  • En examinant wscsvc.dll, du code vérifiant si le processus appelant était PPL a été trouvé
  • Un processus créé avec un simple CreateProcessA n’était pas un processus protégé PPL, et je n’ai pas pu avancer davantage cette nuit-là

Jour 2 : mise en place d’un environnement de débogage distant pénible

  • Sur un MacBook arm64, il était difficile de manipuler correctement Windows x86, et je voulais éviter de devoir travailler dans un environnement arm64 ou de ne pas pouvoir utiliser x64dbg
  • Mon ami pindos m’a donné accès à son PC, auquel je me suis connecté à distance avec Parsec
  • Comme je me connectais depuis la Corée à un PC situé aux États-Unis, la latence moyenne était d’environ 210 ms
  • Le flux de travail de l’époque était extrêmement fastidieux
    • Compiler le module avec MSVC dans Windows arm64 sous Parallels
    • Partager les artefacts de build avec l’hôte via un dossier partagé
    • Copier les artefacts sur la VM du PC de pindos via AnyDesk
    • Déboguer le service WSC dans un environnement Parsec avec 210 ms de latence
  • L’environnement était si inconfortable qu’il ralentissait fortement le développement et l’analyse

Débogage du service WSC et SID WinDefend

  • Le service WSC est une DLL exécutée par svchost, et le principal obstacle à l’attachement d’un débogueur était la protection PPL
  • Dans la VM, le mode test a été activé, puis un driver retirant le PPL du processus cible avec quelques lignes de code en mode noyau a été utilisé
  • Le point d’échec lorsque cmd.exe demandait l’enregistrement d’un antivirus auprès de WSC était WscServiceUtils::CreateExternalBaseFromCaller
  • Cette fonction se faisait passer pour le client RPC, puis vérifiait si le jeton du processus appelant contenait le SID WinDefend
  • Comme je connaissais mal le fonctionnement des jetons Windows à ce moment-là, j’ai conclu qu’il serait possible de passer le contrôle en usurpant WinDefend
  • En manque de sommeil, j’ai aussi mal interprété le fait que le binaire de l’antivirus existant passait ce test IsMember

Tentative d’usurpation de WinDefend et échec

  • Après avoir étudié les jetons Windows pendant quelques heures, l’implémentation est partie dans la direction consistant à exécuter le code avec un jeton contenant le SID WinDefend afin de passer la vérification WSC
  • J’ai exécuté le code avec le SID WinDefend attaché à cmd, mais même si l’appel COM renvoyait STATUS_SUCCESS, aucun nouvel antivirus n’était effectivement enregistré
  • Cette approche s’est finalement révélée inutile, et il a fallu la revérifier le lendemain

Jour 3 : reconstruction de l’algorithme de vérification réel

  • En revérifiant, il s’est avéré que le binaire de l’antivirus existant ne passait pas la vérification du SID WinDefend
  • Passer cette vérification permettait de manipuler l’objet WSC de Windows Defender, mais comme les seuls appels WSC ne permettaient pas de désactiver immédiatement Defender, cela ne servait à rien
  • Le code d’usurpation de WinDefend a été supprimé, et l’autre branche de la condition a été analysée
  • Cette branche vérifiait les points suivants pour le binaire appelant
    • Si le processus était elevated
    • Si la signature du binaire était valide
    • Si un drapeau spécifique était présent dans les DllCharacteristics du PE
  • Le drapeau DllCharacteristics vérifié dans CSecurityVerificationManager::CreateExternalBaseFromPESettings était ForceIntegrity
  • Du code reproduisant la vérification de binaire effectuée par WSC a été créé dans le dossier wsc-binary-check du dépôt defendnot, puis testé sur des binaires System32

Utilisation de Taskmgr.exe et bug de ctx.bin

  • Comme mon ami devait réutiliser son PC, je me suis connecté directement à la VM via Parsec, mais l’environnement est devenu encore plus lent à cause de l’encodage logiciel
  • Taskmgr.exe a été utilisé à la place de cmd.exe, mais des erreurs RPC se produisaient toujours
  • En raison de la latence et des problèmes de saisie, il est devenu difficile de déboguer dans la même VM, et sur recommandation j’ai payé 30 $ pour un abonnement shadow.tech
  • La VM Shadow.tech avait une version de Windows plus ancienne, où le code de wscsvc n’était pas aussi fortement inliné dans une seule fonction que dans les versions récentes, et le résultat de décompilation était plus lisible
  • La véritable cause de l’erreur était un nom d’AV incorrect transmis à WSC
    • defendnot-loader utilisait ctx.bin, qui contenait des paramètres sérialisés, pour transmettre des données à defendnot.dll
    • Un IPC séparé avait été implémenté pour le suivi d’état, mais pour la transmission de configuration, l’ancien mécanisme ctx.bin, vestige du code de no-defender, subsistait
    • La fonction recherchant le chemin de ctx.bin utilisait comme base le dossier par défaut du module Taskmgr.exe, et non celui de nodefend.dll
    • En conséquence, un octet nul était transmis comme nom d’AV, et WSC rejetait ce buffer
  • Après correction du problème de chemin, le test a réussi

Nettoyage du code et problème d’autorun

  • Pour terminer le jour même, le nettoyage du code et l’implémentation de fonctionnalités supplémentaires se sont poursuivis jusqu’à 8 h du matin
  • Parmi les fonctionnalités ajoutées figurait l’ajout de lui-même à l’autorun
  • À 8 h, seul l’autorun ne fonctionnait pas correctement ; après avoir testé plusieurs méthodes sans succès, je suis allé dormir
  • En revérifiant le lendemain, la cause venait de deux cases à cocher liées à l’alimentation lors de la création d’une tâche dans le planificateur de tâches
  • Comme l’ordinateur portable n’était pas branché sur secteur, la tâche ne s’exécutait pas ; après désactivation de ces drapeaux, l’autorun a fonctionné
  • Quelques heures supplémentaires ont ensuite été consacrées au nettoyage du code, puis le travail a été terminé

Conclusion

  • Le travail en lui-même était amusant, mais les problèmes d’environnement et le flux de débogage distant répétés pendant plusieurs jours sont une expérience que je ne veux pas revivre
  • En particulier, le MacBook arm64, la VM x86 distante, la forte latence, l’encodage lent et le bug de chemin de fichier découvert tardivement ont beaucoup augmenté la difficulté de l’implémentation
  • Une documentation WSC plus technique sera publiée séparément plus tard

1 commentaires

 
GN⁺ 2025-05-13
Avis sur Hacker News
  • La méthode la plus intrusive, mais efficace, que j’aie trouvée pour désactiver Defender consistait à démarrer sur un live USB Linux, à renommer C:\ProgramData\Microsoft\Windows Defender, puis à créer un fichier vide à cet emplacement

    • La stratégie de groupe fonctionne toujours très bien, donc dans mon homelab j’ai un contrôleur de domaine local qui modifie automatiquement uniquement les stratégies Defender pour tous les utilisateurs
    • Un produit populaire fonctionnait pratiquement de la même manière et a fini, en quelque sorte, par faire tomber environ 25 % de tout Internet avec lui
    • C’est étrange que Windows ne détecte pas ce genre de changement via des manifestes signés
  • À noter que WSC signifie Windows Security Center

  • L’expression the antivirus I was using m’a pas mal embrouillé. Je ne comprenais pas pourquoi cet éditeur d’antivirus aurait une raison d’envoyer à l’auteur une demande de retrait DMCA
    Je suppose que cela veut dire que l’auteur a rétroconçu un autre antivirus et en a intégré une partie dans un projet open source. Mais comme on voit aussi des titres du genre Impersonating WinDefend, je me demande au final si l’auteur a enfreint le droit d’auteur d’une manière ou d’une autre

    • D’après ce que j’ai compris, il a utilisé l’enveloppe d’un autre outil antivirus pour contourner les exigences de signature. Je comprends que ce soit une zone grise, et je pense qu’on pourrait y voir un usage transformatif, mais je ne suis pas juriste
    • Oui. Il a copié une partie d’un programme antivirus existant et a donc enfreint le droit d’auteur
      Juste avant le paragraphe cité, il est expliqué que « le projet utilisait du code tiers d’un antivirus déjà existant et forçait cet antivirus à s’enregistrer comme antivirus auprès de WSC »
  • Ce code donne l’impression d’être maudit :
    https://github.com/es3n1n/defendnot/blob/master/defendnot-lo...
    Si vous voulez savoir ce qui se passe réellement, c’est ici :
    https://github.com/es3n1n/defendnot/blob/master/cxx-shared/s...

    • Quelqu’un qui maîtrise la magie du C++ peut expliquer ce qui se passe et pourquoi on dit que c’est maudit ?
    • À cause des contraintes de temps, je n’avais pas envie d’implémenter moi-même du RAII pour les objets liés à COM. Mais je compte changer ça dans la prochaine mise à jour
    • Je ne vois pas ce qu’il y a de maudit. La signature côté appel est un peu différente de mes goûts personnels, mais j’utilise ce pattern un peu partout dans mon propre code
      Par exemple, le langage D intègre directement la notion d’instruction exécutée à la fin d’une portée
    • « Le code est une manière de traiter ses collègues » - Michael Feather, https://x.com/mfeathers/status/1031176879577780224
      En résumé, ce n’est pas écrit par une IA. Ce code diffère l’appel d’une fonction jusqu’au moment où l’objet sort de sa portée. L’implémentation utilise des macros C pour créer une syntaxe plus courte qui omet une partie de la définition nécessaire d’une lambda/fonction anonyme en C, et génère un nom de variable unique chargé de gérer l’appel différé
      Cela dit, la syntaxe obtenue évite la convention courante des macros C, à savoir l’écriture en majuscules, et ressemble au premier coup d’œil à un appel de fonction sur un pointeur d’objet. Si l’on n’est pas familier de ce pattern, ou si l’on s’attend à ce que les macros soient signalées autrement, cela peut prêter à confusion
      Pour certains, c’est suffisamment courant et utile pour être presque considéré comme un idiome dans certains contextes. Pour une explication technique, https://news.ycombinator.com/item?id=43959403#43960905 détaille bien le fonctionnement de la macro
  • Pendant mes vacances, j’ai rétroconçu les bureaux virtuels de Windows, et mes vacances n’en ont été que meilleures. Mon meilleur souvenir de l’an dernier, c’est d’avoir découvert à quel point la rétro-ingénierie est amusante
    J’ai aussi appris beaucoup de choses intéressantes, notamment qu’il existe sous le RPC de Windows une couche de messagerie non documentée : https://csandker.io/2022/05/24/Offensive-Windows-IPC-3-ALPC....

  • À chaque fois, je constate que si la photo de profil est un personnage d’anime, l’article sera bon. Je garde ça de côté au cas où je devrais un jour revenir à un environnement Windows médiocre

  • Pour ceux qui se posent la question : WSC signifie Windows Security Center. J’ai dû le chercher moi aussi

    • C’est indiqué dans l’article : « la partie du système qui gère ce bazar s’appelle Windows Security Center, ou WSC en abrégé »
  • Pourquoi vouloir désactiver WSC ?

    • Ça peut être pour les performances, ou pour du développement de malware ou du hacking
    • Si vous êtes un attaquant, vous pouvez espérer tomber sur le cas chanceux où aucun autre produit de détection et réponse sur les endpoints n’est installé. S’il y en a un, il interceptera presque certainement l’opération
      Si vous êtes un éditeur d’EDR, il s’agit d’un appel d’API obfusqué pouvant servir à inhiber ou désactiver Windows Firewall. Par exemple, j’imagine que CrowdStrike peut soit utiliser Windows Firewall, soit sa propre implémentation
    • C’est mon matériel, donc j’en fais ce que je veux
    • Tout logiciel antivirus est au minimum un powervirus. Je n’ai pas envie qu’on me materne en me disant que netcat.exe est interdit
    • Parce qu’il n’y a aucune raison de vouloir s’installer volontairement un rootkit à soi-même
  • J’ai récemment lu https://nostarch.com/windows-security-internals, et cet article m’a beaucoup plus parlé grâce à ça
    Je savais déjà vaguement comment ce genre de fonctionnement en coulisses se passe dans Windows, mais le timing était bon. Le dernier chapitre de ce livre creuse aussi assez en détail les tokens et SID, comme ce que traite l’auteur de cet article