CloseHandle

この記事をシェア

概要

オープンされているオブジェクトハンドルをクローズするWin32 APIの関数です。無効なハンドルや保護されたハンドルを指定することでデバッガーを検出することが可能です。

関数のプロトタイプは以下のとおりです。

C++

BOOL CloseHandle(
  [in]      HANDLE hObject,
);

第一引数のhObjectに無効なハンドルを指定することで、実行中のプロセスがデバッグされている場合、STATUS_INVALID_HANDLE(0xC0000008)例外が発生します。これにより、デバッガーの存在を検出することが可能です。

このほかにも、保護されたハンドルを使用する方法も存在します。保護されたハンドルを第一引数のhObjectに指定し、実行中のプロセスがデバッグされていた場合は、EXCEPTION_HANDLE_NOT_CLOSABLE(0xC0000235)例外が発生します。

実装の例

無効なハンドルを指定し、STATUS_INVALID_HANDLE(0xC0000008)例外によりデバッガーを検出するC++/x86 Assemblyのコード例を以下に示します。

C++

DWORD dCode;
__try {
    CloseHandle((HANDLE)0xDEADBEEF);
}
__except (dCode = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER) {
    if (dCode == EXCEPTION_INVALID_HANDLE) {
        exit(1);
    }
}

Assembly(x86)

    push    0FFFFFFFFh
    push    offset _scopetable_entry
    push    offset _except_handler3
    mov     eax, large fs:0
    push    eax
    mov     large fs:0, esp
    sub     esp, 16
    push    ebx
    push    esi
    push    edi
    mov     [ebp+ms_exc.old_esp], esp
    mov     [ebp+ms_exc.registration.TryLevel], 0
    push    0DEADBEEF      ; hObject
    call    CloseHandle
loc_debugger_not_found:

; ---------------------------------------------------------------------------
loc_except_filter:
    mov     eax, [ebp+ms_exc.exc_ptr]
    mov     eax, [eax]
    mov     eax, [eax]          ; GetExceptionCode()
    mov     [ebp+var_20], eax
    mov     [ebp+dCode], eax
    mov     eax, 1
    retn
; ---------------------------------------------------------------------------
loc_except:
    mov     esp, [ebp+ms_exc.old_esp]
    cmp     [ebp+dCode], EXCEPTION_INVALID_HANDLE
    jnz     short loc_debugger_not_found
    push    1
    call    exit

回避手法

CloseHandleによるデバッガー検出を回避し、プログラムを解析する手法を以下に示します。一時的に検出を回避するときには1、2の手法を、恒久的に検出を回避するときには3の手法を使います。

  • デバッグ中にレジスタやメモリ上の値を変更する
    GetExceptionCodeの戻り値の値を変更します。
  • プラグインを利用する
    ScyllaHide(x64dbgなどで利用可能なプラグイン)の”NtClose”の項目にチェックを入れます。
  • プログラムを書き換える
    CloseHandleの処理をNOP命令に書き換え、変更を保存します。

検出手法

CloseHandleのSTATUS_INVALID_HANDLE(0xC0000008)例外によるアンチデバッグ機能を有するファイルを検出するYARAルールは以下のとおりです。

YARAルール

rule Win32API_CloseHandle
 { 
	strings:
		$str = "CloseHandle"
		$hex = {81 [1-2] 08 00 00 C0}
	condition:
		$str and $hex
 }
この記事をシェア
サイバーセキュリティ
情報局の最新情報を
チェック!