概要
指定されたプロセスの情報を設定するWin32 APIの関数です。PEB(Process Environment Block)構造体へのポインターやWOW64環境で実行されているかどうかを判別する値など、指定する引数に応じてさまざまな情報を設定することができます。
C++
NTSTATUS NtSetInformationProcess(
[In] HANDLE ProcessHandle,
[In] PROCESSINFOCLASS ProcessInformationClass,
[In] PVOID ProcessInformation,
[In] ULONG ProcessInformationLength
);
第二引数のProcessInformationClassで設定する情報のタイプを指定し、第三引数のProcessInformationで設定する値を指定します。
マルウェアの解析妨害においては、ProcessInformationClassとしてProcessBreakOnTermination(0x1D)を指定する手法が挙げられます。この手法を用いると、マルウェアはデバッガーを検知して自身を終了させ、同時にBSoD(Blue Screen of Death)を発生させます。
ProcessBreakOnTerminationタイプの値を設定するためには、デバッグ特権が必要です。解析者がデバッガーを利用する際、以下の理由によりデバッグ特権を有効にする場合があります。
(1) デバッグ対象プロセスの実行権限の関係で、デバッガーでアタッチするためのハンドルを取得できないことがある。
(2) プロセスの詳細情報を取得する処理などが、OSによって制約を受けることがある。
よってマルウェアにデバッグ特権が付与されている場合、デバッガー上で実行されていると判断し、自身を終了させる処理に分岐させます。
なおProcessBreakOnTerminationは、指定プロセスがクリティカルプロセスであるかどうかを示すタイプです。クリティカルプロセスはOSの実行に不可欠なシステムプロセスと位置付けられます。よってこのクリティカルプロセスが終了するとOSの動作が継続できないと判断され、BSoD(Blue Screen of Death)が発生します。
実装の例
C++/x86 Assemblyのコード例を以下に示します。
C++
typedef NTSTATUS (NTAPI* pfnNtSetInformationProcess)(
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength
);
HMODULE hNtDll = LoadLibraryA("ntdll.dll");
pfnNtSetInformationProcess NtSetInformationProcess = (pfnNtSetInformationProcess)GetProcAddress(hNtDll, "NtSetInformationProcess");
NTSTATUS status;
UINT CriticalProcess = 0x01;
status = NtSetInformationProcess(
GetCurrentProcess(),
0x1D,
&CriticalProcess,
sizeof(CriticalProcess)
);
if (NT_SUCCESS(status)) {
exit(1);
}
Assembly(x86)
push 4 ; ProcessInformationLength
mov [ebp-0Ch], 1
lea edx, [ebp-0Ch]
push edx ; ProcessInformation
push 1Dh ; ProcessInformationClass
call GetCurrentProcess
push eax ; ProcessHandle
call NtSetInformationProcess
test eax, eax
jns short loc_being_debugged
loc_being_debugged:
push 1
call exit ; Occurrence of BSoD
回避手法
NtSetInformationProcessによるマルウェア解析環境検知を回避し、プログラムを解析する手法を以下に示します。一時的に検出を回避するときには1または2の手法を、恒久的に検出を回避するときには3の手法を使います。
- デバッグ中に引数を書き換える
NtSetInformationProcessが呼び出される前に、ProcessInformationの値を1から0に書き換えます。 - プラグインを利用する
ScyllaHide(Ollydbg, x64dbgなどで利用可能なプラグイン)の” NtSetInformationProcess”の項目にチェックを入れます。 - プログラムを書き換える
NtSetInformationProcessが呼び出される前のProcessInformationの値が0となるように書き換え、変更を保存します。
検出手法
NtSetInformationProcessを検出するYARAルールを以下に示します。
YARAルール
rule Win32API_NtSetInformationProcess
{
strings:
$str ="NtSetInformationProcess"
condition:
$str
}