How to disable kernel driver digital signature enforcement DSE without test mode?

June 7th, 2022

The implementation of a digital signature enforcement is abbreviated as DSE in kernel terminology. Most of the bypasses are based on exploiting a vulnerability in a legitimate EV signed driver to manually map a "driverless" non signed driver in kernel memory that patches kernel memory and disables digital signature enforcement.

The kernel driver has a direct access to the kernel memory and this technique is also commonly used to bypass kernel-level anti-cheat solutions.

The official way to turn DSE on and off:

  • Bcdedit.exe -set TESTSIGNING ON
  • Bcdedit.exe -set TESTSIGNING OFF

As of March 2022 Microsoft is adding a new vulnerable driver blocklist feature to Windows Defender that prevents those drivers from loading. MS is revoking leaked certs when found as well and distinguishes those updates as a "quality improvements" such as KB5013942. In the end, the public solutions that bypass DSE are becoming obsolete.

If you've no idea where to start. In order to disable DSE, you'll need to find a virtual address of CI!g_CiOptions in the kernel memory. This is a global system variable. The easiest way is to use the local kernel debugger as it comes with up to date symbols for the kernel itself and kernel "built-in" modules loaded by the kernel such as CI.dll in the article case.

CI!g_CiOptions

lkd> .symfix
lkd> .reload
lkd> db CI!g_CiOptions L1
lkd> FFFFF8067D1393B8 0F

The result is a virtual address of a global system variable CI!G_CiOptions in kernel memory (bolded above) and then the current value of DSE in hex.

Setting the value to zero will turn off DSE and restoring the value back to the original restores code integrity checks (CI).

The modification is subject to PatchGuard BSDO but if you restore the byte immediately back to the original value after loading an unsigned driver, as far as I've tested, in most of cases BSDO should not occur.

You can bypass DSE also using the local kernel debugger. However though enabling kernel debugging is not always an option.

lkd> ed CI!g_CiOptions 0 0

The screenshot below represents DATA/STRUCTURES mode in the HEX DEREF software and shows how the variable looks like in the professional version memory viewer:

DSE

The biggest difference vs WinDbg is that the software is capable of finding the structure of classes in memory without source code or symbols and the offsets are automatically applied to a given address. This functionality allows you to restructure undocumented windows kernel structures.

The tool can draw kernel memory in real time and of course you can edit arbitrary kernel memory as well. This will speed up dynamic kernel and malware analysis significantly.

How to find the virtual address of a DSE byte after a reboot?

The kernel uses address space layout randomization (KASLR). The kernel is loaded to a random location in memory on each reboot. You can bypass KASLR easily with a little bit of assembly knowledge. I'll update the article with a source code example on my GitHub.

Now that we know the virtual address of the DSE byte. There are four (3) options (knowledge of reverse engineering is required). For the sake of repetition, we will go through 1) and 2) in this article.

  • 1) Use HEX DEREF PRO to dynamically reverse engineer the instruction address that refers to the DSE byte in kernel memory (the easiest and fastest solution)
  • 2) Set a breakpoint (BP) to that address with the kernel debugger to find the instruction address
  • 3) Dump the kernel with HEX DEREF PRO and analyze the dumped ntoskrnl.exe in IDA or Ghidra and load pdb

#1

g_CiProtectedContent has a pointer to CI!g_CiOptions. After the initial analysis has finished in IDA PRO for CI.dll and the PDB has been loaded:

PAGE:FFFFF8067D144721 lea rcx, g_CiProtectedContent

Similarly to IDA PRO, the code needs to be analyzed in HEX DEREF PRO as well if you want to see XREF's in the memory viewer. The "X" refers to the code execution reference (XREF) in the memory viewer As shown in the image below. 0xFFFFF8067D12B8F0 is the virtual address of g_CiProtectedContent and it has a pointer to 0xFFFFF8067D1393B8 which is the virtual address of CI!g_CiOptions HEX DEREF PRO DATA MODE
You can generate an unique assembly signature for an instruction by right clicking the instruction address in the memory viewer. HEX DEREF PRO DISASSEMBLY MODE

The author of the article is a hobbyist security researcher and lead developer of the HEX DEREF software. The information is for educational and informational purposes only. The lab was performed on Windows 10 Pro 21H2 (19044) Hyper-V virtual machine.