系统win10,python3.6,编码软件vscode
接着源码一的写
直接上代码
my_debugger_defines.py文件需要添加常量和结构体
from ctypes import *
# 为了清晰起见,让我们将Microsoft类型映射到ctypes
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
# 常量
PROCESS_ALL_ACCESS = 0x001F0FFF
INFINITE = 0xFFFFFFFF
DBG_CONTINUE = 0x00010002
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),
]
class EXCEPTION_RECORD(Structure):
pass
EXCEPTION_RECORD._fields_ = [#这里之所以要这么设计,是因为ExceptionRecode调用了EXCEPTION_RECORD
("ExceptionCode",DWORD),
("ExceptionFlags",DWORD),
("ExceptionRecord",POINTER(EXCEPTION_RECORD)),
("ExceptionAddress",PVOID),
("NumberParameters",DWORD),
("ExceptionInfomation",ULONG_PTR * 15),
]
class EXCEPTION_DEBUG_INFO(Structure):
_fields_ = [
("ExceptionRecord",EXCEPTION_RECORD),
('dwFistChance',DWORD),
]
class DEBUG_EVENT_UNION(Union):
_fields_ = [
("Exception",EXCEPTION_DEBUG_INFO),
# ("CreateThread",CREATE_THREAD_DEBUG_INFO),
# ("CreateProcessInfo",CREATE_PROCESS_DEBUG_INFO),
# ("ExitThread",EXIT_THREAD_DEBUG_INFO),
# ("ExitProcess",EXIT_PROCESS_DEBUG_INFO),
# ("LoadDll",LOAD_DLL_DEBUG_INFO),
# ("UnloadDll",UNLOAD_DLL_DEBUG_INFO),
# ("DebugString",OUTPUT_DEBUG_INFO),
# ("RipInfo",RIP_INFO),
]
class DEBUG_EVENT(Structure):#定义DEBUG_EVENT处理事件
_fields_ = [
("dwDebugEventCode",DWORD),#调试事件类型
("dwProcessId",DWORD),
("dwThreadId",DWORD),
("u",DEBUG_EVENT_UNION),
]
my_debugger.py文件添加些方法 和属性
from ctypes import *
from my_debugger_defines import *
kernel32 = windll.kernel32
class debugger():
def __init__(self):
self.h_process = None # 进程句柄
self.pid = None # 进程pid
self.debugger_active = False # 进程活跃状态
pass
def load(self,path_to_exe):
creation_flags = DEBUG_PROCESS
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()
startupinfo.dwFlags = 0x1
startupinfo.wShowWindow = 0x0
startupinfo.cb=sizeof(startupinfo)
if kernel32.CreateProcessA(path_to_exe,
None,
None,
None,
None,
creation_flags,
None,
None,
byref(startupinfo),
byref(process_information)):
print("[*] 我们成功启动目标程序!")
print("[*] PID:%d"%process_information.dwProcessId)
else:
print("[*] Error:0x%08x."%kernel32.GetLastError())
def open_process(self,pid):
"""
打开进程权限
:param pid 进程pid
return 进程句柄
"""
h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS,pid,False)
return h_process
def attach(self,pid):
"""
附加程序
"""
self.h_process = self.open_process(pid)
# 试图附加到目标程序,若附加操作失败
# 则在输出提示信息后返回
if kernel32.DebugActiveProcess(pid):
self.debugger_active = True
self.pid = int(pid)
self.run()
else:
print("[*] 错误码:0x%08x." % kernel32.GetLastError())
print("[*] 无法附加到进程.")
def run(self):
"""
不断轮询调试事件
"""
# 我们等待发生在debug进程中的调试事件
while self.debugger_active == True:
self.get_debug_event()
def get_debug_event(self):
"""
获得调试事件
"""
debug_event = DEBUG_EVENT()
continue_status = DBG_CONTINUE
if kernel32.WaitForDebugEvent(byref(debug_event),INFINITE):
# 我们现在不打算构建任何处理程序
# 这里简单的操作就可以恢复执行目标进程
input("按下任意键....")
self.debugger_active = False
kernel32.ContinueDebugEvent(\
debug_event.dwProcessId,\
debug_event.dwThreadId,\
continue_status)
def detach(self):
"""
停止调试
"""
if kernel32.DebugActiveProcessStop(self.pid):
print("[*] 完成调试,退出....")
return True
else:
print("这里有一个错误")
return False
最后测试文件my_test.py
from my_debugger import debugger
debugger = debugger()
pid = input("输入需要依附的程序的pid:")
debugger.attach(int(pid))
debugger.detach()
这里我们都是测试win自带的计算器,在c:\windows\system32里面,当然也可以用其他软件,我试过效果都一样,我运行这代码之后,计算器就不能点击了,就好像定住了一样不能操作,在控制台按下任意键之后又会恢复正常,整个流程就这样,关于那些结构体,常量以及win32api函数还是那句话,到Google搜就好了,还有些细节等估计我不太会讲,看书是最实在的。