
P³-Shellcode Loader è un loader che implementa una tecnica di iniezione di codice che sfrutta la struttura Process Parameters come posizione di esecuzione e staging per l'iniezione di shellcode in processi remoti, senza innescare i comuni meccanismi di rilevamento.
Autori: Max Hirschberger & Ogulcan Ugur
P³-Shellcode Loader è un loader che implementa una tecnica di code injection che sfrutta la struttura dei Process Parameters (Process Parameter Poisoning) come posizione di esecuzione e staging per l'iniezione di shellcode in processi remoti, senza attivare i comuni meccanismi di rilevamento.
Un concetto simile è stato descritto dal ricercatore di sicurezza modexp, che ha dimostrato che gli argomenti passati all'API CreateProcess possono essere sfruttati per questo scopo [1].
Gli attaccanti vogliono rendere le loro attività meno sospette. Con l'iniezione di processi, gli attaccanti sono in grado di eseguire le loro attività da un processo diverso, più affidabile o che ci si aspetta stia eseguendo l'attività specifica, riducendo così i sospetti.
Di seguito sono riportati i passaggi tipici necessari per iniettare codice in un altro processo:
OpenProcess / NtOpenProcess o CreateProcess / NtCreateProcess).VirtualAllocEx o NtAllocateVirtualMemory).WriteProcessMemory / NtWriteVirtualMemory).VirtualProtectEx / NtProtectVirtualMemory).CreateRemoteThread o NtCreateThreadEx).Ulteriori tecniche di injection includono, ma non si limitano a:
NtSetContextThread)NtQueueApcThread)RtlCreateProcessReflection, che implementa il forking dei processi.
Nei nostri test, abbiamo osservato che la maggior parte degli EDR si concentra su specifiche telemetrie per rilevare l'iniezione di processi. Gli EDR monitorano principalmente l'uso di WriteProcessMemory e VirtualAllocEx, così come le loro chiamate di sistema kernel sottostanti NtWriteVirtualMemory, NtAllocateVirtualMemory e NtAllocateVirtualMemoryEx.Windows fornisce la funzione API CreateProcessW per creare nuovi processi, mostrata nel Listato 1. I primi tre dei suoi parametri lpCommandLine, lpEnvironment e lpStartupInfo sono rilevanti per la tecnica di injection descritta, poiché vengono utilizzati per trasferire dati al nuovo processo.```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
);
*Listato 1: Definizione della funzione API Windows CreateProcessW*
Il parametro `lpCommandLine` specifica la riga di comando per il nuovo processo. È limitato a un massimo di 32.767 caratteri Unicode, incluso il terminatore null Unicode. Per la variante Unicode, è necessario fornire una stringa su cui la funzione possa scrivere. Se viene fornita una stringa costante, qualsiasi tentativo di scrittura effettuato dalla funzione API comporta una violazione di accesso alla memoria. Se il valore è `NULL`, la riga di comando del processo verrà presa dal parametro `lpApplicationName`. Se `lpApplicationName` è `NULL`, deve essere fornito nel campo `lpCommandLine` ed è limitato a caratteri `MAX_PATH`.
Il parametro `lpEnvironment` fornisce un elenco di variabili d'ambiente al processo. Se il valore è `NULL`, verrà utilizzato l'ambiente del processo creatore. L'elenco delle variabili d'ambiente consiste in stringhe successive terminate da null nel formato `NAME=VALUE` con un altro terminatore null alla fine.
Il parametro `lpStartupInfo` è una struttura mostrata nel Listato 2 con campi quali stazione finestra, desktop, handle standard di input e output, nonché campi che configurano la finestra principale del nuovo processo. Secondo la documentazione Microsoft, il campo `lpReserved` è riservato per uso interno senza ulteriore documentazione. Attraverso l'analisi con il debugger WinDbg, è stato possibile correlare questo parametro alla variabile `ShellInfo` di tipo `UNICODE_STRING` nel nuovo processo.```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;
Listato 2: Struttura della struttura dati STARTUPINFOW