NtSetInformationWorkerFactory
Setzt eine Konfigurationsklasse einer Worker Factory — darunter, in einigen PoolParty-Varianten, die StartRoutine, die Worker-Threads ausführen.
Prototyp
NTSTATUS NtSetInformationWorkerFactory( HANDLE WorkerFactoryHandle, WORKERFACTORYINFOCLASS WorkerFactoryInformationClass, PVOID WorkerFactoryInformation, ULONG WorkerFactoryInformationLength );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| WorkerFactoryHandle | HANDLE | in | Handle auf die Worker Factory. Erfordert WORKER_FACTORY_SET_INFORMATION-Zugriff. |
| WorkerFactoryInformationClass | WORKERFACTORYINFOCLASS | in | Klassen-Selektor — WorkerFactoryBasicInformation, WorkerFactoryThreadMinimum/Maximum, WorkerFactoryThreadCpuSets, WorkerFactoryAdjustThreadGoal usw. |
| WorkerFactoryInformation | PVOID | in | Puffer, dessen Layout von der Klasse abhängt — z. B. eine WORKER_FACTORY_BASIC_INFORMATION-Struktur oder ein einzelner ULONG. |
| WorkerFactoryInformationLength | ULONG | in | Größe des Informationspuffers in Bytes. Eine inkonsistente Länge liefert STATUS_INFO_LENGTH_MISMATCH. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x183 | win10-1507 |
| Win10 1607 | 0x18C | win10-1607 |
| Win10 1703 | 0x192 | win10-1703 |
| Win10 1709 | 0x195 | win10-1709 |
| Win10 1803 | 0x197 | win10-1803 |
| Win10 1809 | 0x198 | win10-1809 |
| Win10 1903 | 0x199 | win10-1903 |
| Win10 1909 | 0x199 | win10-1909 |
| Win10 2004 | 0x19F | win10-2004 |
| Win10 20H2 | 0x19F | win10-20h2 |
| Win10 21H1 | 0x19F | win10-21h1 |
| Win10 21H2 | 0x1A1 | win10-21h2 |
| Win10 22H2 | 0x1A1 | win10-22h2 |
| Win11 21H2 | 0x1AA | win11-21h2 |
| Win11 22H2 | 0x1AE | win11-22h2 |
| Win11 23H2 | 0x1AE | win11-23h2 |
| Win11 24H2 | 0x1B1 | win11-24h2 |
| Server 2016 | 0x18C | winserver-2016 |
| Server 2019 | 0x198 | winserver-2019 |
| Server 2022 | 0x1A7 | winserver-2022 |
| Server 2025 | 0x1B1 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 B1 01 00 00 mov eax, 0x1B1 F6 04 25 08 03 FE 7F 01 test byte ptr [0x7FFE0308], 1 75 03 jne short +3 0F 05 syscall C3 ret CD 2E int 2Eh C3 ret
Undokumentierte Hinweise
Das `WORKERFACTORYINFOCLASS`-Enum (definiert in phnt/ntexapi.h) wählt aus, welches Feld der zugrundeliegenden Kernel-Struktur `EWORKER_FACTORY` berührt wird. Die meisten Klassen — Thread-Min/Max, CPU-Sets, Timeout-Anpassungen — sind triviale Threadpool-Sizing-Knöpfe. Zwei sind interessant: `WorkerFactoryBasicInformation` legt die Felder `StartRoutine` und `StartParameter` offen (und kann sie per Set überschreiben), und `WorkerFactoryThreadFlags` kann Worker als langlebig oder kurzlebig kennzeichnen und damit ändern, wie aggressiv der Kernel sie einsammelt.
Häufige Malware-Nutzung
PoolParty 'Start Routine Overwrite'-Varianten teilen die Operation in zwei Schritte: zuerst NtCreateWorkerFactory mit einer harmlosen StartRoutine aufrufen (ntdll!TppWorkerThread ist die offensichtliche Wahl — die Factory wirkt in einem kurzen Snapshot identisch zu einer legitimen), dann NtSetInformationWorkerFactory mit `WorkerFactoryBasicInformation` aufrufen, um StartRoutine kurz vor dem Posten der Arbeit auf den Shellcode-Pointer zu überschreiben. Das Zweischritt-Muster schlägt einfache prozessübergreifende Detektionen aus, die StartRoutine nur zur Erzeugungszeit inspizieren. Derselbe Syscall dient dazu, Thread-Minima in manchen Sleep-Evasion-Gadgets auf null zu setzen, die den Threadpool nutzen, um das Leerlaufverhalten eines harmlosen Prozesses zu imitieren.
Erkennungsmöglichkeiten
WorkerFactoryBasicInformation-Writes sind in normalem Code selten — der ntdll-Threadpool setzt StartRoutine einmal bei Erzeugung und rührt sie nie wieder an. Ein Kernel-Callback, der `EWORKER_FACTORY.StartRoutine` vor und nach diesem Syscall vergleicht und jede Änderung des Feldes meldet, ist hochwertig. Prozessübergreifende Invokation verstärkt das Signal: legitimes Threadpool-Tuning ist immer intra-process. Microsoft-Windows-Threading ETW emittiert einige Klassen, aber nicht alle; verlässliche Abdeckung erfordert ObRegisterCallbacks auf dem WorkerFactory-Objekttyp oder einen Minifilter, der den Syscall im Kernel beobachtet.
Direkte Syscall-Beispiele
cPoolParty StartRoutine overwrite
// Step 2 of the 'overwrite' variant — flip the entry point to shellcode
// after the factory was created with a benign decoy routine.
typedef struct _WORKER_FACTORY_BASIC_INFORMATION {
LARGE_INTEGER Timeout;
LARGE_INTEGER RetryTimeout;
LARGE_INTEGER IdleTimeout;
BOOLEAN Paused;
BOOLEAN TimerSet;
BOOLEAN QueuedToExWorker;
BOOLEAN MayCreate;
BOOLEAN CreateInProgress;
BOOLEAN InsertedIntoQueue;
BOOLEAN Shutdown;
ULONG BindingCount;
ULONG ThreadMinimum;
ULONG ThreadMaximum;
ULONG PendingWorkerCount;
ULONG WaitingWorkerCount;
ULONG TotalWorkerCount;
ULONG ReleaseCount;
LONGLONG InfiniteWaitGoal;
PVOID StartRoutine;
PVOID StartParameter;
HANDLE ProcessId;
SIZE_T StackReserve;
SIZE_T StackCommit;
NTSTATUS LastThreadCreationStatus;
} WORKER_FACTORY_BASIC_INFORMATION;
WORKER_FACTORY_BASIC_INFORMATION info = {0};
NtQueryInformationWorkerFactory(hWf, WorkerFactoryBasicInformation,
&info, sizeof(info), NULL);
info.StartRoutine = pRemoteShellcode; // hijack
info.StartParameter = NULL;
NtSetInformationWorkerFactory(hWf, WorkerFactoryBasicInformation,
&info, sizeof(info));asmx64 direct stub (Win11 24H2 SSN 0x1B1)
NtSetInformationWorkerFactory PROC
mov r10, rcx
mov eax, 1B1h ; Win11 24H2 / Server 2025
syscall
ret
NtSetInformationWorkerFactory ENDPMITRE ATT&CK-Mappings
Last verified: 2026-05-20