← Back to list

Reverse Engineering a 0day used Against CrowdStrike EDR

Hello again…

Jehad Abudagga · 2026-04-05 08:58 · 68 claps · 3.8 min read
#byovd #edr #red-teaming #reverse-engineering #apt
Open on Medium ↗
Wiki topics: SAF · Safety & Alignment

Reverse Engineering a 0day used Against CrowdStrike EDR

Hello again…

I've been reversing kernel drivers for over a year now and last week i came across several interesting Kernel drivers that have been used in BYOVD attacks against several EDRs including the well known CrowdStrike EDR

I decided to make a blog about it and publish the POC and drivers for everyone.

Lets start.

In this picture we can see the driver and its variants (15+ variants) all have the same code inside.

Identified Drivers

Identified Drivers

All the Drivers are signed by Microsoft and have valid signatures and not blocked or revoked by anyone.

Drivers signed by Microsoft

Drivers signed by Microsoft

When opening one of the drivers in virus total we can see that its not detected by any AV or EDR vendor.

link: https://www.virustotal.com/gui/file/6fbaad2f00afaa94723fa7d5bd46e7ea4babb7ce478a8e7229ce7bd4b85e0f51/detection

Virus total scan of one of the drivers

Virus total scan of one of the drivers

Reverse Engineering

Now for the reverse engineering part, i opened Ida pro and loaded the driver in it, Ida pro was not able to decompile the main function (DriverEntry) in the driver.

This is a known IDA issue with drivers that use non-standard stack frames or that have had their entry point obfuscated. Rather than fight it, I skipped DriverEntry and went straight for the dispatch handler which is where the interesting logic lives anyway.

Decompilation failure in DriverEntry

Decompilation failure in DriverEntry

The DeviceIoControlHandler function was decompiled but looked terrible, raw offsets for CurrentStackLocation fields, unnamed sub-functions, meaningless variable names.

DeviceIoControlHandler before fixing.

DeviceIoControlHandler before fixing.

After fixing the types and names:

DeviceIoControlHandler after fixing.

DeviceIoControlHandler after fixing.

We can see 2 IOCTL’s, the first i was too lazy to reverse but the second one (0x22E010) is leading to a function responsible for process killing i named procKiller.

When opening the procKiller decompilation code still it looks ugly and garbage, i had to fix it like i did before.

procKiller function before fixing

procKiller function before fixing

procKiller function after fixing

procKiller function after fixing

The procKiller function flow is as following:

  1. The IOCTL input buffer is treated as a null-terminated ASCII string containing the decimal PID.

  2. The driver calls atoi() on it, passes the integer to TerminateProcess.

  3. Writes "ok" back to the output buffer on success. That's the entire interface.

Inside the TerminateProcess is the true flow of killing the process:

TerminateProcess function

TerminateProcess function

the TerminateProcess takes the PID and opens the process using ZwOpenProcess function to obtain a handle, then a call to ZwTerminateProcess using the obtained process handle.

This is why CrowdStrike (and other EDRs running as PPL) can be killed. In user mode, OpenProcess against a PPL process returns Access Denied. But from the kernel, ZwOpenProcess doesn’t care.

Now that we have reversed the killing part and identified the IOCTL responsable for process killing, we still miss one critical piece which is the driver’s symblolic link , without it we cant send process termination requests from usermode.

For the symbolic link hunting i decided to go for the dynamic approach which is loading the driver and seeing if any new symlinks pop up in WinObj and we were able to find the driver symbolic link:

Driver Symlink

Driver Symlink

Now we have all the pieces:

Driver symlink: \.{F8284233–48F4–4680-ADDD-F8284233}

Kill Process IOCTL : 0x22E010

Creating the POC

First i added all driver symlink and the ioctl as variables:

in the main function the flow is the following:

  1. Opens \.{F8284233–48F4–4680-ADDD-F8284233} via CreateFileW.
  2. Converts the PID to a decimal ASCII string.
  3. Sends it via DeviceIoControl with IOCTL 0x22E010.
  4. Process Terminated !!!

main function part 1

main function part 1

main function part 2

main function part 2

Now its time to test the POC against CrowdStrike:

First we load the driver using OSRLOADER.

you can also load the driver using sc.exe:

sc.exe create PoisonX binPath="C:\Path\to\Driver.sys" type=kernel
sc.exe start PoisonX

Loading the driver using OSRLOADER

Loading the driver using OSRLOADER

Then we run the POC against crowdstrike.

Before running the POC

Before running the POC

After running POC

After running POC

For the POC and the drivers, i just published them on GitHub. https://github.com/j3h4ck/PoisonKiller/


메타데이터
post_id
a5ea1fbe3fd4
slug
reverse-engineering-a-0day-used-against-crowdstrike-edr-a5ea1fbe3fd4
url
https://medium.com/@jehadbudagga/reverse-engineering-a-0day-used-against-crowdstrike-edr-a5ea1fbe3fd4
canonical_url
https://medium.com/@jehadbudagga/reverse-engineering-a-0day-used-against-crowdstrike-edr-a5ea1fbe3fd4
author_url
https://medium.com/@jehadbudagga
status
ok
fetched_at
2026-06-23 03:48:11