Debugger¶
- final class ntoseye.Debugger¶
A live debugging session. You can use it as a context manager: when the
withblock ends, the debugger closes (close()), which removes all breakpoints, resumes the target, and ends the session.You can use it from any Python thread, and the session thread runs the calls one at a time. A call that waits (
run(),wait()) releases the GIL. Ctrl+C (KeyboardInterrupt) during a call that runs or waits on the target breaks in, as in the REPL, and raises the exception; the target is left halted where it was. Between calls the session continues to service the guest, resuming breakpoint hits in the wrong process and hits with a false condition so the guest does not stay frozen. A debugger that ntoseye gives to a REPL custom command is valid only on the REPL thread, and only for that command.- property breakpoints: Breakpoints¶
Code breakpoints and data watchpoints:
.add(...),.watch(...), iteration,[id].
- property capabilities: list[BackendCapability]¶
The capability matrix of the backend, which shows the operations that the transport supports.
- close() None¶
Remove all breakpoints, let the target run, and end the session. This releases the connection and the single-instance lock of the target, so you can attach to the target again. After this call, this debugger and its handles raise an exception, and a second call does nothing. If closing fails, the target stays halted, the session stays open, and the error is raised. A borrowed debugger (from a REPL command) does not own the session and leaves it unchanged.
- property coherent: bool¶
False after a reboot until the module list of the kernel exists. During that period kernel symbols and breakpoints work, but process and module enumeration do not work yet.
- command(line: str, timeout: float | None = None) str¶
Run a REPL command line and return its text output without styling. If a command resumes the target, this waits up to
timeoutseconds for the next stop, which then becomesdbg.stop. Command loops and.sleepalso end whentimeoutelapses.
- crash(timeout: float | None = None) Stop¶
Force a MANUALLY_INITIATED_CRASH (bugcheck 0xE2).
Windows first writes its crash dump, which often takes a minute, and the target ignores break-ins during this time. Then Windows reboots or, if automatic restart is disabled, breaks in. Ctrl+C stops the wait.
- debug_log(*, since: int = 0) DebugOutputPage¶
Captured guest debug output (DbgPrint) since sequence
since. To poll only for new lines, pass the previousnext_seq.
- property drivers: Drivers¶
Driver objects from the
Driverdirectory of the object manager:drivers["Disk"],.at(addr).
- eval(expr: str) int¶
Evaluate a debugger (MASM) expression to an integer (
?) in this object’s scope: the debugger’s is the kernel’s, with the registers of the stopped vCPU (on a user-mode minidump, of the selected thread); a process’s resolves the symbols of its modules, which it loads first; a VTL1 address space’s (the secure kernel’s, a trustlet’s) has no registers, as the live ones hold VTL0 state.
- property exceptions: Exceptions¶
Exception stop policies (
sx*):.set(code, mode), iteration,.reset().
- property generation: int¶
The number of times ntoseye has rebuilt its view of the guest, for example after a reboot. Handles from an older generation raise
StaleHandleError, so keep this value with raw addresses to know when they become stale.
- hypercalls() list[Hypercall]¶
The Windows hypervisor’s hypercall table, one entry per call code, as
!hvcalls -alists it. Needs the VM’shv-evmcsenlightenment or a vCPU stopped in the hypervisor. This feature is experimental.
- hypervisor_partitions() list[HypervisorPartition]¶
The partitions of the Windows hypervisor, root first, with their virtual processors, as
!hvpartitionsand!hvvpslist them. Each call walks them again. This needs the VM’shv-evmcsenlightenment or a vCPU stopped in the hypervisor, and an Intel host. RaisesNtoseyeErrorif ntoseye does not recognize the layout of this hypervisor build. This feature is experimental.
- property inspect: Inspect¶
System-wide reports and helpers that decode an object at an address (
!vm,!pool, …).
- interrupt() Stop¶
Break into the running target and return the stop that results. On a halted target, return the stop it is halted at (
breakrefuses it).
- property memory: Memory¶
Kernel virtual memory, read through the page tables of the kernel. User addresses are not mapped here, so read them through
process.memory. On a user-mode minidump, the captured process’s memory.
- property modules: Modules¶
Loaded kernel modules:
modules["nt"], iteration,.at(address). On a user-mode minidump, the modules the dump lists.
- notices() list[Notice]¶
Remove and return what the debugger reported since the last call, in order. Each notice has a
level:"warning"for something that did not work as it should, such as a breakpoint that failed to re-arm or host memory that no longer matched after a reload, or"info"for status, such as a background symbol fetch finishing, a breakpoint slot that was reclaimed, or theModLoad:line of ansxn ldfilter.
- property partition: int | None¶
The ID of the hypervisor partition inspected in place of the target (see
select_partition), orNonewhile the target is.
- property physical: Memory¶
Guest-physical memory, without address translation. A user-mode minidump has none, and its reads raise
NtoseyeError.
- reboot(timeout: float | None = None) Stop¶
Reboot the debug target and reload its kernel context.
ntoseye sends the reboot without confirmation, and handles the next KD state-change through the normal target-reload path.
- reload() None¶
Rebuild the guest state now (find the kernel again). Stops already do this when the backend reports a reload, and this function forces a rebuild. A user-mode minidump has no kernel to find, and raises
NtoseyeError.
- run(timeout: float | None = None, *, address: int | str | Process | Thread | Module | Driver | Device | Heap | None = None, disposition: Literal['handled', 'not_handled'] | None = None) Stop | None¶
Resume VM execution.
With an address, g runs to a temporary breakpoint at that address. ntoseye checks that an instruction starts there as bp does: it refuses an address inside an instruction and warns when it cannot check. In secure-kernel code, this breakpoint uses a debug register, and ntoseye never patches the code. The .vtl 1 memory view accepts only g without an address, which leaves the view before it resumes the VM. To stop in VTL1, use
ba e1.
- property secure_kernel: SecureKernel¶
The VBS secure kernel (VTL1), with read-only
memory,symbols,types,modules, andtrustlets. ntoseye finds it in host memory on first use and raisesNtoseyeErrorif VBS is not running or the backend cannot read host memory. This feature is experimental.
- select_partition(partition_id: int) None¶
Inspect the Windows guest that hypervisor partition
partition_idruns (a Windows Sandbox, a Hyper-V VM) in place of the target, as.partitiondoes:memory,processes,modules,symbols,typesandthreadsthen read that guest, through its EPT, and the vCPUs are its VPs, with their VTL0 registers. The target stays halted.memory.writewrites the guest’s memory through its EPT, and a register write goes to the target’s vCPU that runs the selected VP at the stop; a VP no vCPU runs has its registers in the hypervisor’s memory, and raisesNtoseyeError.breakpoints.add(..., hardware=True)andbreakpoints.watchset the partition’s breakpoints, which stop only on its VPs (processor=names one) and need the gdb backend; software breakpoints raise.runleaves the view and runs the target, and a hit of the partition’s breakpoint returns in its view, on the VP that hit it.step,step_overandstep_outstep the thread of the selected VP, andrun(address=...)runs until any of its VPs reaches an address, each a run of the target to a breakpoint of the partition’s;step(until=...)andtrace_callsraise. The root partition’s ID (1) returns to the target. Handles minted on either side of a switch go stale (generationadvances). The target must be halted. This feature is experimental.
- step(timeout: float | None = None, *, until: Literal['call', 'ret', 'branch'] | int | str | Process | Thread | Module | Driver | Device | Heap | None = None) Stop¶
Step one instruction (step into).
- step_out(timeout: float | None = None) Stop¶
Run until the current function returns.
gu stops at the return address only when the thread that you step returns from this call. Other threads that get to the address, and deeper calls of the same function, continue to run.
- step_over(timeout: float | None = None, *, until: Literal['call', 'ret', 'branch'] | int | str | Process | Thread | Module | Driver | Device | Heap | None = None) Stop¶
Step over the current instruction.
If the instruction is a call, p runs to the instruction after the call and stops there only when the thread that you step returns from that call. Other threads that get to the address, and deeper calls of the same code, continue to run.
- property symbols: Symbols¶
Kernel-scope symbols:
symbols["nt!KeBugCheckEx"],nearest(addr),search(query), and the symbol and source paths. On a user-mode minidump, the symbols of the dump’s modules.
- trace_calls(timeout: float | None = None, *, limit: int = 10000) CallTrace¶
Watch and trace calls until the current function returns.
- property types: Types¶
Kernel-scope PDB types:
types["_EPROCESS"].at(addr). On a user-mode minidump, the types of the dump’s modules’ PDBs (types["ntdll!_PEB"]).
- property user_dump: UserDump | None¶
The process, threads, and exception a user-mode minidump captured, or
Noneon a kernel target. A user-mode minidump has no kernel, soprocesses,threads,cpus,drivers,physical, and the kernel’sinspectreports raiseNtoseyeErroron it.