概要
オープンされているオブジェクトハンドルをクローズする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
}