WinDbg Patching Arguments at Runtime

When a function is about to receive a bad argument (e.g. NULL filename passed to __loaddll), you can fix the pointer value on the stack before the call executes.

Quick command reference

Goal Command
Search for an existing ASCII string s -a 0 L?80000000 "string"
Search for an existing Unicode string s -u 0 L?80000000 "string"
Allocate fresh memory in the target .dvalloc 100
Write ASCII string to memory eza <addr> "\\.\vwin32"
Write Unicode string to memory ezu <addr> "path"
Write a dword (e.g. argument pointer) ed <addr> <value>
Read string at a pointer da poi(esp)

Typical workflow

  1. Stop right before the call, so esp points at the argument slot (after push).
  2. Find or create the replacement string:
    windbg s -a 0 L?80000000 "\\.\vwin32"
    If not found, allocate memory:
    windbg .dvalloc 100 eza <allocated_addr> "\\.\vwin32"
  3. Patch the argument on the stack:
    windbg ed esp <string_addr>
  4. Verify:
    windbg dd esp L2 da poi(esp)
  5. Continue execution with g.

Notes

  • eip must still be at the call instruction when you patch esp, otherwise you may overwrite the wrong thing.
  • For 64-bit code, arguments are usually in registers (rcx, rdx, r8, r9) first; use r rcx=<addr> rather than stack editing.
  • .dvalloc memory is readable and writable in the target process for the rest of the debug session.