KDU stands for Kernel Driver Utility. It was developed mainly to assist in some other projects, like for example VBoxHardenedLoader. Since release in the beginning of 2020 it supported various vulnerable drivers as "functionality providers".
Overall these are the major 1.1 version changes:
- Driver mapping shellcode has been updated, two additional shellcode variants have been added;
- More vulnerable drivers from Huawei, Realtek, MSI, LG, ASUSTeK have been added.
Details about changes are below.
Shellcode variants
Overall shellcode has been redesigned to work with mapped section instead of registry. Previous version read payload driver image from Windows registry specific key. It was quick and cheap solution as I didn't bother with it and just re-used Stryker bootstrap shellcode variant. Now KDU will allocate special section with random name to store payload driver image, additional parameters and to query result uppon shellcode execution completion.
There are three variants of driver mapping shellcode available for selection via -scv <number> command. The difference between them is how they handle payload execution part. First variant uses newly created system thread to run payload entry point. It is pretty much the same method as original KDU/TDL/Stryker use. Second allocates work item and runs payload entry point within existing system worker thread. Third is more complex as it is designed for a small limited usage with drivers that are unaware of preconditions required for manual mapping. Preciously they require their DriverEntry parameters to be valid. This shellcode variant will allocate driver object, fill it common part and pass it together with supplied registry path to the payload DriverEntry as parameters. This is something like Dustman copy-pasters did with Eldos RawDisk however it also provides valid registry path parameter which is can be used by payload driver. While using 3rd shellcode version you need to supply driver object name using command -drvn <ObjectName> and optionally registry key name -drvr <RegName>. If no registry key name specified KDU will assume registry key name is the same as driver object name. Examples of usage -> https://github.com/hfiref0x/KDU#usage.
New providers
- Huawei PhyMemx64 driver from Huawei MateBook Manager of various versions. This driver is a blatant copy-paste from infamous WINIO source code;
- Realtek RtkIo64 driver from Realtek Dash Client Utility of various versions. This driver based on PHYMEM open-source project code, which is a wormhole by design;
- EneTechIo64 from MSI Dragon Center, it is similar to previously added EneTech variants (all based on WINIO), however it utilizes "unique" unlocking algorithm (see https://swapcontext.blogspot.com/2020/08/ene-technology-inc-vulnerable-drivers.html for a complete overview) and freshly signed so that is why I decided to add this variant too;
- LG LHA driver from LG Device Manager, which is explained in Jackson_T blogpost. This driver is semi-original with some influence of open-source projects;
- ASUSTeK AsIO2 driver from ASUS GPU Tweak utility, this driver also described in my blogpost about EneTech drivers derivatives.
Bonus (AsIO3.sys unlock)
ASUSTeK "giveio" drivers seems had some special love from the developers who are sitting on WINIO source code in EneTech. GLCKIO, GLCKIO2, AsIO, AsIo<O><variousnames>, AsIO2 and now AsIO3. What they share in common (except WINIO base) - their authors never fix their bugs. They actually just pull "new" version of driver when someone find a bug in it and contact ASUS for security reasons. Numerous CVE numbers generated by various groups/researches etc. So what they actually changing? Well, they just switching driver "locks" - a primitive handmade solutions which purpose is to block usage of the given driver by 3rd party. And under 3rd party I mean - block and/or ruin the way this driver was exploited in the submitted security issue. Thus submitted issue will be no longer reproducible as-is and they can tell - hey we fixed it, now you can gtfo, lol. Sometimes, like in case of AsIO2 their newly added locking code adds additional bugs and vulnerabilities. But nobody cares I guess.
Their latest release is AsIO3.sys with self-explaining pdb (C:\Working\MB\GLCKIO2\AsIO3\x64\Release\AsIO3_64.pdb). The key changes compared to AsIO2:
- They have been forced to make it pass Driver Verifier checks; 👏
- New driver lock, no more TinyAES with keys found by devs in Google search;
- All the bugs/vulnerabilities of WINIO stay same.
Driver is fresh and comes as part of ASUS GPU Tweak software v2303.
Pic 1. AsIO3 details. |
New driver "lock" looks pretty damn solid and complicated! I mean they wasted so much code to create this ineffective piece of garbage while instead they could put their efforts into fixing (or even rewriting) entire WINIO. To "unlock" previous AsIO2 all you need - generate special resource named "asuscert" and put it into your application resources, see complete unlocking code here. In newest versions everything changed.
AsIO contain three components - AsusCertService.exe (32bit), wrapper dll and driver. In the AsIO3 driver implemented special check of requestor application during IRP_MJ_CREATE. Driver reads file from disk, calculates SHA256 for it and compares this value with hardcoded hash. If they do not match - STATUS_ACCESS_DENIED will be returned to the caller.
Pic 2. AsusCertService.exe SHA256 hardcoded in AsIO3 driver |
Thus initially only AsusCertService.exe allowed to open and communicate with AsIO3 driver. Entire purpose of this executable is to manage connections for AsIO3 driver. This driver also provides a way to register "trusted application" that will be able to call AsIO3. AsusCertService setups named pipe (no SD set ROFL) called "asuscert". Now if another application want to use AsIO3 and should contact AsusCertService via named pipe. AsusCertService will validate client executable to be digitally signed and signer must be one of the hardcoded values as shown below.
Pic 3. AsusCertService client signer check. |
After successful check service will register client process as trusted for AsIO3 driver by sending special IOCTL 0xA040A490 with input buffer set to client process id. Driver manage this list similar to GLCKIO2 where it was firstly introduced. Another IOCTL 0xA040A494 used to remove client process id from trusted process list.
How to bypass this garbage and completely useless code and unlock this driver for your application:
- Make a copy of AsusCertService somewhere, make sure it is unmodified otherwise driver side hash check will fail;
- Create a zombie process from this copy, stop before calling entrypoint;
- Unmap original code and replace it with your own shellcode;
- Resume zombie process;
- In a shellcode -> open driver and register your parent process in trusted process list using 0xA040A490 IOCTL code;
- Make sure AsusCertService zombie process will be alive and kicking (put it into infinite wait for example in your shellcode) while your main process is working, this is to prevent AsIO3 driver from zeroing trusted processes list;
- Now from your process you can do whatever you want with AsIO3, for example BSOD it (since AsIO3 provides full set of unfixed WINIO vulnerabilities/bugs).
Pic 4. AsIO3 usual state. |
Well, what can I say. A quantum supercomputer calculating for a thousand years could not even approach the number of fucks which ASUS do not give when it comes to security of their drivers.
AsIO3 unlock PoC can be found at -> https://github.com/hfiref0x/AsIo3Unlock
Disclaimer
Using KDU program might crash your computer with BSOD. Compiled binary
and source code provided AS-IS in hope it will be useful BUT WITHOUT
WARRANTY OF ANY KIND. Since KDU rely on completely bugged and vulnerable drivers security of computer where it executed maybe put at risk. Make sure you understand what you do.
KDU github with precompiled binaries -> https://github.com/hfiref0x/KDU