Skip to content

Fix replay tool output buffer sizing and usage instructions - #8

Open
dajiaohuang wants to merge 1 commit into
0dayResearchLab:masterfrom
dajiaohuang:fix/replay-output-buffer-and-usage
Open

dajiaohuang wants to merge 1 commit into
0dayResearchLab:masterfrom
dajiaohuang:fix/replay-output-buffer-and-usage

Conversation

@dajiaohuang

Copy link
Copy Markdown

Trigger

make deploy -- --tags examples,examples-template-windows builds the Windows target
harness (kafl.targets/windows_x86_64/src/driver/vuln_test.c) with an output buffer of
0x10000 bytes (malloc(0x10000)), and every payload record stores the output length used
by the harness. Replaying such a record with the utility documented in section 7 of
docs/installation/README.md, where outbuffer_length is larger than 8 KiB.

Actual

replay.cpp allocates a fixed BUF_SIZE (0x2000) output buffer but passes the record's
outbuffer_length unmodified to DeviceIoControl as nOutBufferSize:

output = (char*)VirtualAlloc(NULL, BUF_SIZE, ...);
...
NTSTATUS res = DeviceIoControl(hDriver, ioctl_code, input, inbuffer_length, output, outbuffer_length, &byteRead, 0);

so the kernel writes up to outbuffer_length bytes into an 8 KiB allocation. Replaying a
16 KiB record makes the tool die with an access violation (0xC0000005).

Section 7 of the same guide also cannot be followed as written: replay.cpp uses
CreateFileW/DeviceIoControl, i.e. it is a Windows binary, but the instructions use a
placeholder [you compiler] command and then ./replay on the Linux host, and reference an
undefined $kAFL variable (the deployed env.sh only exports KAFL_ROOT).

Expected

Replay any payload produced by the harness (output buffers up to 0x10000) without memory
corruption, and documented build/run steps that work on the supported Ubuntu host plus the
Windows guest.

Change

  • Size the output buffer from the record's outbuffer_length, growing it only when a larger
    record is replayed, and zero the allocated region before each IOCTL.
  • Rewrite the replay section: cross-compile with MinGW-w64 and run the resulting executable
    inside the Windows guest; use ~/kAFL (the clone location from section 2) instead of the
    undefined $kAFL.

Validation

  • MSVC /W4 /std:c++17 build of the changed replay.cpp: clean.
  • Local fixture on the host (no kernel driver): a link-time stand-in for DeviceIoControl
    that follows the documented contract (kernel may write up to nOutBufferSize bytes),
    plus synthetic multi-record payload files:
    • before: 8 KiB record OK; 16 KiB record -> 0xC0000005; 4 KiB -> 32 KiB records -> 0xC0000005
    • after: 8 KiB, 16 KiB, 64 KiB (0x10000, the harness maximum) and mixed-size records all OK
  • Not run: full msFuzz/kAFL deployment, a real kernel-driver replay (requires Intel PT
    hardware, the patched kAFL kernel and a Windows guest), and the MinGW cross-build itself
    (the file was compiled with MSVC here; no MinGW toolchain available in this environment).

replay.cpp allocated a fixed 0x2000 byte output buffer, but each payload
record's outbuffer_length is passed unmodified to DeviceIoControl as
nOutBufferSize. The target harness (kafl.targets windows_x86_64) uses a
0x10000 byte output buffer, so replaying a record produced for an IOCTL
that returns more than 8 KiB makes the kernel write past the replay
buffer.

Size the output buffer from the record's outbuffer_length instead,
growing it only when a larger record is replayed, and zero the allocated
region before each IOCTL.

The documented build/run steps could not work either: replay.cpp uses
CreateFileW/DeviceIoControl, i.e. it is a Windows binary, yet the guide
compiled it with a placeholder command and ran ./replay on the Linux
host, and referenced an undefined $kAFL variable. Build it with the
MinGW-w64 C++ cross-compiler and run it inside the Windows guest.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant