NtCreateJobObject
Crea un job object — el contenedor de kernel usado para aplicar límites, contabilidad y política de terminación a un conjunto de procesos.
Prototipo
NTSTATUS NtCreateJobObject( PHANDLE JobHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| JobHandle | PHANDLE | out | Recibe el handle del job object recién creado si tiene éxito. |
| DesiredAccess | ACCESS_MASK | in | Derechos de acceso para el handle devuelto, normalmente JOB_OBJECT_ALL_ACCESS para los propietarios. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Nombre y atributos opcionales; NULL crea un job anónimo (lo más común para sandboxing). |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0xA1 | win10-1507 |
| Win10 1607 | 0xA3 | win10-1607 |
| Win10 1703 | 0xA6 | win10-1703 |
| Win10 1709 | 0xA7 | win10-1709 |
| Win10 1803 | 0xA8 | win10-1803 |
| Win10 1809 | 0xA8 | win10-1809 |
| Win10 1903 | 0xA9 | win10-1903 |
| Win10 1909 | 0xA9 | win10-1909 |
| Win10 2004 | 0xAD | win10-2004 |
| Win10 20H2 | 0xAD | win10-20h2 |
| Win10 21H1 | 0xAD | win10-21h1 |
| Win10 21H2 | 0xAE | win10-21h2 |
| Win10 22H2 | 0xAE | win10-22h2 |
| Win11 21H2 | 0xB1 | win11-21h2 |
| Win11 22H2 | 0xB2 | win11-22h2 |
| Win11 23H2 | 0xB2 | win11-23h2 |
| Win11 24H2 | 0xB4 | win11-24h2 |
| Server 2016 | 0xA3 | winserver-2016 |
| Server 2019 | 0xA8 | winserver-2019 |
| Server 2022 | 0xB0 | winserver-2022 |
| Server 2025 | 0xB4 | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 B4 00 00 00 mov eax, 0xB4 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
NtCreateJobObject asigna una estructura de kernel `_EJOB` y devuelve un handle. Por sí sola no hace nada observable: el objeto cobra sentido cuando se le asignan procesos vía NtAssignProcessToJobObject y se aplica política mediante NtSetInformationJobObject. Los job objects sustentan el sandboxing en Windows — los renderers de Chromium / Edge, AppContainer / Windows Sandbox y la gestión moderna de procesos hijo en Win32 se apoyan en jobs. Los jobs anidados (Win8+) permiten apilar políticas sin romper asignaciones previas. La SSN cambia cada par de actualizaciones mayores.
Uso común por malware
Casi totalmente benigno. El patrón ofensivo interesante es el inverso — *escapar* de un job mediante PROCESS_CREATE_FLAGS_BREAKAWAY_FROM_JOB al spawnear un hijo (cuando el job lo permite) o terminando el proceso controlador para que se dispare la política JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE y borre evidencias. Un puñado de herramientas red-team crean su propio job para aplicar JobObjectExtendedLimitInformation con JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE a un stager que se autodestruye si el implante muere. Señal ofensiva débil — honestamente, los jobs están en todas partes de un sistema sano.
Oportunidades de detección
Sysmon hoy no tiene un evento dedicado a job objects. La telemetría útil viene de ETW Microsoft-Windows-Kernel-Process (los registros de inicio de proceso exponen el ID del job vía TokenInformation) y de hooks EDR sobre ntdll!NtCreateJobObject combinados con ntdll!NtAssignProcessToJobObject. El ángulo blue-team no es «quién creó un job» (todos lo hacen) sino «quién creó un job que incluye un proceso que no lanzó» — síntoma de intento de contención o control de terminación. Emparejar con NtSetInformationJobObject(JobObjectExtendedLimitInformation) para señalar KILL_ON_JOB_CLOSE en jobs inusuales.
Ejemplos de syscalls directos
asmx64 direct stub (Win11 24H2 SSN)
; Direct syscall stub for NtCreateJobObject (SSN 0xB4 on Win11 24H2 / Server 2025)
NtCreateJobObject PROC
mov r10, rcx ; syscall convention
mov eax, 0B4h ; SSN for win11-24h2
syscall
ret
NtCreateJobObject ENDPcSandbox-spawn skeleton (step 1 — create the job)
// First step of a sandboxed child-process pattern.
// Pair with NtAssignProcessToJobObject + NtSetInformationJobObject to fully wire it up.
HANDLE hJob = NULL;
NTSTATUS s = NtCreateJobObject(&hJob,
JOB_OBJECT_ALL_ACCESS,
NULL); // anonymous, unnamed
if (!NT_SUCCESS(s)) return s;
// At this point hJob is empty; nothing happens to any process until
// NtAssignProcessToJobObject(hJob, hChild) is called.rustwindows-sys + naked syscall stub
// Cargo: windows-sys = "0.59" (Win32_System_JobObjects)
use std::arch::asm;
#[unsafe(naked)]
unsafe extern "system" fn nt_create_job_object_stub() {
asm!(
"mov r10, rcx",
"mov eax, 0xB4", // Win11 24H2; resolve dynamically for other builds
"syscall",
"ret",
options(noreturn),
);
}Mapeos MITRE ATT&CK
Last verified: 2026-05-20