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
- Stop right before the call, so
esppoints at the argument slot (afterpush). - 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" - Patch the argument on the stack:
windbg ed esp <string_addr> - Verify:
windbg dd esp L2 da poi(esp) - Continue execution with
g.
Notes
eipmust still be at thecallinstruction when you patchesp, otherwise you may overwrite the wrong thing.- For 64-bit code, arguments are usually in registers (
rcx,rdx,r8,r9) first; user rcx=<addr>rather than stack editing. .dvallocmemory is readable and writable in the target process for the rest of the debug session.