例子代码:
调试器需要具备两种基本能力:打开执行程序作为自身子进程运行、附加一个现有进程的能力
第一种使用CreateProcessA函数,重要的参数是:lpApplicationName(可执行文件所在路径)、lpCommandLine(命令行参数)、dwCreationFlags(可调式设置)、lpStartupInfo(结构体STARINFO)和lpProcessInformation(结构体PROCESS_INFORMATION),其余参数可以设置为NULL。
my_debugger_defines.py
#__author__ = 'zt'
#coding=utf-8
from ctypes import *
#为ctype变量创建符合匈牙利命名风格的匿名,这样可以使代码更接近Win32的风格
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
#常值定义
DEBUG_RPOCESS = 0x00000001
CREATE_NEW_CONSOLE = 0x00000010
#定义函数CreateProcessA()所需的结构体
class STARTUPINFO(Structure):
_fields_ = [
("cb", DWORD),
("lpReserved", LPTSTR),
("lpDesktop", LPTSTR),
("lpTitle", LPTSTR),
("dwX", DWORD),
("dwY", DWORD),
("dwXSize", DWORD),
("dwYSize", DWORD),
("dwXCountChars", DWORD),
("dwYCountChars", DWORD),
("dwFillAttribute", DWORD),
("dwFlags", DWORD),
("wShowWindow", WORD),
("cbReserved2", WORD),
("lpReserved2", LPBYTE),
("hStdInput", HANDLE),
("hStdOutput", HANDLE),
("hStdError", HANDLE),
]
class PROCESS_INFORMATION(Structure):
_fields_ = [
("hProcess", HANDLE),
("hThread", HANDLE),
("dwProcessId", DWORD),
("dwThreadId", DWORD),
]
my_debugger.py
#__author__ = 'zt'
#coding=utf-8
from ctypes import *
from my_debugger_defines import *
kernel32 = windll.kernel32
class debugger():
def __init__(self):
pass
def load(self,path_to_exe):
#参数dwCreationFlags中的标志位控制着进程的创建方式。你若希望新创建的进程独占一个新的控制台窗口,而不是与父进程
#共用同一个控制台,你可以加上标志位CREATE_NEW_CONSOLE creation_flags = DEBUG_PROCESS
creation_flags = DEBUG_RPOCESS
#实例化之前定义的结构体
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()
#在以下两个成员变量的共同作用下,新建进程将在一个单独的窗体中被显示,你可以通过改变结构体STARTUPINFO中的各成员
#变量的值来控制debugee进程的行为。
startupinfo.dwFlags = 0x1
startupinfo.wShowWindow = 0x0
#设置结构体STARTUPINFO中的成员变量
#cb的值,用以表示结构体本身的大小
startupinfo.cb = sizeof(startupinfo)
if kernel32.CreateProcessA(
path_to_exe,
None,
None,
None,
None,
creation_flags,
None,
None,
byref(startupinfo),
byref(process_information)
):
print "[*] We have successfully lauched the process!"
print "[*] PID: %d" % process_information.dwProcessId
else:
print "[*] Error: 0x%08x." % kernel32.GetLastError()
my_test.py
__author__ = 'zt'
import my_debugger
debugger = my_debugger.debugger()
debugger.load("C:\\WINDOWS\\system32\\calc.exe")