
Projet de recherche rétro-ingénierie des interfaces COM du Centre de sécurité Windows pour tracer l'enregistrement des antivirus via ATL, vtable, WSCAPI et RPC, avec vérification à l'exécution via WMI.
OWN-Defender est un projet de recherche sur la sécurité Windows axé sur la compréhension de la manière dont le Centre de sécurité Windows (WSC) représente et gère les produits de sécurité antivirus via ses interfaces COM.
Le projet a débuté comme une investigation sur le comportement démontré par DefendNot, mais plutôt que de traiter l'implémentation existante comme une boîte noire, je l'ai utilisée comme point de départ pour une rétro-ingénierie indépendante et une vérification.
L'objectif de ce projet est de comprendre le chemin d'exécution complet :
COM
↓
CLSID / IID
↓
CoCreateInstance
↓
QueryInterface
↓
ATL Interface Map
↓
vtable
↓
IWscAVStatus4
↓
CWscIsv
↓
WSCAPI.dll
↓
RPC
↓
Centre de sécurité Windows
Le projet a été développé et testé dans un environnement de recherche Windows contrôlé.
Usage exclusivement destiné à la recherche / à l'éducation
Ce projet est destiné à la recherche sur les internals Windows, à la rétro-ingénierie, à l'éducation en sécurité et aux tests de sécurité autorisés. Ne l'utilisez pas pour interférer avec des logiciels de sécurité sur des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de test.
La question initiale était simple :
Comment le Centre de sécurité Windows sait-il qu'un produit antivirus existe ?
Au lieu de m'arrêter à la documentation publique de l'API, je voulais comprendre ce qui se passe sous l'API.
Cela a conduit à plusieurs questions :
QueryInterface() résout-il l'interface ?__int64 a1 pour une méthode ?Register() est réellement la fonction d'enregistrement AV ?La première étape consistait à identifier la classe COM du Centre de sécurité Windows.
Le projet utilise la classe COM WSC :
CLSID_WscIsv
F2102C37-90C3-450C-B3F6-92BE1693BDF2
L'implémentation contient également une logique permettant de localiser dynamiquement le CLSID dans le registre Windows au lieu de se fier exclusivement à une valeur codée en dur.
Conceptuellement :
HKLM
└── SOFTWARE
└── Classes
└── CLSID
└── {CLSID}
└── API ISV du Centre de sécurité Windows
Cela a fourni la première relation importante :
Registre
↓
CLSID
↓
API ISV du Centre de sécurité Windows
Le défi suivant consistait à déterminer quelle interface COM devait être demandée.
Le projet utilise :
IWscAVStatus4
avec :
4DCBAFAC-29BA-46B1-80FC-B8BDE3C0AE4D
L'une des leçons importantes de la recherche était :
Un nom de GUID seul ne constitue pas une preuve suffisante.
J'ai vérifié la relation par rétro-ingénierie plutôt qu'en supposant que le nom de l'interface et le GUID étaient corrects.
L'investigation comprenait :
QueryInterface_ATL_INTMAP_ENTRYQueryInterfaceL'une des étapes de rétro-ingénierie les plus utiles a été de suivre l'implémentation de :
CComAggObject<CWscIsv>::QueryInterface()
qui atteint finalement :
ATL::CComObjectRootBase::InternalQueryInterface()
La table des interfaces ATL est utilisée pour comparer l'IID demandé aux entrées d'interface enregistrées.
Conceptuellement :
IID demandé
↓
QueryInterface()
↓
InternalQueryInterface()
↓
Table des interfaces ATL
↓
Comparaison GUID
↓
Interface correspondante
↓
Pointeur d'interface
Cela a fourni une preuve indépendante que le GUID étudié correspondait effectivement à l'interface COM attendue.
Register()L'un des plus grands défis de rétro-ingénierie a été de comprendre pourquoi IDA/Ghidra n'affichait pas toujours la signature de méthode que j'attendais.
L'interface reconstruite contient :
virtual HRESULT __stdcall Register(
BSTR path,
BSTR name,
unsigned int,
unsigned int
) = 0;
Cependant, le décompilateur pouvait afficher une implémentation telle que :
_IWscAVStatus4<CWscIsv>::Register(__int64 a1)
Au premier abord, cela semblait incohérent.
Des investigations plus poussées ont montré que la représentation du décompilateur décrivait un wrapper/thunk et l'appel vtable indirect sous-jacent plutôt que de présenter la signature d'interface logique complète.
C'est devenu une leçon importante :
La sortie d'un décompilateur est une interprétation du code machine, pas la vérité au niveau du code source original.
Pour résoudre ces divergences, j'ai comparé :
Définition de l'interface COM
↓
Disposition de la vtable
↓
Assembleur
↓
wrapper/thunk
↓
Convention d'appel
↓
Fonction cible réelle
Register()Une autre source de confusion était la présence de plusieurs fonctions portant des noms tels que :
IWscAVStatus2::Register
IWscAVStatus4::Register
IWscFWStatus2::Register
RegisterAV
La prise de conscience importante était que des noms similaires ne signifient pas des interfaces identiques.
Par exemple :
AV
↓
IWscAVStatus4
↓
Enregistrement AV
tandis que :
Pare-feu
↓
IWscFWStatus2
↓
Enregistrement du pare-feu
Le numéro d'interface et l'implémentation environnante devaient être vérifiés au lieu de sélectionner une fonction simplement parce que son nom contenait Register.
C'était l'une des parties les plus utiles de la recherche car elle m'a obligé à corréler :
Interface
+
IID
+
vtable
+
implémentation
+
disposition des paramètres
+
cible d'appel
Après avoir identifié la bonne interface, j'ai tracé l'opération d'enregistrement plus profondément dans le binaire.
Le chemin observé était approximativement :
IWscAVStatus4::Register()
↓
CWscIsv
↓
RegisterSecurityProductFunction
↓
wscRegisterSecurityProduct()
↓
WSCAPI.dll
↓
s_wscRegisterSecurityProduct()
↓
NdrClientCall3()
↓
RPC
↓
Centre de sécurité Windows
C'était particulièrement important car la méthode COM elle-même n'était pas l'opération finale.
L'appel franchissait finalement une frontière RPC.
Cela a changé ma façon de voir l'architecture :
COM
≠
implémentation finale
Au lieu de cela :
COM
↓
implémentation locale
↓
API WSC
↓
client RPC
↓
composant Windows
WSCAPI.dllLa couche suivante était WSCAPI.dll.
Le chemin rétro-ingénié atteignait :
wscRegisterSecurityProduct()
qui invoquait finalement :
s_wscRegisterSecurityProduct()
puis :
NdrClientCall3()
C'était le point où l'investigation passait d'un appel COM normal à l'infrastructure RPC Windows.
Comprendre cette couche a aidé à expliquer pourquoi le comportement ne pouvait pas être entièrement compris en regardant uniquement la DLL COM d'origine.
L'analyse statique n'était qu'une partie de la recherche.
Après avoir reconstruit l'interface et le chemin d'appel pertinents, j'ai créé ma propre implémentation contrôlée et comparé le comportement résultant avec le Centre de sécurité Windows.
J'ai utilisé les informations du Centre de sécurité Windows / WMI telles que :
ROOT\SecurityCenter2
AntiVirusProduct
pour observer indépendamment les informations du produit enregistré.
Le processus de vérification était :
Rétro-ingénierie
↓
Reconstruction de l'interface
↓
Implémentation personnelle
↓
Exécution à l'exécution
↓
Centre de sécurité Windows
↓
Observation WMI
↓
Comparaison des résultats
Cela m'a permis de vérifier que les conclusions de l'analyse statique correspondaient au comportement Windows observable.
Ce projet m'a appris considérablement plus que la simple interaction avec une interface COM.
CoCreateInstanceQueryInterfaceWSCAPI.dllNdrClientCall3Le plus important, j'ai appris à éviter de me fier à une seule preuve.
Au lieu de cela :
Symbole
↓
Décompilateur
↓
Assembleur
↓
GUID
↓
Table des interfaces
↓
vtable
↓
Graphe d'appels
↓
RPC
↓
Vérification à l'exécution
Chaque couche augmente la confiance dans la conclusion.
L'implémentation de recherche se compose de deux composants principaux.
OWN-Defender
│
├── OWN-Defender.cpp
│ ├── Interaction COM WSC
│ ├── Découverte du CLSID
│ ├── Initialisation COM
│ ├── Interaction IWscAVStatus4
│ ├── Enregistrement
│ ├── Mise à jour du statut
│ └── Nettoyage
│
└── dllmain.cpp
├── Point d'entrée DLL
├── Chargeur de recherche
├── Exécution contrôlée
└── Gestion du nettoyage/arrêt
Le dépôt est volontairement petit afin que la relation entre le comportement rétro-ingénié et l'implémentation reste facile à suivre.
Ce projet a été construit autour de questions plutôt que de simplement reproduire une fonctionnalité :
Comment WSC identifie-t-il la classe COM ?
Comment l'IID est-il mappé à l'interface ?
Comment QueryInterface localise-t-il l'interface ?
Pourquoi IDA affiche-t-il des signatures de fonctions différentes ?
Où se trouve la vtable réelle ?
Quel Register() est l'implémentation AV ?
Que se passe-t-il après la méthode COM ?
Où WSCAPI.dll entre-t-il dans la chaîne d'appels ?
Où commence le RPC ?
Comment le résultat peut-il être vérifié indépendamment ?
Ces questions ont finalement été plus précieuses que l'implémentation finale elle-même.
Le projet fournit également un point de départ utile pour étudier la frontière de sécurité entre :
Application
↓
COM
↓
Centre de sécurité Windows
↓
Informations du fournisseur de sécurité
Une distinction importante est que l'enregistrement d'informations de produit de sécurité n'équivaut pas automatiquement à la désactivation du moteur Defender ou au contournement de ses mécanismes de protection.
Par conséquent, ce projet doit être considéré principalement comme :
Recherche en rétro-ingénierie sur le Centre de sécurité Windows / COM
plutôt que comme une affirmation selon laquelle l'enregistrement WSC seul constitue une vulnérabilité de Defender.
Tout impact sur la sécurité nécessite une investigation et une validation séparées.
Cette recherche a été inspirée en partie par le travail démontré dans DefendNot par es3n1n.
Un merci spécial à l'auteur pour avoir fourni un point de départ utile pour comprendre le mécanisme WSC.
Projet original : https://github.com/es3n1n/defendnot
Le but de ce dépôt n'est pas de revendiquer la recherche originale comme mienne, mais de documenter mon propre processus de rétro-ingénierie, mon implémentation indépendante et ma vérification du comportement Windows sous-jacent.
Ce dépôt est fourni pour :
Utilisez ce projet uniquement sur des systèmes que vous possédez ou pour lesquels vous êtes explicitement autorisé à tester.
L'auteur n'est pas responsable des mauvais usages, dommages, pertes de données, interférences avec les contrôles de sécurité ou déploiements non autorisés.
Ce projet est sous licence GNU General Public License v3.0.
Voir LICENSE pour plus de détails.
L'objectif principal d'OWN-Defender n'est pas simplement de reproduire une technique d'enregistrement AV.
Il s'agit de démontrer une méthodologie de rétro-ingénierie reproductible :
Trouver
↓
Cartographier
↓
Rétro-ingéniérer
↓
Reconstruire
↓
Tracer
↓
Implémenter
↓
Vérifier
Ce qui a commencé avec une question sur le Centre de sécurité Windows est devenu une exploration plus approfondie de COM, ATL, le mappage GUID/IID, les vtables, le code généré par le compilateur, WSCAPI, RPC et l'architecture de sécurité Windows.
L'implémentation est le résultat. Le processus de rétro-ingénierie est le véritable projet.