
P³-Shellcode Loader は、一般的な検知メカニズムをトリガーすることなく、リモートプロセスへのシェルコード注入の実行およびステージングの場所として Process Parameters 構造体を利用する、コードインジェクション技術を実装したローダーです。
著者: Max Hirschberger & Ogulcan Ugur
P³-Shellcode Loader は、一般的な検知メカニズムを引き起こすことなく、リモートプロセスへのシェルコードインジェクションの実行およびステージングの場所として Process Parameters 構造体(プロセスパラメータポイズニング)を活用するコードインジェクション技術を実装したローダーです。
同様のコンセプトは、セキュリティ研究者 modexp によって説明されており、CreateProcess API に渡される引数がこの目的に利用可能であることを実証しました [1]。
攻撃者は、自身の活動をより疑われにくくしたいと考えます。プロセスインジェクションを用いることで、攻撃者はより信頼されている、または特定の活動を行うと期待される別のプロセスから活動を実行できるため、疑念を低減できます。
別のプロセスにコードを注入するために必要な典型的な手順は以下のとおりです:
OpenProcess / NtOpenProcess または CreateProcess / NtCreateProcess を介して)。VirtualAllocEx または NtAllocateVirtualMemory を介して)。WriteProcessMemory / NtWriteVirtualMemory を介して)。VirtualProtectEx / NtProtectVirtualMemory を介して)。CreateRemoteThread または NtCreateThreadEx を介して)。その他のインジェクション技術には、以下が含まれますがこれらに限定されません:
NtSetContextThread を介して)NtQueueApcThread を介して)RtlCreateProcessReflection を悪用します。
私たちのテストでは、ほとんどのEDRがプロセスインジェクションを検知するために特定のテレメトリに焦点を当てていることを観察しました。EDRは主に WriteProcessMemory と VirtualAllocEx、およびその基盤となるカーネルシステムコールである NtWriteVirtualMemory、NtAllocateVirtualMemory、NtAllocateVirtualMemoryEx の使用を監視します。Windows は、新しいプロセスを作成するための API 関数 CreateProcessW を提供します(リスト 1 を参照)。そのパラメータの最初の3つ、lpCommandLine、lpEnvironment、lpStartupInfo は、新しいプロセスにデータを転送するために使用されるため、説明したインジェクション技術に関連します。```c
BOOL CreateProcessW(
[in, optional] LPCWSTR lpApplicationName,
[in, out, optional] LPWSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCWSTR lpCurrentDirectory,
[in] LPSTARTUPINFOW lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
*リスト 1: CreateProcessW Windows API 関数の定義*
`lpCommandLine` パラメータは、新しいプロセスのコマンドラインを指定します。これは、unicode の null 終端文字を含めて最大 32,767 文字に制限されています。unicode バリアントの場合、関数が書き込むことのできる文字列を指定する必要があります。定数文字列が指定された場合、API 関数による書き込み試行はメモリアクセス違反を引き起こします。値が `NULL` の場合、プロセスのコマンドラインは `lpApplicationName` パラメータから取得されます。`lpApplicationName` が `NULL` の場合、コマンドラインは `lpCommandLine` フィールドで指定する必要があり、`MAX_PATH` 文字に制限されます。
`lpEnvironment` パラメータは、プロセスに環境変数のリストを提供します。値が `NULL` の場合、作成元プロセスの環境が使用されます。環境変数のリストは、`NAME=VALUE` 形式の連続した null 終端文字列で構成され、末尾に別の null 終端文字が付きます。
`lpStartupInfo` パラメータは、リスト 2 に示す構造体であり、ウィンドウステーション、デスクトップ、標準入力および標準出力ハンドルなどのフィールドに加えて、新しいプロセスのメインウィンドウを構成するフィールドを持ちます。Microsoft のドキュメントによると、`lpReserved` フィールドは内部使用のために予約されており、それ以上のドキュメントはありません。WinDbg デバッガによる解析を通じて、このパラメータを新しいプロセスの `UNICODE_STRING` 型の `ShellInfo` 変数に関連付けることができました。```c
typedef struct _STARTUPINFOW {
DWORD cb;
LPWSTR lpReserved; // Copied to ShellInfo (UNICODE_STRING)
LPWSTR lpDesktop;
LPWSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
// (...) additional fields
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
// (...) additional fields
} STARTUPINFOW, *LPSTARTUPINFOW;
リスト 2: STARTUPINFOW データ構造のレイアウト
新しいプロセスが作成されると、指定されたすべてのプロセスパラメータがプロセス環境ブロック (PEB) に書き込まれます。PEB は、すべてのプロセスに存在し、各プロセスに固有のデータ構造です。これらのパラメータは、型 RTL_USER_PROCESS_PARAMETERS の ProcessParameters メンバー内でアクセスできます。プロセスパラメータのほかに、この構造体には、読み込まれたモジュールのリストなどの実行時情報も含まれます。PEB の構造と、RTL_USER_PROCESS_PARAMETERS 内の関連するプロセスパラメータを、リスト 3 とリスト 4 に示します。```c
typedef struct _PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
// (...) additional fields
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // Poisonable
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
// (...) additional fields
} PEB, *PPEB;
*リスト3: PEBデータ構造のレイアウト*```c
typedef struct _RTL_USER_PROCESS_PARAMETERS
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
// (...) additional fields
CURDIR CurrentDirectory;
UNICODE_STRING DllPath; // Potential candidate for transfer
UNICODE_STRING ImagePathName; // Potential candidate for transfer
UNICODE_STRING CommandLine; // Primary candidate for transfer
PVOID Environment; // Primary candidate for transfer
// (...) additional fields
UNICODE_STRING ShellInfo; // Primary candidate for transfer
// (lpReserved in STARTUPINFO)
UNICODE_STRING RuntimeData; // Potential candidate for transfer
// (...) additional fields
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
リスト4:RTL_USER_PROCESS_PARAMETERSデータ構造のレイアウト
図1は、STARTUPINFOW構造体のlpReservedフィールドに指定されたポイズン値を持つShellInfoパラメータを示しています。さらに、図2はSystem Informerツール内の制御されたコマンドラインを示しています。
図1:ポイズン化されたShellInfoパラメータ
図2:ポイズン化されたコマンドライン