概要
指定されたシステム情報を取得するWin32 APIの関数です。システム上で動作しているプロセッサー数の情報や、乱数生成時に使用されるシード値の情報など、指定する引数に応じてコンピューターシステムに関する様々な情報を取得することができます。
C++
NTSTATUS NtQuerySystemInformation(
[In] SYSTEM_INFORMATION_CLASS SystemInformationClass,
[In, out] PVOID SystemInformation,
[In] ULONG SystemInformationLength,
[In, optional] PULONG ReturnLength
);
第一引数のSystemInformationClassで取得する情報の種類を指定します。マルウェアの解析妨害においては、SystemInformationClassとしてSystemKernelDebuggerInformation(0x23)を指定して、カーネルデバッガーの存在を検知する手法が挙げられます。
SystemKernelDebuggerInformation(0x23)を指定して関数が実行されると、第二引数のSystemInformationが示す構造体に結果が返されます。この構造体はKdDebuggerEnabledとKdDebuggerNotPresentの2つのメンバから構成されます。このうち、KdDebuggerNotPresentがFalse(0x0)を示す場合、マルウェアはカーネルデバッガーを検知して自身を終了させます。
実装の例
C++/x86 Assemblyのコード例を以下に示します。
C++
typedef enum SYSTEM_INFORMATION_CLASS {
SystemKernelDebuggerInformation = 0x23
} SYSTEM_INFORMATION_CLASS;
typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION {
BOOLEAN DebuggerEnable;
BOOLEAN DebuggerNotPresent;
} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION;
typedef NTSTATUS (NTAPI* pfnNtQuerySystemInformation)(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
HMODULE hNtDll = LoadLibraryA("ntdll.dll");
pfnNtQuerySystemInformation NtQuerySystemInformation = (pfnNtQuerySystemInformation)GetProcAddress(hNtDll, "NtQuerySystemInformation");
SYSTEM_KERNEL_DEBUGGER_INFORMATION info;
NtQuerySystemInformation(
SystemKernelDebuggerInformation,
&info,
sizeof(info),
NULL
);
if (!(info.DebuggerNotPresent)) {
exit(1);
}
Assembly(x86)
push 0 ; ReturnLength
push 2 ; SystemInformationLength
lea edx, [ebp-0Ah]
push edx ; SystemInformation
push 23h ; SystemInformationClass
call NtQuerySystemInformation
cmp [ebp-9], 0
jz short loc_being_debugged
loc_being_debugged:
push 1
call exit
回避手法
NtQuerySystemInformationによるマルウェア解析環境検知を回避し、プログラムを解析する手法を以下に示します。一時的に検出を回避するときには1または2の手法を、恒久的に検出を回避するときには3の手法を使います。
- デバッグ中にフラグを書き換える
NtQuerySystemInformationが呼び出された後に、KdDebuggerNotPresentの値を0x0から0x1に書き換えます。 - デバッグ中に分岐命令を変更する
NtQuerySystemInformationを呼び出した後の分岐命令をJMP命令またはNOP命令に書き換えます。 - プログラムを書き換える
NtQuerySystemInformationを呼び出した後の分岐命令をJMP命令やNOP命令となるように書き換え、変更を保存します。
検出手法
NtQuerySystemInformationを検出するYARAルールを以下に示します。
YARAルール
rule Win32API_NtQuerySystemInformation
{
strings:
$str ="NtQuerySystemInformation"
condition:
$str
}