The win32 submodule provides a collection of useful API wrappers for most operations needed by a debugger. This will allow you to perform any task that the abstraction layer for some reason can’t deal with, or won’t deal with in the way you need. In most cases you won’t need to resort to this, but it’s important to know it’s there.
Except in some rare cases, the rationale to port the API calls to Python was:
- Take Python basic types as input, return Python basic types as output.
- Functions that in C take an output pointer and a size as input, in Python take neither and return the output data directly (the wrapper takes care of allocating the memory buffers).
- Functions that in C have to be called twice (first to get the buffer size, then to get the data) in Python only have to be called once (returns the data directly).
- Functions in C with more than one output pointer return tuples of data in Python.
- Functions in C that return an error condition, raise a Python exception (WindowsError) on error and return the data on success.
- Default parameter values were added when possible. The default for all optional pointers is NULL. The default flags are usually the ones that provide all possible access (for example, the default flags value for GetThreadContext is CONTEXT_ALL)
- For APIs with ANSI and Widechar versions, both versions are wrapped. If at least one parameter is a Unicode string en Widechar version is called (and all string parameters are converted to Unicode), otherwise the ANSI version is called. Either ANSI or Widechar versions can be used explicitly (for example, CreateFile can be called as CreateFileA or CreateFileW).
All handles returned by API calls are wrapped around the Handle class. This allows you to use the with statement to ensure proper cleanup, and causes handles to be closed automatically when they go out of scope, thus preventing handle leaks.
import sys
from winappdbg import win32
try:
fullpath, basename = win32.SearchPath( None, sys.argv[1], '.dll' )
except WindowsError, e:
if e.winerror != win32.ERROR_FILE_NOT_FOUND:
raise
fullpath, basename = win32.SearchPath( None, sys.argv[1], '.exe' )
print "Full path: %s" % fullpath
print "Base name: %s" % basename
import sys
import thread
from winappdbg import win32
def processKiller(dwProcessId):
# Attach to the process.
win32.DebugActiveProcess( dwProcessId )
# Quit the current thread.
thread.exit()
from winappdbg.win32 import *
def print_heap_blocks( pid ):
# Determine if we have 32 bit or 64 bit pointers.
if sizeof(SIZE_T) == sizeof(DWORD):
fmt = "%.8x\t%.8x\t%.8x"
hdr = "%-8s\t%-8s\t%-8s"
else:
fmt = "%.16x\t%.16x\t%.16x"
hdr = "%-16s\t%-16s\t%-16s"
# Print a banner.
print "Heaps for process %d:" % pid
print hdr % ("Heap ID", "Address", "Size")
# Create a snapshot of the process, only take the heap list.
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPHEAPLIST, pid )
# Enumerate the heaps.
heap = Heap32ListFirst( hSnapshot )
while heap is not None:
# For each heap, enumerate the entries.
entry = Heap32First( heap.th32ProcessID, heap.th32HeapID )
while entry is not None:
# Print the heap id and the entry address and size.
print fmt % (entry.th32HeapID, entry.dwAddress, entry.dwBlockSize)
# Next entry in the heap.
entry = Heap32Next( entry )
# Next heap in the list.
heap = Heap32ListNext( hSnapshot )
# No need to call CloseHandle, the handle is closed automatically when it goes out of scope.
return
from winappdbg.win32 import *
def print_modules( pid ):
# Determine if we have 32 bit or 64 bit pointers.
if sizeof(SIZE_T) == sizeof(DWORD):
fmt = "%.8x %.8x %s"
hdr = "%-8s %-8s %s"
else:
fmt = "%.16x %.16x %s"
hdr = "%-16s %-16s %s"
# Print a banner.
print "Modules for process %d:" % pid
print
print hdr % ("Address", "Size", "Path")
# Create a snapshot of the process, only take the heap list.
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pid )
# Enumerate the modules.
module = Module32First( hSnapshot )
while module is not None:
# Print the module address, size and pathname.
print fmt % ( module.modBaseAddr,
module.modBaseSize,
module.szExePath )
# Next module in the process.
module = Module32Next( hSnapshot )
# No need to call CloseHandle, the handle is closed automatically when it goes out of scope.
return
from winappdbg.win32 import *
def print_drivers( fFullPath = False ):
# Determine if we have 32 bit or 64 bit pointers.
if sizeof(SIZE_T) == sizeof(DWORD):
fmt = "%.08x\t%s"
hdr = "%-8s\t%s"
else:
fmt = "%.016x\t%s"
hdr = "%-16s\t%s"
# Get the list of loaded device drivers.
ImageBaseList = EnumDeviceDrivers()
print "Device drivers found: %d" % len(ImageBaseList)
print
print hdr % ("Image base", "File name")
# For each device driver...
for ImageBase in ImageBaseList:
# Get the device driver filename.
if fFullPath:
DriverName = GetDeviceDriverFileName(ImageBase)
else:
DriverName = GetDeviceDriverBaseName(ImageBase)
# Print the device driver image base and filename.
print fmt % (ImageBase, DriverName)