一、为了对一个进程进行调试,你必须手写用一些方法把调试器和进程链接起来。所以我们的调试器可以有两种:
(1)装载一个可执行程序然后运行它
(2)动态的附加到一个运行的进程。
优点:
(1)在于他能在程序运行任何代码之前完全的控制程序,这对分析病毒或恶意代码很有用。
(2)附加到一个进程,它允许你跳过启动部分的代码,分析你感兴趣的代码,你分析的就是程序执行的地方
二、方法(1)、首先在windows上创建一个进程用CreateProcessA()函数。需要将特定的标志传进这个函数,使得目标进程能够调试。
BOOL WINAPI CreateProcessA(
LPCSTR lpApplicationName,需要执行的程序的路径
LPTSTR lpCommandLine,我们希望传递给程序的参数
,,,
,,,
,,,
DWORD dwCreationFlags,接受一个特定的值,表示我们希望程序以被调试的状态启动
,,,
LPSTARTUPINFO lpStartupInfo,该结构用来在创建子进程时设置各种属性
LPPROCESS_INFORMATION lpProcessInformation)该结构用来在进程创建后接受相关信息。
建立3个文件。my_debugger_defines1.py用于存放常量,结构体等。my_debugger1.py用于存放程序代码。my_test1.py用于测试
my_debugger_defines1.py
#-*-coding:utf-8-*-
from ctypes import *
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
#常量
DEBUG_PROCESS = 0x00000001#与父进程公用一个控制台(以子进程的方式运行)
CREATE_NEW_CONSOLE = 0x00000010#独占一个控制台(以单独的进程运行)
#结构体
class STARTUPINFO(Structure):
_fields_ = [
("cb",DWORD),
("lpReserved",LPTSTR),
("lpTitle",LPTSTR),
("dwX",DWORD),
("dwY",DWORD),
("dwXSize",DWORD),
("dwYSize",DWORD),
("dwXCountChars",DWORD),
("dwYCountChars",DWORD),
("dwFillAttribute",DWORD),
("dwFlags",DWORD),
("wShowWindow",WORD),
("cbReserved2",WORD),
("lpReserved2",WORD),
("hStdInput",HANDLE),
("hStdOutput",HANDLE),
("hStdError",HANDLE),
]
class PROCESS_INFORMATION(Structure):
_fields_ = [
("hProcess",HANDLE),
("hThread",HANDLE),
("dwProcessId",DWORD),
("dwThreadId",DWORD),
]
my_debugger1.py
#-*-coding:utf-8-*-
from ctypes import *
from my_debugger_defines1 import *
kernel32 = windll.kernel32
class debugger():
def __init__(self):
pass
def load(self,path_to_exe):
creation_flags = DEBUG_PROCESS
#初始化结构体
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()
#the following two options allow the started process to be shown as a separate window
#this also illustrates how different settings in the STARTUPINFO struct can affect the debuggee.
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 launched the process!"
print "[*]PID:%d"%process_information.dwProcessId
else:
print "[*]Error:0x%08x."%kernel32.GetLastError()
my_test1.py
#-*-coding:utf-8-*-
import my_debugger1
debugger = my_debugger1.debugger()
debugger.load("C:\\Windows\\SysWOW64\\calc.exe")
运行结果:
哦也~成功了~
方法(2) 1、为了附加到指定进程,必须首先得到他的句柄,用OpenProcess(),有kernel32.dll导出。
HANDLE WINAPI OpenProcess(
DWORD dwDesireAccess,决定了我们对打开的进程拥有什么权限,PROCESS_ALL_ACCESS
BOOL bInheitHandle, false
DWORD dwProcessId,句柄的ID
);
#1获取进程的句柄
def open_process(self,pid):
h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,pid)#权限,False,进程id
return h_process
2、接下来用DebugActiveProcess()函数附加到目标进程:
BOOL WINAPI DebugActiveProcess(
DWORD dwProcessId
);
def attach(self,pid):
self.h_process = self.open_process(pid)
#2用DebugActiveProcess()函数附加到进程
if kernel32.DebugActiveProcess(pid):
self.debugger_active = True
self.pid = pid
#self.run()
else:
print "[*]Unable to attach to process."
3、调试器循环调用WaitForDebugEvent()以便俘获调试事件。
BOOL WINAPI WaitForDebugEvent(
LPDEBUG_EVENT lpDebugEvent,#该结构体描述一个调试事件
DWORD dwMilliseconds,#设为无限等待
)
4、调试器捕捉的每一个事件都有相关的事件处理函数进行处理,
5、当处理函数完成了操作,我们希望进程继续执行用ContinueDebugEvent()
BOOL WINAPI ContinueDebugEvent(
DWORD dwProcessId,
DWORD dwThreadId,
DWORD dwContinueStatus #DBG_CONTINUE, DBG_EXCEPTION_NOT_HANDLED
);
6、从进程分离出来:把进程ID传递给DebugActiveProcessStop()
def detach(self):
#5进程分离,把进程id传递给DebugActiveProcessStop()
if kernel32.DebugActiveProcessStop(self.pid):
print "[*]Finished debugging.Exiting..."
return True
else:
print "There was an error"
return False
my_debugger_defines1.py
#-*-coding:utf-8-*-
from ctypes import *
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
##############
PVOID = c_void_p
ULONG_PTR =c_ulong
#常量
DEBUG_PROCESS = 0x00000001#与父进程公用一个控制台(以子进程的方式运行)
CREATE_NEW_CONSOLE = 0x00000010#独占一个控制台(以单独的进程运行)
################
PROCESS_ALL_ACCESS = 0x001F0FFF
INFINITE = 0xFFFFFFFF
DBG_CONTINUE = 0x00010002
#结构体
class STARTUPINFO(Structure):
_fields_ = [
("cb",DWORD),
("lpReserved",LPTSTR),
("lpTitle",LPTSTR),
("dwX",DWORD),
("dwY",DWORD),
("dwXSize",DWORD),