Skip to content

i014n/RightHand-Persistence

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RightHand Persistence

inspired by CVE-2026-21509

C++ COM Context Menu Handler for Persistence

A sample implementation of a Windows context menu handler using C++ and COM, demonstrating a stealthy persistence technique. By registering a custom COM object, your code executes whenever a user right-clicks on specific targets (files, folders, or backgrounds) in Windows Explorer.

Disclaimer: This project is intended for educational and research purposes only. The techniques demonstrated here can be used for malicious purposes. The author does not condone the use of this code for any illegal activity. Be responsible and use this knowledge ethically.


POC

poc

Getting Started

Prerequisites

  • A C++ compiler (e.g., MSVC from Visual Studio, or MinGW-w64)
  • Windows SDK
  • Testing Virtual Machine (for safe registration and execution)

My Setup

  • IDE: Visual Studio 2019
  • VM Development: Windows 10 x64 (Build 19045)
  • VM Test: Windows 10 x64 / Windows 11 x64

Project Architecture

                                       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

1. DllMain.cpp

Contains the standard functions required by a COM object to register and unregister the DLL.

  • DllRegisterServer(): Writes the registry paths corresponding to the target file extensions/backgrounds. Executed when the DLL is registered.
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(): Cleans up the registry. Called when the DLL is unregistered.

2. MyClassFactory

Required to instantiate the COM object. Read More on Class Factories.

3. Clsid_defined.h

Contains the GUID under which the application will be registered in Explorer. You can generate a new GUID using Visual Studio's guidgen.exe or an online GUID Generator.

// {CEF1AA1B-42F7-4A54-AF46-BCEE5B3FE6BF}
DEFINE_GUID(CLSID_DecrypShellExtensionx64, 0xcef1aa1b, 0x42f7, 0x4a54, 0xaf, 0x46, 0xbc, 0xee, 0x5b, 0x3f, 0xe6, 0xbf);

4. Source.def

The Module-Definition file. This dictates which functions the DLL exports. Read More on .DEF files.

EXPORTS
    DllGetClassObject PRIVATE
    DllCanUnloadNow PRIVATE
    DllRegisterServer PRIVATE
    DllUnregisterServer PRIVATE

5. MyMenuHandler.cpp

The core class implementing IShellExtInit and IContextMenu. This is where you define your custom actions.

  • MyContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgId) Called every time a right-click occurs on your registered target. Used to parse what file or folder was clicked.
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) Called when the user clicks your specific custom option from the context menu. This is where your persistence payload or custom action executes.

Testing

On the target VM, copy the compiled DLL and run the following commands:

1. Registration

Register the DLL using standard Windows binaries.

regsvr32.exe RightHandPersistence.dll

2. Restart Explorer

Restart the explorer.exe process to ensure it loads the new shell extension into memory.

taskkill /f /im explorer.exe & start explorer.exe

3. Unregistration

To remove the context menu handler and clean up the registry, use the /u flag with regsvr32.exe. This calls your DllUnregisterServer function.

regsvr32.exe /u RightHandPersistence.dll

Customization

1. Targeting Specific Locations

Windows categorizes "empty space" differently than files. To target the background, map your registry keys to these specific locations.

Right-click Target Registry Key Path
Files (All) HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers
Folders (The icon) HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers
Folder Background HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers
Desktop Background HKEY_CLASSES_ROOT\DesktopBackground\shellex\ContextMenuHandlers

More details on mapping extensions can be found in the Microsoft Shell Context Menu documentation.

2. Creating Custom Menu Commands

You can specify custom text for the menu (e.g., "Custom Copy" or "Run Diagnostics") by implementing the IContextMenu::QueryContextMenu method. Clicking this custom text triggers your logic inside IContextMenu::InvokeCommand.


References

About

COM Windows Persistence Technique

Topics

Resources

Stars

Watchers

Forks

Contributors