Memory and disassembly

!address

Show the module and section, or the VAD region, that an address belongs to.

!address <address>
!address [-summary] [address]

Also: address

On a user-mode minidump the command uses the regions that the dump’s memory-info list records. Without an argument, it lists them with their state, protection, type, allocation base, usage, and how much of each the dump captured, followed by a summary by usage, type, state, and protection; -summary shows only the summary. With an address, it shows the region that holds it. Usage comes from the dump’s modules, its threads’ stacks and TEBs, the PEB, and the heaps that !heap lists, with all of their segments and large blocks; it is for any other region. A dump without a memory-info list shows the memory ranges it captured instead.

!db

Show guest-physical memory as bytes.

!db <address> [L<count>|length|end]
!dd

Show guest-physical memory as doublewords.

!dd <address> [L<count>|length|end]
!dq

Show guest-physical memory as quadwords.

!dq <address> [L<count>|length|end]
!dw

Show guest-physical memory as words.

!dw <address> [L<count>|length|end]
!eb

Write one or more bytes to guest-physical memory.

!eb <address> <value>...
!ed

Write one or more doublewords to guest-physical memory.

!ed <address> <value>...
!eq

Write one or more quadwords to guest-physical memory.

!eq <address> <value>...

Search guest-physical memory for a pointer-sized value.

!search <value> [delta [start-pfn [end-pfn]]]

The command compares each pointer-aligned quadword in the PFN range, which is all RAM by default. With no delta, it lists a quadword if it equals the value or differs from it by one bit. With a delta, it lists a quadword if it is within delta of the value or differs from value - delta by one bit. WinDbg’s !search uses the same rules. Each hit shows its PFN, its offset, and the value, and from the PFN database, the PTE that maps the page and the virtual address that this PTE maps. The virtual address is - when the PTE is not in the self-map. The command skips and counts the pages that it cannot read, and the search stops after 4096 hits or when you press Ctrl+C.

#

Search the disassembly for the next instruction that matches a pattern.

# [pattern] [address [L<count>]]

