
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 참조). 해당 함수의 처음 세 매개변수인 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
);
*Listing 1: CreateProcessW Windows API 함수의 정의*
`lpCommandLine` 매개변수는 새 프로세스의 명령줄을 지정합니다. 유니코드 null 종결자를 포함하여 최대 32,767자의 유니코드 문자로 제한됩니다. 유니코드 변형의 경우 함수가 쓸 수 있는 문자열을 제공해야 합니다. 상수 문자열이 제공되면 API 함수가 수행하는 쓰기 시도로 인해 메모리 액세스 위반이 발생합니다. 값이 `NULL`이면 프로세스의 명령줄은 `lpApplicationName` 매개변수에서 가져옵니다. `lpApplicationName`이 `NULL`이면 `lpCommandLine` 필드에 제공해야 하며 `MAX_PATH`자로 제한됩니다.
`lpEnvironment` 매개변수는 프로세스에 환경 변수 목록을 제공합니다. 값이 `NULL`이면 생성 프로세스의 환경이 사용됩니다. 환경 변수 목록은 `NAME=VALUE` 형식의 연속된 null 종결 문자열로 구성되며 끝에 또 다른 null 종결자가 있습니다.
`lpStartupInfo` 매개변수는 Listing 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: 포이즌 처리된 명령줄