Debugger

final class ntoseye.Debugger

A live debugging session. As a context manager, leaving the with block closes it (close()): every breakpoint is removed, the target resumes, and the session ends.

Usable from any Python thread: calls are serialized on the session’s own thread, and a call that waits (run(), wait()) releases the GIL. Ctrl+C (KeyboardInterrupt) during a call ends a wait, step, or trace early and raises; during a resuming command() it breaks in, as in the REPL. Between calls the session keeps servicing the guest, resuming wrong-process and false-condition breakpoint hits so the guest never sits frozen. A debugger handed to a REPL custom command is valid only on the REPL’s thread, for that command.

__enter__() → Debugger
__exit__(_exc_type: Any, _exc_value: Any, _traceback: Any) → bool
property breakpoints: Breakpoints

Code breakpoints and data watchpoints: .add(...), .watch(...), iteration, [id].

property capabilities: list[Record]

The backend’s capability matrix as {capability, label, supported} records: which operations the transport supports.

close() → None

Remove every breakpoint, leave the target running, and end the session: the connection and the target’s single-instance lock are released, so the target can be attached again, and this debugger and its handles raise from then on. Closing again does nothing. On failure the target is left halted, the session stays open, and the error is raised. A borrowed (REPL command) debugger does not own the session and leaves it alone.

property coherent: bool

False after a reboot until the kernel’s module list exists: kernel symbols and breakpoints work, process/module enumeration does not yet.

command(line: str, timeout: float | None = None) → str

Run a REPL command line and return its text output (styling stripped). Commands that resume the target wait for the next stop, up to timeout seconds; the stop is then dbg.stop.

cont(disposition: Literal['handled', 'not_handled'] = ...) → None

Resume without waiting, acknowledging the current exception as handled or not_handled (KD only).

property cpus: Cpus

The target’s processors (vCPUs): cpus[0].registers.rip.

crash() → None

Crash the target on purpose (.crash), producing a bugcheck stop.

debug_log(since: int = 0) → Record

Captured guest debug output (DbgPrint) since sequence since: {lines: [{seq, timestamp_ms, text}], next_seq, dropped}. Pass the previous next_seq to poll only new lines.

property drivers: Drivers

Driver objects from the object manager’s Driver directory: drivers["Disk"], .at(addr).

eval(expr: str) → int

Evaluate a debugger (MASM) expression in kernel scope to an integer; registers are the stopped vCPU’s.

property exceptions: Exceptions

Exception stop policies (sx*): .set(code, mode), iteration, .reset().

property generation: int

How many times the guest has been rebuilt (reboots). Handles from an older generation raise StaleHandleError; cache this beside raw addresses to know when they went stale.

property inspect: Inspect

System-wide reports and decode-by-address helpers (!vm, !pool, …).

interrupt() → Stop

Break into the running target and return the resulting stop.

property memory: Memory

Kernel virtual memory: the kernel’s own page tables. User addresses are not mapped here; read them through process.memory.

property modules: Modules

Loaded kernel modules: modules["nt"], iteration, .at(addr).

notices() → list[str]

Drain the diagnostics the debugger raised since the last call (a breakpoint that failed to re-arm, a reclaimed breakpoint slot, host memory that stopped matching after a reload).

property physical: Memory

Guest-physical memory, untranslated.

property processes: Processes

Running processes keyed by PID: processes[4], .find(name).

reboot() → None

Reboot the target (.reboot). The next stop is a Stop.Reboot.

reload() → None

Rebuild guest state now (rediscover the kernel). Stops already do this when the backend reports a reload; this forces it.

run(timeout: float | None = None, *, disposition: Literal['handled', 'not_handled'] = ...) → Stop | None

Resume and wait for the next stop, auto-resuming past wrong-process and false-conditional hits. Returns the Stop, or None if the target is still running after timeout seconds.

run_to(target: int | str, timeout: float | None = None, *, step: Literal['over', 'into'] | None = None) → Stop | None

Run until target (an address, or a symbolic module!name[+off]) is reached (g <addr>), or with step="over"/"into" single-step there (pa/ta). Other stops en route are returned as they are; with timeout, an unreached target is interrupted where it is.

property secure_kernel: SecureKernel

The VBS secure kernel (VTL1): read-only memory, symbols, types, modules, and trustlets. Discovered on first use from host memory; raises NtoseyeError when VBS is not running or the backend cannot read host memory. Experimental.

step(until: Literal['call', 'ret', 'branch'] | None = None) → Stop

Single-step one instruction, or with until (“call”, “ret”, “branch”) step into until the next such instruction (tc/tt/th).

step_out() → Stop

Run until the current function returns (gu).

step_over(until: Literal['call', 'ret', 'branch'] | None = None) → Stop

Step over the current instruction, or with until step over until the next call/ret/branch (pc/pt/ph).

property stop: Stop | None

The current stop while the target is halted, None while it runs.

property symbols: Symbols

Kernel-scope symbols: symbols["nt!KeBugCheckEx"], nearest(addr), search(query), the symbol and source paths.

property threads: Threads

Every Windows thread keyed by TID: threads[tid], .at(ethread).

trace_calls(limit: int = 10000) → Record

Trace calls until the current function returns (wt), single-stepping at most limit instructions: {end, error, instructions, root}, where root is the call tree and end says why tracing stopped.

property types: Types

Kernel-scope PDB types: types["_EPROCESS"].at(addr).

wait(timeout: float | None = None) → Stop | None

Wait for the next stop without resuming. Returns the current stop at once when already halted, None if still running after timeout.

write_dump(path: str) → int

Write a full PAGEDU64 kernel dump of the halted target to path (.dump /f). Returns the number of unreadable pages zero-filled.