32 KiB
Table of Contents
- 1. Introduction
- 2. Windbg Commands
- 3. Debugging Management
- 4. Working with Memory and Registers
- 5. Modules
- 6. Retrieving Symbolic Information
- 7. Typed Variables
- 8. Processes and Threads
- 9. Local Variables
- 10. Breakpoints
- 11. Debugging Events
- 12. Disasm Class
- [API Reference | PYKD 0.2 API Reference]
1. Introduction
1.1 General Information
The pykd project started in 2010. The main motivation for its development was the inconvenience of built-in tools for writing debugging scripts for WinDbg. The Python language was chosen as an alternative scripting engine for several reasons:
- Ease of learning the language
- A large standard library
- A powerful and convenient framework for creating extension modules
pykd is a module for the CPython interpreter. It is written in C++ and uses Boost.Python to export functions and classes to Python. pykd provides access to debugging management on the Windows platform via the Debug Engine library and retrieves symbolic information via the MS DIA library.
It is important to note that pykd does not provide direct access to the COM interfaces of Debug Engine and MS DIA. Instead, it implements its own interface, making the development process faster and more convenient (at least, that is the hope).
pykd can work in two modes:
- As a plugin for WinDbg, providing commands for running scripts within a debugging session.
- As a standalone module for the Python interpreter, which is useful for creating automated tools to analyze crash dumps, for example.
1.2 Quick Start
For a quick start, it is best to download the automatic installer. It will install all necessary components, including Python (if it is not already installed).
To verify the installation, launch WinDbg and start debugging an application or analyzing a dump. Then, load pykd:
.load pykd.pyd
If no error messages appear, the installation was successful. To double-check that everything works, try running the Python interactive console within WinDbg:
>!pycmd
Python 2.6.5 (r265:79096, Mar 19 2010, 18:02:59) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> print("Hello world!")
Hello world!
>>> quit()
>
Try running example scripts:
!py help
!py samples
If everything works, you can proceed to writing your own scripts.
1.3 Building from Source
Getting the Source Code
Download the source code from the repository.
Installing Python
Download the required version from here.
Installing and Configuring Boost
Boost can be obtained from this link. Installation and build instructions are also available there.
Setting Up Environment Variables
The following environment variables need to be set for compilation:
$(DIA_SDK_ROOT)
– Path to the MS DIA library. It should look like:
The MS DIA library is installed with Visual Studio.C:\Program Files (x86)\Microsoft Visual Studio 9.0\DIA SDK
$(DBG_SDK_ROOT)
– Path to the Debug Engine SDK:
The Debug Engine SDK is included in Debugging Tools for Windows (now part of Platform SDK).C:\Program Files (x86)\Debugging Tools for Windows (x86)\sdk
$(BOOST_ROOT)
– Path to the Boost installation directory.$(PYTHON_ROOT)
– Path to the Python installation directory. The expected directory structure:
If Python installation does not differentiate between x86 and x64, the project file may need modification.C:\Python26\x86\... C:\Python26\x64\...
Building Boost.Python Libraries
To compile the required Boost.Python static libraries, use the following commands:
bjam --stagedir=stage --with-python stage
bjam address-model=64 --stagedir=stage64 --with-python stage
If bjam is not installed, download it from here.
1.4 Manual Installation
Installing pykd.pyd and Required Dependencies
To install manually, you will need:
pykd.pyd
- C++ Runtime Redistributable (
vcredist
) matching the version used to buildpykd.pyd
.
Where to Copy pykd.pyd?
The location depends on how you intend to use pykd
:
- As a WinDbg plugin – Copy
pykd.pyd
to thewinext
directory inside the WinDbg installation folder. You may rename it topykd.dll
so it can be loaded without specifying an extension:kd>.load pykd
- For Python scripting – Place
pykd.pyd
in a directory where Python can find it. Possible options:- Inside Python's
Lib
subdirectory. - Any custom directory, added to the
PYTHONPATH
environment variable. - Any directory, without modifying
PYTHONPATH
, but always launching Python from that directory.
- Inside Python's
Installing vcredist
Make sure to install the appropriate C++ Runtime Redistributable (vcredist).
Registering MS DIA
The MS DIA library must be registered after installation. Find the msdia90.dll
file and execute:
regsvr32 msdia90.dll
If you built the module yourself using Visual Studio, then vcredist is already installed, and MS DIA should be registered automatically.
1.5 API Changes
loadModule
Function Removal
The loadModule
function has been removed. Use the module
class constructor instead:
# Old way (no longer valid)
mod = loadModule("mymodule")
# New way
mod = module("mymodule")
2. Windbg Commands
2.1 Loading the Plugin
To load the pykd plugin in WinDbg, run:
kd>.load pykd_path/pykd.pyd
If pykd.pyd
is inside the winext folder (a subdirectory of Debugging Tools for Windows), the path is not needed:
kd>.load pykd.pyd
If pykd.pyd
is renamed to pykd.dll
, the extension can be omitted:
kd>.load pykd
To view loaded extensions in WinDbg, use:
kd>.chain
To unload the plugin:
kd>.unload pykd_path/pykd.pyd
kd>.unload pykd.pyd
kd>.unload pykd
To avoid manually loading pykd every session, load it once and then save the workspace:
kd> Save Workspace
2.2 Running a Script
To run a Python script using pykd, use the !py
command:
kd>!py script_path/script_name.py param1 param2 ...
The .py
extension can be omitted.
To avoid specifying full paths, add the script directory to PYTHONPATH
or modify the Windows registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.6\PythonPath
In Python, command-line parameters are available in sys.argv
:
import sys
print("Script path: " + sys.argv[0])
print("param1: " + sys.argv[1])
print("param2: " + sys.argv[2])
2.3 Console Mode
To launch an interactive Python console within WinDbg, use:
kd>!pycmd
Example session:
1: kd> !pycmd
Python 2.6.5 (r265:79096, Mar 19 2010, 18:02:59) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
The pykd
module is automatically imported, so you can start using pykd functions immediately.
To exit the Python console, use quit()
. The state of the interpreter is preserved:
>>> a = 10
>>> quit()
1: kd> !pycmd
Python 2.6.5 (r265:79096, Mar 19 2010, 18:02:59) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> print(a)
10
>>>
3. Debugging Management
3.1 Pausing and Resuming Debugging
In WinDbg, you can pause and resume debugging using:
- Break (Ctrl + Break)
- Go (F5)
Equivalent pykd functions:
go()
– Resumes execution and returns control when the debugger stops.breakin()
– Forces a break into the debugger.
Example: Continuous Debugging Loop
try:
while True:
go()
print("Break detected")
except:
print("Process terminated")
⚠ Warning: breakin()
is rarely needed. Since scripts usually execute only while the debugger is paused, calling breakin()
inside a script has no effect.
To stop debugging from a script, create a separate thread for breakin()
.
⚠ Do NOT use breakin()
, go()
, or trace()
inside event handlers (e.g., conditional breakpoints).
3.2 Step-by-Step Execution
For step debugging (tracing), use:
step()
– Equivalent to Step Into in WinDbg.trace()
– Equivalent to Step Over in WinDbg.
Both functions may raise a DbgException
if the debugged process has exited.
3.3 Debugging from Python Applications
If you want to run scripts outside WinDbg, you must first create a debugging session.
If only one session is used, it is created automatically with these functions:
Creating a Debugging Session
loadDump(dumpName)
– Loads a crash dump.startProcess(imageName)
– Starts a new process in debugging mode.attachProcess(processId)
– Attaches the debugger to an existing process.attachKernel(parameterStr)
– Attaches the debugger to a kernel debugging session.
Detaching or Terminating the Debugged Process
detachProcess(id)
– Detaches the debugger from a process.killProcess(id)
– Stops debugging and terminates the process.
Checking Debugger Mode
To determine if the debugger is analyzing a memory dump:
if isDumpAnalyzing():
print("Debugger is analyzing a memory dump.")
To check if debugging is in kernel mode:
if isKernelDebugging():
print("Kernel debugging mode detected.")
This is useful when scripts depend on kernel symbols and should only run in kernel mode.
3.4 Printing Debug Information
Instead of using print()
, pykd provides specialized functions:
dprint(message, dml=False)
– Prints a message without a newline.dprintln(message, dml=False)
– Prints a message with a newline.
The dml
parameter enables DML (Debug Markup Language) formatting, which works in WinDbg only.
Example: Using DML for Clickable Output
dprintln("<b><u>Click here to reload all symbols:</u></b>", True)
dprintln("<link cmd=\".reload /f\">Reload Symbols</link>", True)
This displays a clickable command inside WinDbg.
3.5 Executing Debugger Commands
To run WinDbg commands from Python, use:
dbgCommand("!analyze -v")
Example:
output = dbgCommand("!analyze -v")
dprint(output)
To evaluate an expression (similar to the ?
command in WinDbg):
expr("@rax + 10")
Loading & Calling WinDbg Extensions
extHandle = loadExt("ext_path") # Load an extension
result = callExt(extHandle, "command", "params") # Call an extension command
removeExt(extHandle) # Unload extension
⚠ Important: The ext
class was removed in pykd 0.2. Use loadExt()
instead.
3.6 Creating a Crash Dump
You can save the system state as a crash dump for later analysis.
Creating a Dump File
writeDump("C:\\dump\\fulldump.dmp", False) # Full memory dump
writeDump("C:\\dump\\minidump.dmp", True) # Minidump (smaller)
The second parameter specifies the dump type:
False
= Full dump (contains all memory pages).True
= Minidump (smaller, excludes unnecessary memory pages).
Crash dumps can be created in both user-mode and kernel-mode debugging.
4. Working with Memory and Registers
4.1 Accessing General-Purpose Registers
To access general-purpose registers (GPRs), use:
* cpuReg reg( regName ) # Access register by name
* cpuReg reg( regIndex ) # Access register by index
Example: Accessing a Register
r = reg("eax")
print(r / 10 * 234)
Exception Handling
Both versions of reg()
return an instance of the cpuReg
class.
If the register information cannot be retrieved, a BaseException
is raised.
cpuReg
Class Methods
The cpuReg
class provides the following methods:
name()
– Returns the register name.index()
– Returns the register index.
Arithmetic Operations with Registers
The cpuReg
class supports arithmetic operations directly, without type conversion:
r = reg("eax")
print(r / 10 * 234)
Enumerating All Registers
import pykd
try:
i = 0
while True:
r = pykd.reg(i)
pykd.dprintln(f"{r.name()} {hex(r)} ({r})")
i += 1
except pykd.BaseException:
pass
⚠ Important: pykd
currently supports only integer registers.
FPU, MMX, and SSE registers are not supported (planned for future versions).
4.2 Accessing Model-Specific Registers (MSR)
Use rdmsr(msrNumber)
to read MSR registers:
print(findSymbol(rdmsr(0x176)))
4.3 Virtual Address Normalization
All pykd functions return normalized 64-bit virtual addresses. On 32-bit platforms, addresses are sign-extended to 64 bits:
Original Address | Normalized Address |
---|---|
0x00100000 |
0x0000000000100000 |
0x80100000 |
0xFFFFFFFF80100000 |
For comparison, use addr64()
:
import pykd
nt = pykd.module("nt")
if nt > addr64(0x80000000):
print("NT module is in higher address space")
4.4 Direct Memory Access
To read unsigned integers from memory:
ptrByte(va)
ptrWord(va)
ptrDWord(va)
ptrQWord(va)
For signed integers:
ptrSignByte(va)
ptrSignWord(va)
ptrSignDWord(va)
ptrSignQWord(va)
For architecture-independent reads:
ptrMWord(va)
ptrSignMWord(va)
ptrPtr(va)
To read a block of memory:
loadBytes(va, count)
loadWords(va, count)
loadDWords(va, count)
loadQWords(va, count)
Returns a list.
4.5 Memory Access Errors
If a memory access fails, MemoryException
is raised:
try:
a = ptrByte(0)
except MemoryException:
print("Memory exception occurred")
To check if an address is valid:
isValid(va)
4.6 Reading Strings from Memory
Instead of using loadBytes()
, pykd provides:
loadChars(va, count) # Returns ASCII string
loadWChars(va, count) # Returns Unicode string
For null-terminated strings:
loadCStr(va)
loadWStr(va)
⚠ Maximum string length is 64 KB. Longer strings will raise MemoryException
.
For Windows kernel UNICODE_STRING and ANSI_STRING structures:
loadAnsiString(va)
loadUnicodeString(va)
5. Modules
5.1 Module Class
A module is an executable file mapped into memory. A typical program consists of a main module (usually a .exe
file) and a set of libraries.
Creating a Module Instance
The module
class has two constructor forms:
module(moduleName)
module(va)
- The first form creates a module object by name.
- The second form creates a module object by a virtual address belonging to the module.
If the module is not found, a BaseException
is raised.
Example:
from pykd import *
try:
ntdll = module("ntdll")
print(ntdll.name(), hex(ntdll.begin()), hex(ntdll.size()))
except BaseException:
print("Module not found")
Retrieving Module Information
Use these methods of the module
class:
name()
– Returns the module's name.image()
– Returns the module's executable file name.pdb()
– Returns the full path to the PDB (symbol) file.begin()
– Returns the module's base virtual address.end()
– Returns the module's end virtual address.checksum()
– Returns the module's checksum.timestamp()
– Returns the module's timestamp.getVersion()
– Returns the module's version as a tuple, e.g.,(1, 0, 6452, 0)
.queryVersion(valueName)
– Retrieves a specific version resource value.
Loading and Accessing Symbols
To load symbol information, use:
mod.reload()
To find a symbol's virtual address:
addr = mod.offset("symbolName")
If the symbol is not found, a BaseException
is raised.
Instead of explicitly calling offset()
, you can use attributes:
nt = module("nt")
print(hex(nt.offset("PsLoadedModuleList")))
print(hex(nt.PsLoadedModuleList)) # Shortcut
To retrieve the Relative Virtual Address (RVA) of a symbol:
rva = mod.rva("symbolName")
Module Type Information
To retrieve type information, use:
t = mod.type("_MDL")
print(t)
Example output:
struct/class: _MDL Size: 0x1c (28)
+0000 Next : _MDL*
+0004 Size : Int2B
+0006 MdlFlags : Int2B
+0008 Process : _EPROCESS*
+000c MappedSystemVa : Void*
+0010 StartVa : Void*
+0014 ByteCount : ULong
+0018 ByteOffset : ULong
Typed Variables
pykd
provides the typedVar
class for working with structured data. You can obtain an instance using:
mod.typedVar(va)
mod.typedVar(symbolName)
mod.typedVar(typeName, va)
Example:
nt = module("nt")
print(nt.typedVar("_LIST_ENTRY", nt.PsLoadedModuleList))
Output:
struct/class: _LIST_ENTRY at 0xfffff8000369c650
+0000 Flink : _LIST_ENTRY* 0xfffffa8003c64890
+0008 Blink : _LIST_ENTRY* 0xfffffa80092f8f30
5.2 Handling Module Load and Unload Events
To handle module load/unload events, subclass eventHandler
:
onLoadModule
– Called when a module is loaded.onUnloadModule
– Called when a module is unloaded.
6. Retrieving Symbolic Information
6.1 Symbol Files (PDB)
A PDB (Program Database) file contains debugging symbols. Depending on compiler settings, it may include:
- Global variables and constants.
- Function and method names with parameters.
- User-defined types (structs, classes, enums).
- Constant values.
- Local variables.
pykd uses the MS DIA library to work with symbols and provides a custom interface for direct access.
6.2 Type Information
typeInfo
Class
The typeInfo
class represents type information, including:
- Structures
- Classes
- Unions
- Enumerations
- Bit fields
- Pointers
- Basic types
Methods:
name() # Returns type name
size() # Returns type size
staticOffset() # Returns static field offset
fieldOffset() # Returns field offset
bitOffset() # Returns bit field offset
bitWidth() # Returns bit field width
field() # Retrieves a field
asMap() # Retrieves enum name-value mapping
deref() # Dereferences a pointer
ptrTo() # Creates a pointer to a type
arrayOf() # Creates an array of the type
append() # Adds a field (for manually created structs)
Getting a typeInfo
Object
Use the constructor with a type name:
t = typeInfo("ntdll!_UNICODE_STRING")
print(t)
Example output:
class/struct : _UNICODE_STRING Size: 0x10 (16)
+0000 Length : UInt2B
+0002 MaximumLength : UInt2B
+0008 Buffer : UInt2B*
To retrieve all types in a module:
nt = module("ntdll")
for typeName in nt.enumTypes():
print(typeName)
Creating Custom Types
If a required type is missing, use typeBuilder
:
tb = typeBuilder()
us = tb.createStruct("_UNICODE_STRING")
us.append("Length", tb.UInt2B)
us.append("MaximumLength", tb.UInt2B)
us.append("Buffer", tb.WChar.ptrTo())
print(us)
Output:
class/struct : _UNICODE_STRING Size: 0x10 (16)
+0000 Length : UInt2B
+0002 MaximumLength : UInt2B
+0008 Buffer : WChar*
[Back to Table of Contents](#table]
7. Typed Variables
7.1 typedVar
Class
The typedVar
class simplifies working with complex structures:
t1 = typedVar("MyModule!MyVar")
t2 = typedVar("MyModule!MyType", addr)
ti = typeInfo("MyModule!MyType")
t3 = typedVar(ti, addr)
If the variable or type does not exist, SymbolException
is raised.
Example:
try:
typedVar("MyModule!NonExistentVar")
except SymbolException:
print("Variable does not exist")
7.2 typedVar
Class Methods
getAddress()
– Returns variable address.sizeof()
– Returns variable size.offset()
– Returns field offset within the parent structure.field(fieldName)
– Retrieves a structure field.deref()
– Dereferences a pointer.type()
– Retrieves variable type.
7.3 typedVar
Class Methods
The typedVar
class provides methods to access and manipulate structured data.
Retrieving Variable Properties
getAddress()
– Returns the memory address of the variable.sizeof()
– Returns the size of the variable in bytes.offset()
– If the variable is a structure field, returns the offset within its parent.
Accessing Structure Fields
field(fieldName)
– Returns the value of a specific field as atypedVar
object.
Example:
tv = typedVar("structVar")
print(tv.field("fieldName"))
Alternatively, access fields as attributes:
print(tv.fieldName)
Both methods return the same result.
Dereferencing Pointers
deref()
– Returns the value pointed to by atypedVar
pointer.
Example:
ptr = typedVar("ptrStruct")
dereferenced_value = ptr.deref()
Retrieving Type Information
type()
– Returns thetypeInfo
object for the variable.
7.4 Classes and Structures
Enumerating Structure Fields
To loop through all fields of a structure:
tv = typedVar("structVar")
for fieldName, fieldValue in tv:
print(fieldName, fieldValue)
This returns a tuple containing the field name and value.
7.5 Arrays and Pointers
typedVar
supports arrays and multidimensional arrays.
Accessing Array Elements
Use the []
operator:
arr = typedVar("intArray")
print(arr[0]) # First element
print(arr[2]) # Third element
Accessing Multidimensional Arrays
matrix = typedVar("intMatrix")
print(matrix[1][2]) # Element at row 1, column 2
Working with Pointers
Use deref()
to get the value stored at a pointer’s address:
ptr = typedVar("ptrIntArray")
print(ptr.deref()[1]) # Access second element through pointer
⚠ Important: typedVar
does not follow C pointer arithmetic rules. Pointer arithmetic treats addresses as raw numbers.
7.6 Enumerations
Use typeInfo.asMap()
to get an enumeration’s name-value mapping.
Example:
var = typedVar("myStruct")
enum_type = var.structType.type().asMap()
print(enum_type[var.structType]) # Get enum name from value
Using Enums in Conditional Statements
if var.structType == var.structType.type().TYPE_ONE:
print("TYPE_ONE detected")
else:
print("ANOTHER_TYPE")
7.7 Casting to Other Types
Converting typedVar
to String
print(str(typedVar("g_struct")))
Example output:
struct/class: struct3 at 0x13f4391f8
+0000 m_arrayField : Int4B[2]
+0008 m_noArrayField : Int4B 0x3 (3)
Converting typedVar
to Integer
Use int()
or long()
. The conversion depends on the variable type:
Type | Conversion Result |
---|---|
Basic Types | Direct value |
Structures | Pointer to the structure |
Enums | Numeric value |
Pointers | Address stored in pointer |
Arrays | Address of first element |
Example:
var = typedVar("g_struct")
print(int(var.m_noArrayField)) # Integer conversion
print(hex(int(var.m_arrayField))) # Get array address
Output:
3
0x13f4391f8
8. Processes and Threads
8.1 User-Mode Threads
In user mode, the debugger operates in the context of the debugged process. If the process has multiple threads, you can switch contexts.
Key concepts:
- Current thread – The thread that will continue execution after resuming debugging.
- Implicit thread – The thread the debugger is currently analyzing.
Switching the Debugger's Thread Context
To change the thread context, use:
setImplicitThread(teb_address)
To get the current implicit thread:
getImplicitThread()
To get a list of all process threads:
getProcessThreads()
8.2 Kernel-Mode Threads
In kernel mode:
setImplicitThread()
andgetImplicitThread()
use ETHREAD instead of TEB.getProcessThreads()
is not available.
To enumerate process threads, use the _EPROCESS
structure:
nt = module("nt")
process = nt.typedVar("_EPROCESS", processAddr)
threadList = nt.typedVarList(process.ThreadListHead, "_ETHREAD", "ThreadListEntry")
⚠ Switching threads does not switch the process context.
8.3 Kernel-Mode Processes
In kernel debugging, you can work with system processes and driver execution contexts.
9. Local Variables
9.1 Retrieving Local Variables
If debug symbols contain local variable information, you can access them without manually handling registers and stack values.
Use:
locals_dict = getLocals()
Example:
# Retrieve a specific local variable
print(getLocals()["argc"])
# Print all local variables
for varName, varValue in getLocals().items():
print(varName, varValue)
10. Breakpoints
10.1 Setting Breakpoints
Use setBp()
to set breakpoints.
It returns an ID that can be used to remove the breakpoint with removeBp()
.
Setting a software breakpoint:
nt = module("nt")
bpid = setBp(nt.NtCreateFile)
Setting a hardware breakpoint:
bpid = setBp(nt.NtCreateFile, 1, 4)
- The second parameter is the memory access size.
- The third parameter is the access type:
1
– Read2
– Write4
– Execute
10.2 Conditional Breakpoints
Breakpoints can have conditions using callback functions.
Example:
import fnmatch
from pykd import *
nt = module('nt')
objAttrType = nt.type("_OBJECT_ATTRIBUTES")
def onCreateFile(id):
objattr = typedVar(objAttrType, ptrPtr(reg('esp') + 0xC))
return fnmatch.fnmatch(loadUnicodeString(objattr.ObjectName), '*.exe')
setBp(nt.NtCreateFile, onCreateFile)
In this case, the breakpoint triggers only when an executable file (*.exe
) is accessed.
You can also use lambda functions for conditions:
setBp(myAddr, lambda id: reg('rax') > 0x1000)
Handling Breakpoint Persistence
If a script sets a breakpoint but then exits, the breakpoint will be removed.
To persist it, use:
-
Script-controlled execution:
setBp(nt.NtCreateFile, onCreateFile) go()
This waits for the breakpoint to trigger before exiting.
-
Using
!pycmd
Run the script inside!pycmd
, so it remains active even after execution:>!pycmd >>> import setmybreak >>> quit() >g
The breakpoint stays active even after exiting the Python console.
⚠ Restricted functions inside breakpoints:
Do not use the following inside breakpoint handlers:
go()
,breakin()
,trace()
startProcess()
,killProcess()
,openDump()
setCurrentProcess()
,setImplicitThread()
11. Debugging Events
11.1 Handling Breakpoints (onBreakpoint
)
11.2 Handling Exceptions (onException
)
11.3 Handling Module Load Events (onLoadModule
)
11.4 Handling Module Unload Events (onUnloadModule
)
12. Disassembly (disasm
Class)
The disasm
class is a wrapper over the WinDbg disassembler. It provides equivalent results to the u
command.
12.1 Creating a Disassembler
d = disasm() # Start from current instruction
d = disasm(offset) # Start from a specific address
12.2 Disassembling Instructions
instr = d.disasm() # Disassemble next instruction
instr = d.disasm(offset) # Disassemble from a specific offset
12.3 Assembling Instructions
d.asm("mov eax, 1") # Modify machine code
12.4 Getting Current Instruction Info
print(d.current()) # Current address
print(d.instruction()) # Instruction mnemonic
print(d.length()) # Instruction size
12.5 Getting Effective Address
print(d.ea()) # Effective address of last instruction operand
12.6 Resetting Disassembler
d.reset() # Restart from initial address