《python灰帽子》源码二,调试器与被调试程序分离(可附加和脱离)

系统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搜就好了,还有些细节等估计我不太会讲,看书是最实在的。

猜你喜欢

转载自blog.csdn.net/qq_41738613/article/details/83189050