Pydbg is also a pure python based debugger. Pydbg is my favourite debugger, I use it in various automation tasks and it is extremely flexible and powerful
Problem Statement:
We want to track VirtualAlloc API whenever VirtualAlloc is called, our script should display its arguments and the returned pointer.
VirtualAlloc: LPVOID WINAPI VirtualAlloc( __in_opt LPVOID lpAddress, __in SIZE_T dwSize, __in DWORD flAllocationType, __in DWORD flProtect );
Solution:
# Author: Amit Malik # http://www.securityxploded.com import sys import pefile import struct from pydbg import * from pydbg.defines import * def ret_addr_handler(dbg): lpAddress = dbg.context.Eax # Get value returned by VirtualAlloc print " Returned Pointer: ",hex(int(lpAddress)) return DBG_CONTINUE def virtual_handler(dbg): print "****************" pdwSize = dbg.context.Esp + 8 # 2nd argument to VirtualAlloc rdwSize = dbg.read_process_memory(pdwSize,4) dwSize = struct.unpack("L",rdwSize)[0] dwSize = int(dwSize) print "Allocation Size: ",hex(dwSize) pflAllocationType = dbg.context.Esp + 12 # 3rd argument to VirtualAlloc rflAllocationType = dbg.read_process_memory(pflAllocationType,4) flAllocationType = struct.unpack("L",rflAllocationType)[0] flAllocationType = int(flAllocationType) print "Allocation Type: ",hex(flAllocationType) pflProtect = dbg.context.Esp + 16 # 4th Argument to VirtualAlloc rflProtect = dbg.read_process_memory(pflProtect,4) flProtect = struct.unpack("L",rflProtect)[0] flProtect = int(flProtect) print "Protection Type: ",hex(flProtect) pret_addr = dbg.context.Esp # Get return Address rret_addr = dbg.read_process_memory(pret_addr,4) ret_addr = struct.unpack("L",rret_addr)[0] ret_addr = int(ret_addr) dbg.bp_set(ret_addr,description="ret_addr breakpoint",restore = True,handler = ret_addr_handler) return DBG_CONTINUE def entry_handler(dbg): virtual_addr = dbg.func_resolve("kernel32.dll","VirtualAlloc") # Get VirtualAlloc address if virtual_addr: dbg.bp_set(virtual_addr,description="Virtualalloc breakpoint",restore = True,handler = virtual_handler) return DBG_CONTINUE def main(): file = sys.argv[1] pe = pefile.PE(file) # get entry point entry_addr = pe.OPTIONAL_HEADER.AddressOfEntryPoint + pe.OPTIONAL_HEADER.ImageBase dbg = pydbg() # get pydbg object dbg.load(file) dbg.bp_set(entry_addr,description="Entry point breakpoint",restore = True,handler = entry_handler) dbg.run() if __name__ == '__main__': main()
Notice that in this script first i am setting breakpoint on entry point and then on VirtualAlloc not directly to VirtualAlloc because pydbg does not support deferred breakpoints. I am also ignoring 1st argument to VirtualAlloc i.e lpAddress, see VirtualAlloc specification in problem statement.
This script uses two modules PEFile and Pydbg, PEFile is used to get the entry point.