IntelLabs / IntelLabs/kAFL

Possible Thread Starvation Issue in QEMU-NYX DWM Fuzzing

Open
#326 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Makefile
Stars
814
Forks
109
PR merge metrics
No merged PRs in 30d

Description

Hello,

We are currently fuzzing a specific function within `dwm.exe`(dwmcore.dll), using a harness implemented as a DLL that is injected into the target process.

**Our fuzzing architecture is as follows:**

1. A new thread (hereafter referred to as Thread 1) is created inside `dwm.exe`, and our harness DLL is loaded within it.
2. The harness installs a trampoline hook at the return address of a specific handler function in `dwmcore.dll` (hereafter referred to as Function A).
- This trampoline is designed to invoke a `Release_Hypercall` instead of returning normally from Function A.
- The goal is to allow A function to fully process the fuzzed input, then trigger a snapshot restoration via hypercall, enabling the next fuzzing iteration.
3. The harness then issues a specific NT syscall, which queues a message for DWM’s internal message handling thread (hereafter referred to as Thread 2).
4. Thread 2 processes the queued message by calling Function A.
5. Upon completing Function A, the trampoline triggers the `Release Hypercall`, restoring the VM snapshot and continuing the fuzzing loop.

---

**Current Issue:**

- The NT syscall initiated by our harness (Thread 1) is successfully executed.
- However, Thread 2(Original Dwm handling Thread) does not appear to invoke Function A, meaning the trampoline is never reached.
- As a result, the `Release Hypercall` is never triggered, and QEMU remains stuck in a halted state. (We’ve set the timeout to 255 seconds, but the issue persists.)

---

**We are currently considering two possible causes:**

**1. QEMU-NYX is configured to run with a single core and single thread, which may cause Thread 1 (our harness) to monopolize CPU time, preventing Thread 2 from running.**

- To address this, we attempted to yield execution using `SwitchToThread()` and similar mechanisms, but this did not resolve the issue.

**2. The submitted IP range for coverage feedback is limited to userland (`dwm.exe`, `dwmcore.dll`), and execution transitions into kernel space (`win32k.sys`) during the input processing path.**

- Specifically, the call path goes from userland (harness) → kernel (`win32k.sys`) → back to userland (`dwmcore.dll`), and we suspect that QEMU-NYX halts execution when it encounters instructions outside the submitted IP range.
- However, since we are not fully familiar with the internals of QEMU-NYX, this remains a hypothesis.

---

**Additional Observations:**

- DWM does not load unless the `vga std` option is passed to QEMU, so we included this to ensure proper rendering device initialization.
- We also enabled `display vnc=:1` to observe the fuzzing state via VNC. After our harness is injected and the initial hypercall is issued, the screen appears frozen.
- This could indicate that either DWM, QEMU, or the VNC server has stalled.

---

Has anyone experienced similar issues, or do you have any insights into what might be going wrong in this setup?

We’ve attached our harness (DLL) source code below for reference.

**P.S.** In the latest version of Windows 11, QEMU-NYX crashes after reaching "Getting devices ready... 100%". We are currently using Windows 11 23H2 (older release) for stability.

[harness.zip](https://github.com/user-attachments/files/19678150/harness.zip)

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.