NtWorkerFactoryWorkerReady
Indica al kernel que un worker de threadpool está listo para recibir trabajo — parte del handshake interno ntdll!TppWorkerThread.
Prototipo
NTSTATUS NtWorkerFactoryWorkerReady( HANDLE WorkerFactoryHandle );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| WorkerFactoryHandle | HANDLE | in | Handle a la worker factory a la que pertenece este hilo de trabajo. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0x1 | win10-1507 |
| Win10 1607 | 0x1 | win10-1607 |
| Win10 1703 | 0x1 | win10-1703 |
| Win10 1709 | 0x1 | win10-1709 |
| Win10 1803 | 0x1 | win10-1803 |
| Win10 1809 | 0x1 | win10-1809 |
| Win10 1903 | 0x1 | win10-1903 |
| Win10 1909 | 0x1 | win10-1909 |
| Win10 2004 | 0x1 | win10-2004 |
| Win10 20H2 | 0x1 | win10-20h2 |
| Win10 21H1 | 0x1 | win10-21h1 |
| Win10 21H2 | 0x1 | win10-21h2 |
| Win10 22H2 | 0x1 | win10-22h2 |
| Win11 21H2 | 0x1 | win11-21h2 |
| Win11 22H2 | 0x1 | win11-22h2 |
| Win11 23H2 | 0x1 | win11-23h2 |
| Win11 24H2 | 0x1 | win11-24h2 |
| Server 2016 | 0x1 | winserver-2016 |
| Server 2019 | 0x1 | winserver-2019 |
| Server 2022 | 0x1 | winserver-2022 |
| Server 2025 | 0x1 | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 01 00 00 00 mov eax, 0x1 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
Notas no documentadas
El número de syscall más estable de toda la tabla — `0x1` desde Windows 7 en adelante. Lo invoca exclusivamente `ntdll!TppWorkerThread` (la StartRoutine canónica de cualquier worker factory) y le dice al kernel: 'este worker terminó su despacho anterior, decrementa mi contador de pendientes, vuelvo a NtWaitForWorkViaWorkerFactory'. La contabilidad que realiza es lo que permite al kernel decidir si generar más workers, retirar inactivos o mantener el conteo plano.
Uso común por malware
Casi nunca lo invoca directamente el malware — es parte de la contabilidad interna del threadpool y solo tiene sentido en el contexto de un bucle real `TppWorkerThread`. La excepción son las variantes de PoolParty donde el shellcode mismo emula el handshake del worker para mantener la contabilidad del threadpool coherente (y por tanto el proceso padre receptivo) tras secuestrar un worker. Saltarse el ciclo ready/wait/release hace que el `PendingWorkerCount` del kernel se desvíe, lo que puede ahogar al resto del threadpool de la víctima — observable como una aplicación colgada.
Oportunidades de detección
Efectivamente indetectable de forma aislada — cada proceso de Windows con CRT, runtime .NET o apartment COM emite miles por segundo. La detección solo es posible cuando *falta*: una worker factory cuyo contador ready nunca se incrementa mientras su puerto de finalización se drena indica que algo está esquivando el handshake (un shellcode PoolParty que olvidó emular el bucle, o un depurador reteniendo un worker). Es una heurística, no una señal primaria.
Ejemplos de syscalls directos
cSkeleton of ntdll!TppWorkerThread
// Approximate reverse of the user-mode loop driven by NtCreateWorkerFactory.
// Do NOT call directly — this is what TppWorkerThread does on every worker.
VOID WINAPI TppWorkerThreadLike(PVOID context) {
HANDLE hWf = ((PTHREADPOOL_INTERNAL)context)->WorkerFactoryHandle;
for (;;) {
FILE_IO_COMPLETION_INFORMATION info;
NTSTATUS s = NtWaitForWorkViaWorkerFactory(hWf, &info);
if (!NT_SUCCESS(s)) break;
// Dispatch the callback that info.KeyContext encodes.
DispatchCallback(&info);
// Tell the kernel we're done and ready for the next item.
NtWorkerFactoryWorkerReady(hWf);
}
}asmx64 direct stub (SSN 0x1)
; Stable across every Windows 10/11 build.
NtWorkerFactoryWorkerReady PROC
mov r10, rcx
mov eax, 1
syscall
ret
NtWorkerFactoryWorkerReady ENDPMapeos MITRE ATT&CK
Last verified: 2026-05-20