二、纯 python 实现一个调试器

本文介绍了如何使用Python实现一个调试器,包括创建子进程和附加到现有进程。通过CreateProcessA函数创建子进程,并通过OpenProcess、DebugActiveProcess等API实现对现有进程的调试。调试过程中涉及调试事件的处理和权限的传递。

要想调试一个程序, 就需要与目标程序建立某种联系, 为此, 我们的调试器应该具备两种基本能力:

  • 打开一个程序, 并使它以自身子进程的形式运行起来
  • 附加到一个正在进去的程序上

1. 创建子进程

使用 CreateProcessA() 来实现就可以了.
这个函数其实已经很熟悉了, 回顾一下吧:

BOOL CreateProcess (
    LPCTSTR lpApplicationName, // 程序路径
    LPTSTR lpCommandLine, // 命令行参数
    LPSECURITY_ATTRIBUTES lpProcessAttributes。
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles,
    DWORD dwCreationFlags, // 创建的标志
    LPVOID lpEnvironment,
    LPCTSTR lpCurrentDirectory,
    LPSTARTUPINFO lpStartupInfo, // 指向一个用于决定新进程的主窗体如何显示的 STARTUPINFO 结构体
    LPPROCESS_INFORMATION lpProcessInformation // 指向一个用来接收新进程的识别信息的 PROCESS_INFORMATION 结构体
);

基本上, 我们只要关心 lpApplicationName、lpCommandLine、dwCreationFlags、lpStartupInfo 和 lpProcessInformation 这五个参数, 其它的设为 NULL即可.
其中通过给 dwCreationFlags 参数设定一个指定的值, 那么跑起来的程序就有了可调试权限.

现在我们来通过 python 来运行一个新进程.
首先新建两个 py 文件: my_debugger.py 和 my_debugger_defines.py
my_debugger_defines.py 保存的是程序常量及结构定义的地方.
my_debugger.py 是核心代码实现的地方.
先来定义我们程序所需要的数据结构:

# -*- coding: utf-8 -*-
from ctypes import *

# 统一命名风格
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPSTR = c_char_p
LPWSTR = c_wchar_p
HANDLE = c_void_p

DEBUG_PROCESS = 0x00000001 # 与父进程共用一个控制台(以子进程的方式运行)
CREATE_NEW_CONSOLE = 0x00000010 # 独占一个新控制台(以单独的进程运行)

# 定义 CreateProcessA() 所需的结构体
class STARTUPINFOA(Structure):
    _fields_ = [
        ('cb', DWORD),
        ('lpReserved', LPSTR),
        ('lpDesktop', LPSTR),
        ('lpTitle', LPSTR),
        ('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_INFORMATIONA(Structure):
    _fields_ = [
        ('hProcess', HANDLE),
        ('hThread', HANDLE),
        ('dwProcessId', DWORD),
        ('dwThreadId', DWORD),
    ]

再来书写核心代码:

# -*- coding: utf-8 -*-
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值