Recently came across with interesting blogs from RedDrip and Fortra which talks about dwmcore.dll
vulnerability (CVE-2024-30051). This vulnerability is interesting when it comes to debug the vulnerable function. Since the vulnerable function is in user-mode and it can’t debug directly on the machine itself as debugging dwm.exe
(The process that loads dwmcore.dll
) directly will cause graphic freeze on the machine.
In order to debug the dwm.exe
or dwmcore.dll
without any issue, remote debugging can be useful over here. You may think why not just using kernel mode? I had tried this, and it doesn’t always or never hit the breakpoint on the user-mode code which makes debugging process difficult in this case.
After some Google-fu, found this blog from TimDbg which give tutorial on setting up remote debugging 🐞 by using Microsoft NT Symbolic Debugger (NTSD)
or DbgSrv
on the machine where we want to debug. This is very useful in my use case.
Environment Setup
Debuggee machine (Windows 10 VM)
This is the host machine that you want to debug.
I’m using NTSD
in this case, you can get it by:
- Install Visual Studio
- Install Windows Driver Kit
After that, you have to enable kernel mode debugging in the debuggee machine.
> bcdedit /debug on
> bcdedit /set TESTSIGNING ON
> shutdown /r /t 0
Debugger machine (Windows 10 Host)
This is the client machine you want to debug from.
- Install Windbg Preview from here.
Initiating Debugging Session
Debuggee machine
Get the kernel debug key with the command below.
> bcdedit /dbgsettings NET HOSTIP:<YOUR_INTERFACE_IP_FROM_WINDBG_MACHINE> PORT:<YOUR_PORT>
I would prefer to put IP in Ethernet adapter VMware Network Adapter (Found in ipconfig) as INTERFACE_IP as this is the local connection between debugger and debugee host.
The key value is after the Key=
(It ends with iv8 for my case)
Execute ntsd
to pass the control of the debugger to the kernel debugger (Windbg). For further information on the command switch used, please read the doc here. The machine’s graphic will freeze after ntsd
attached to the dwm.exe
> ntsd -d -p <pid_of_dwm>
Remember set the
ntsd
into global path viaenvironment settings
Debugger machine
Launch Windbg, go to File > Start debugging > Attach to kernel. Copy the key value get from the debuggee machine and paste it into Key textbox in Windbg.
If there is no issue, you should see the Input>
prompt from Windbg instead of kd>
.
From here you can start placing breakpoint on the user-mode process being debugged (In this case is dwm.exe and its relevant modules loaded)
For example:
Input> bp dwmcore!CCommandBuffer::Initialize+0x96 ".if(@r8==0x35f) {.echo hit} .else {gc;}"
The .if(@r8==0x35f) {.echo hit} .else {gc;}
is the conditional breakpoint for Windbg which you can try to play around with it ✌ as this is important when debugging the system code to ensure the breakpoint hits when it meets certain requirements. If not, you have to keep pressing g
forever 😴
You can type .breakin
or g
in the prompt to switch back to kernel debug mode. From there the graphic on debuggee machine will stop freezing and proceed to execute the exploit store in the debuggee machine. The execution of the exploit will hit the breakpoint set in the user-mode code.
Once hitting the breakpoint of the user-mode code, you will get back to the Input>
prompt. Then, continue debug the user-mode code from there. Since in this mode, step in (t) or step out (p) or go (g) can’t execute from Windbg GUI button. Have to do these actions via the Input>
prompt.
I hope this is helpful to anyone who wanted to try analyzing this dwmcore
vulnerability as I’m struggling to debug the user-mode module for a long time 🥲
References
Debugging Tools for Windows — Windows drivers | Microsoft Learn
Switching Modes — Windows drivers | Microsoft Learn
Windows Debuggers: Part 1: A WinDbg Tutorial — CodeProject
Process Hacker: _RTL_USER_PROCESS_PARAMETERS Struct Reference (sourceforge.io)
Making NtCreateUserProcess Work — Hack.Learn.Share (captmeelo.com)