python灰帽子--自己动手写调试器

一、为了对一个进程进行调试,你必须手写用一些方法把调试器和进程链接起来。所以我们的调试器可以有两种:
     (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),
   
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值