The pattern can match any part of the address, bytes, or text of an instruction, where the text is the mnemonic, the operands, and the resolved symbol. The match is not case-sensitive, and you can use * and ? wildcards. To include spaces, put the pattern in quotes (# "mov*cr3" nt!KiSwapContext). The command shows the first match. If you do not give an address, the search continues after the last match, and the first search starts at the instruction pointer. If you do not give a pattern, the command uses the last pattern again, so a bare # finds the next occurrence. L<count> sets the maximum number of instructions to search. Without it, the search continues until it finds a match, reaches an unreadable page, or searches 1,048,576 instructions, and you can also stop it with Ctrl+C.

.pagein

Make a paged-out address resident with the debugger worker in the guest.

.pagein [/p <pid|eprocess>] <address>

Because the guest does the work, ntoseye resumes the target, which halts again at nt!DbgBreakPointWithStatus and not at its earlier location. /p attaches the worker to a process first, which user-space addresses need.

.readmem

Read a file into a virtual memory range.

.readmem <file> <address> <L<count>|length|end>
.writemem

Write a virtual memory range to a file.

.writemem <file> <address> <L<count>|length|end>
c

Compare two memory ranges byte by byte.

c <address> <L<count>|length|end> <address2>

The command compares the range with the same number of bytes at . It lists each byte that is different, as <address> <byte> - <address2> <byte> (c nt L1000 poi(@$t0)). If an offset is unreadable in one of the ranges, the command skips and counts it. It compares up to 1 GiB and stops after 4096 differences or when you press Ctrl+C.

dS

Show a UNICODE_STRING descriptor and its buffer.

dS <address>
dW

Show memory as words with an ASCII column.

dW <address> [L<count>|length|end]
da

Show a NUL-terminated ASCII string.

da <address> [max-chars]
db

Show memory as bytes.

db <address> [L<count>|length|end]
dc

Show memory as doublewords with an ASCII column.

dc <address> [L<count>|length|end]
dd

Show memory as doublewords (4 bytes).

dd <address> [L<count>|length|end]
dds

Show memory as doublewords, and the symbol of each value that resolves to one.

dds <address> [L<count>|length|end]
df

Show memory as single-precision (df, 4-byte) or double-precision (dD, 8-byte) floating-point numbers.

df <address> [L<count>|length|end]

Also: dD

dl

Dump a bounded _LIST_ENTRY chain.

dl [-b] <address> <maxcount> [size]

By default, the walk follows Flink, and -b follows Blink. The optional size is the number of pointer-sized words that the command shows for each element, 2 by default. The given address is the first element, as in WinDbg, so the walk includes all nodes until it returns to that address. In memory, a list head and a record link look the same, so if you start at a list head instead of at poi(ListHead), the command shows the head as one pseudo-record and does not drop a real record. If the list is empty, its link points to itself, and the command shows nothing. The walk keeps the entries that it collected, and reports null links, cycles, unreadable links, and when it reaches the entry limit. It does not report when it reaches the requested maxcount.

dp

Show memory as pointer-sized values.

dp <address> [L<count>|length|end]
dpp

Show pointers and the data that each pointer points to.

dpp <address> [L<count>|length|end]

Also: dqp, ddp, dqa, dpa, dda, dqu, dpu, ddu

After each pointer, dp shows the value, da the ASCII string, and du the UTF-16 string at that pointer. dd reads doubleword pointers, and dq* and its dp* aliases read quadwords. d*p also shows symbols.

dq

Show memory as quadwords (8 bytes).

dq <address> [L<count>|length|end]
dqs

Show memory as quadwords, and the symbol of each value that resolves to one.

dqs <address> [L<count>|length|end]

Also: dps

Use it for raw stack triage. If the unwinder cannot find the return addresses, dqs @rsp finds them in the raw stack.

ds

Show an ANSI_STRING descriptor and its buffer.

ds <address>
du

Show a NUL-terminated UTF-16 string (for example, a UNICODE_STRING Buffer).

du <address> [max-chars]
dw

Show memory as words (2 bytes).

dw <address> [L<count>|length|end]
dyb

Show memory as binary values with their bytes.

dyb <address> [L<count>|length|end]
ea

Write an ANSI string to memory.

ea <address> <text>
eb

Write one or more bytes to memory.

eb <address> <value>...
ed

Write one or more doublewords (4 bytes) to memory.

ed <address> <value>...
ef

Write single-precision (ef, 4-byte) or double-precision (eD, 8-byte) floating-point numbers to memory.

ef <address> <number>...

Also: eD

The numbers are decimal floating-point literals (ef @rcx 1.5 -2 3e-4), whatever the radix setting.

eq

Write one or more quadwords (8 bytes) to memory.

eq <address> <value>...
eu

Write a UTF-16 string to memory.

eu <address> <text>
ew

Write one or more words (2 bytes) to memory.

ew <address> <value>...
eza

Write a NUL-terminated ANSI string to memory.

eza <address> <text>
ezu

Write a NUL-terminated UTF-16 string to memory.

ezu <address> <text>
f

Fill memory with a repeated byte pattern.

f <address> <L<count>|length|end> <pattern>...

The pattern is bytes, in the same format as for s: 90, 48 89 5c, 48895c, or \x48\x89. The command repeats the pattern to fill the range (f @rsp L20 cc). It fills up to 16 MiB.

ib

Read a byte from an I/O port.

ib <port>

Reads the port (a byte for ib, a word for iw, a dword for id) on the current processor. The command uses the Windows KD protocol (DbgKdReadIoSpaceApi), so it needs the kd or kdnet backend and a halted target, and the GDB, memory, and dump backends have no I/O space. The port must be aligned to the access size. As on real hardware, a port read can change the device state (for example, a FIFO or a status latch).

id

Read a dword from an I/O port.

id <port>

Reads the port (a byte for ib, a word for iw, a dword for id) on the current processor. The command uses the Windows KD protocol (DbgKdReadIoSpaceApi), so it needs the kd or kdnet backend and a halted target, and the GDB, memory, and dump backends have no I/O space. The port must be aligned to the access size. As on real hardware, a port read can change the device state (for example, a FIFO or a status latch).

iw

Read a word from an I/O port.

iw <port>

Reads the port (a byte for ib, a word for iw, a dword for id) on the current processor. The command uses the Windows KD protocol (DbgKdReadIoSpaceApi), so it needs the kd or kdnet backend and a halted target, and the GDB, memory, and dump backends have no I/O space. The port must be aligned to the access size. As on real hardware, a port read can change the device state (for example, a FIFO or a status latch).

m

Copy a memory range to another address.

m <address> <L<count>|length|end> <destination>

The command reads the full range before it writes, so overlapping ranges copy as if through a buffer (m @rsp L20 @rsp+8). If this session set a breakpoint in the range, the command copies the original byte that the breakpoint replaced. It copies up to 16 MiB, and if a byte of the range is unreadable, it writes nothing.

ob

Write a byte to an I/O port.

ob <port> <value>

Writes the value to the port (a byte for ob, a word for ow, a dword for od) on the current processor. The command uses the Windows KD protocol (DbgKdWriteIoSpaceApi), so it needs the kd or kdnet backend and a halted target. The port must be aligned to the access size, and the value must fit in it.

od

Write a dword to an I/O port.

od <port> <value>

Writes the value to the port (a byte for ob, a word for ow, a dword for od) on the current processor. The command uses the Windows KD protocol (DbgKdWriteIoSpaceApi), so it needs the kd or kdnet backend and a halted target. The port must be aligned to the access size, and the value must fit in it.

ow

Write a word to an I/O port.

ow <port> <value>

Writes the value to the port (a byte for ob, a word for ow, a dword for od) on the current processor. The command uses the Windows KD protocol (DbgKdWriteIoSpaceApi), so it needs the kd or kdnet backend and a halted target. The port must be aligned to the access size, and the value must fit in it.

s

Search memory for bytes, values, or a string.

s [-b|-w|-d|-q|-a|-u] <address> <L<count>|length|end> <pattern>...

-b (the default) searches for bytes: 4d 5a, 4d5a, or \x4d\x5a. -w, -d, and -q search for 2-, 4-, and 8-byte values (s -d @rsp L100 0 1). -a and -u search for an ASCII or UTF-16 string (s -a nt L?1000000 "This program"). L<count> sets the number of elements of the search type. The search skips unreadable pages, scans up to 1 GiB, and stops after 4096 matches or when you press Ctrl+C.

u

Disassemble memory at a symbol or address.

u [address [L<count>|length|end]]

Also: disasm

L<count> sets the number of instructions, 8 by default. If you give an end address, the command shows all instructions that start at or before that address. If you do not give an address, the command continues after the last instruction that the previous u showed. After the target runs or steps, or when you select another frame, thread, or process, it starts at the instruction pointer instead.

ub

Disassemble the instructions that end at an address.

ub <address> [L<count>|count]
uf

Disassemble the function that contains an address.

uf [address]

The function’s runtime function entry gives its extent. A leaf function has none, so uf reads it from its symbol for as far as its control flow reaches before the next symbol: it follows the branches inside the function, and treats a branch past the next symbol as a tail call.