VoidSec / DriverBuddyReloaded

Driver Buddy Reloaded is an IDA Pro Python plugin that helps automate some tedious Windows Kernel Drivers reverse engineering tasks
https://voidsec.com/driver-buddy-reloaded
GNU General Public License v3.0
313 stars 46 forks source link

[BUG] IOCTLs with less than 10 decimal digits aren't found #15

Closed eranzim closed 2 years ago

eranzim commented 2 years ago

Describe the bug Any IOCTL with a code that has less than 10 decimal digits (e.g. 0x222003) won't be found by the current code.

Expected behavior All IOCTLs should be found

Desktop (please complete the following information):

VoidSec commented 2 years ago

Thank you for the report. The checks implemented in:

are present in order to significantly lower the false positives; at the moment the script is trying to decode IOCTLs only if an immediate value, with at least 10 digits, is found in a possible DispatchDeviceControl routine and the value does not belong to a known NTSTATUS.

While it's true for most of the IOCTL values I've encountered to be in a format like 9C4060D4h = 2621464788dec (10 digits), there are also valid IOCTL codes as 0x222004h = 2236420dec (7 digits).

Unfortunately, that's a silly problem as I was not able to find any convention/definition on Windows that states what is their minimum/maximum possible value they can have nor their minimum digits. AFAIK even 0x1 will be a valid IOCTL and will be decoded successfully: image

I can think of removing/limiting the safeguard to exclude unprobable IOCTL code (e.g. 1/2 digits only) in the next release thus resulting in much higher false-positive rates

eranzim commented 2 years ago

I'm not sure 0 is a legal device number... I mean generally you can probably do anything you want, but maybe you won't get as much 0s... Looks like 0x10000 (== 65536) might be a good minimal value. Instead of number of digits, you could check 0x10000 <= value... Might be able to also limit value from above. According to this: https://github.com/h0mbre/ioctl.py/blob/master/ioctl.py , maximal device type is 0xf60 (though I don't know what is that repo based on)

VoidSec commented 2 years ago

Umh, as per Microsoft guidelines:

DeviceType: Values of less than 0x8000 are reserved for Microsoft. Values of 0x8000 and higher can be used by vendors.

Unfortunately 0x10000 is a valid IOCTL and cannot be used to tell them apart: image

I spoke with @HackSysTeam as well as other kernel driver hackers and we didn't come up with any good way of finding IOTCL ranges; I'll keep trying and let you know the result :)

eranzim commented 2 years ago

So maybe only check minimal value, i.e. anything greater than 0x10000 is valid? Maybe we can also check that the Access and Method values give valid enum values (I didn't check their width), but I think just starting with 0x10000 <= value is a good enough check for now (and an improvement to the current one).

VoidSec commented 2 years ago

At the moment it has been partially fixed in https://github.com/VoidSec/DriverBuddyReloaded/commit/96be3fa7ba870466dcea9371916a8709bd15e0d7, It now includes all the IOCTL values with more than 2 digits. It will have a bit more false positives but hopefully nothing that will break

eranzim commented 2 years ago

Why do you even need to calculate digits? Why not change the check to if value >= 0x10000 and value not in NTSTATUS.ntstatus_values:?

VoidSec commented 2 years ago

You're right. I've just realized that you were using the value of 0x10000 as anything below will result in 0 as a device number. Theoretically, 0 is an unknown device but I'll agree with you that using 0x10000 won't result in many false positives. I'll make a new commit to reflect those changes.