NtClose

この記事をシェア

概要

オープンされているオブジェクトハンドルをクローズするWin32 APIの関数です。無効なハンドルや保護されたハンドルを指定することでデバッガーを検出することが可能です。
NtCloseは、CloseHandle実行時にも呼び出されるネイティブAPIであり、解析妨害としての使い方はCloseHandleと同じです。

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

C++

NTSTATUS NtClose(
  [in] HANDLE Handle
);

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

実装の例

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

C++

typedef NTSTATUS(NTAPI* pfnNtClose) (
    HANDLE Handle
    );

HMODULE hNtDll = LoadLibraryA("ntdll.dll");
pfnNtClose NtClose = (pfnNtClose)GetProcAddress(hNtDll, "NtClose");

DWORD dCode;
__try {
    NtClose((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
    push    offset LibFileName ; "ntdll.dll"
    call    ds:LoadLibraryA
    push    offset ProcName ; "NtClose"
    push    eax             ; hModule
    call    ds:GetProcAddress
    mov     [ebp+ms_exc.registration.TryLevel], 0
    push    0DEADBEEFh      ; Handle
    call    eax             ; NtClose
loc_debuger_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

回避手法

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

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

検出手法

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

YARAルール

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