10.0 探索API调试事件原理

简介: 本章笔者将通过`Windows`平台下自带的调试API接口实现对特定进程的动态转存功能,首先简单介绍一下关于调试事件的相关信息,调试事件的建立需要依赖于`DEBUG_EVENT`这个特有的数据结构,该结构用于向调试器报告调试事件。当一个程序发生异常事件或者被调试器附加时,就会产生对应的`DEBUG_EVENT`调试事件,通常`DEBUG_EVENT`包含了多种调试类型,包括异常事件、进程创建事件、线程创建事件、进程退出事件和线程退出事件等等,我们只需要动态捕捉这些调试事件并作相应的处理即可实现更多有用的功能。
+关注继续查看

本章笔者将通过Windows平台下自带的调试API接口实现对特定进程的动态转存功能,首先简单介绍一下关于调试事件的相关信息,调试事件的建立需要依赖于DEBUG_EVENT这个特有的数据结构,该结构用于向调试器报告调试事件。当一个程序发生异常事件或者被调试器附加时,就会产生对应的DEBUG_EVENT调试事件,通常DEBUG_EVENT包含了多种调试类型,包括异常事件、进程创建事件、线程创建事件、进程退出事件和线程退出事件等等,我们只需要动态捕捉这些调试事件并作相应的处理即可实现更多有用的功能。

调试事件通常可以分为如下几种类型;

  • 异常事件 (Exception Event) - 发生了异常,例如访问非法的内存、除以零或调用了无效的函数。
  • 进程创建事件 (Process Creation Event) - 当一个新进程被创建时发送此事件。
  • 进程退出事件 (Process Exit Event) - 当一个进程退出时发送此事件。
  • 线程创建事件 (Thread Creation Event) - 当一个新线程被创建时发送此事件。
  • 线程退出事件 (Thread Exit Event) - 当一个线程退出时发送此事件。
  • 调试字符串事件 (Debug String Event) - 当一个进程向其调试器发送字符串消息时发送此事件。
  • 输出字符串事件 (Output String Event) - 当输出调试字符串时发送此事件。
  • 动态链接库加载事件(LOAD_DLL_DEBUG_EVENT) - 当进程装载 DLL 时发送此事件。

当我们需要调试一个程序时有两种方式可以实现,第一种方式是通过CreateProcess()函数创建一个进程,并在调用函数时指定DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS则当程序被运行起来后自动进入到调试状态,另一种方式则是通过DebugActiveProcess()函数,该函数接受一个正在运行的进程PID号,可动态附加到一个已运行程序上而对其进行调试。

一旦调试器通过CreateProcess()附加并运行,下一步则是通过WaitForDebugEvent()用于等待一个调试事件,当有调试事件到达后系统会将调试类型存储到debugEvent.dwDebugEventCode这个变量内,此时我们可以通过判断该变量内的参数来对特定的事件做出自定义处理操作,接着会通过ContinueDebugEvent()继续等待下一个调试事件的到来,我们以打开一个进程并创建调试为例,看一下如下代码片段;

#include <iostream>
#include <windows.h>

int main(int argc, char* argv[])
{
    DEBUG_EVENT debugEvent = { 0 };
    BOOL bRet = TRUE;

    // 创建调试进程
    STARTUPINFO startupInfo = { 0 };
    PROCESS_INFORMATION pInfo = { 0 };
    GetStartupInfo(&startupInfo);

    // 创建调试进程并设置 DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS 调试事件
    bRet = CreateProcess("d://lyshark.exe", NULL, NULL, NULL, TRUE, DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &startupInfo, &pInfo);
    if (!bRet)
    {
        return 0;
    }

    // 附加调试进程
    // DebugActiveProcess(13940)

    // 无限循环等待调试事件
    while (WaitForDebugEvent(&debugEvent, INFINITE))
    {
        // 根据调试事件判断
        switch (debugEvent.dwDebugEventCode)
        {
            // 异常调试事件
        case EXCEPTION_DEBUG_EVENT:
            printf("异常处理事件 \n");
            break;

            // 线程创建调试事件
        case CREATE_THREAD_DEBUG_EVENT:
            printf("线程创建调试事件 \n");
            break;
            // 进程创建调试事件
        case CREATE_PROCESS_DEBUG_EVENT:
            printf("进程创建调试事件 \n");
            break;
            // 线程退出调试事件
        case EXIT_THREAD_DEBUG_EVENT:
            printf("线程退出调试事件 \n");
            break;
            // 进程退出调试事件
        case EXIT_PROCESS_DEBUG_EVENT:
            printf("进程退出调试事件 \n");
            break;
            // 装载DLL调试事件
        case LOAD_DLL_DEBUG_EVENT:
            printf("装载DLL调试事件 \n");
            break;
            // 卸载DLL调试事件
        case UNLOAD_DLL_DEBUG_EVENT:
            printf("卸载DLL调试事件 \n");
            break;
            // 输出调试信息事件
        case OUTPUT_DEBUG_STRING_EVENT:
            printf("输出调试信息事件 \n");
            break;
        }

        // 使调试器能够继续以前报告调试事件的线程
        bRet = ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
    }

    system("pause");
    return 0;
}

当编译并运行上述程序后,读者应该能看到如下图所示的输出效果,其中包括了各类调试事件被触发时的提示信息,由于在调试事件内没有做任何操作,程序在加载后就被自动运行起来了;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/b8eecce4.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章
|
1月前
|
JSON 测试技术 API
API接口:原理、实现及应用
API接口:原理、实现及应用
37 1
|
2月前
|
XML JavaScript API
API接口:原理、设计与应用
API,全称应用程序接口,是一些预先定义的函数,目的是提供应用程序与开发人员以访问一组例程的能力,我们可以在不暴露各内部例程的情况下,使用这些例程。API是构建在操作系统或应用程序之间的接口,它充当一个桥梁或纽带,使得不同的应用程序或系统之间可以相互交流和交互。
|
4月前
|
存储 JSON 移动开发
react16常见api以及原理剖析
react16常见api以及原理剖析
46 0
|
6月前
|
设计模式 API
「深入了解API:从原理到实践」
API比喻成有机体中的神经元,它们将不同系统之间的信息传递和处理集合起来,消除了沟通的困难和技术上的限制。API可以使软件开发人员将应用程序组件直接连接在配有操作系统的系统或技术下。借助API,我们可以创建一个强大、协调一致的应用程序,满足广泛的需求。
42 0
|
6月前
|
安全 API
"深入理解API:从原理到实践"
本文将介绍从原理到实践中API的全面理解。首先,我们将对API的概念和作用进行介绍,同时解释API与Web服务的区别。接下来,我们将深入研究如何设计API,包括如何选择API类型、规范API请求和响应格式、以及如何保证API的可靠性。此外,我们还讨论了API的安全性问题,并提供了一些实用的建议,以保护API免受攻击。
34 0
|
6月前
|
XML JSON API
深入理解API:从原理到实践的完整指南"
API,或称为应用程序编程接口,是现代软件开发中不可或缺的一部分。简单来说,API是两个软件应用程序之间通信的桥梁,它允许应用程序之间交换数据和服务而不必了解彼此的实现细节。
61 0
|
6月前
|
XML 算法 Java
API调用原理说明
API调用原理说明
63 0
|
7月前
|
存储 Kubernetes Cloud Native
带你读《云原生应用开发:Operator原理与实践》——2.3.1 Kubernetes API 访问控制
带你读《云原生应用开发:Operator原理与实践》——2.3.1 Kubernetes API 访问控制
|
7月前
|
API
zookeeper入门到精通07——zookeeper客户端API节点操作与原理
zookeeper入门到精通07——zookeeper客户端API节点操作与原理
|
7月前
|
机器学习/深度学习 存储 并行计算
网格搜索的原理以及实战以及相关API(GridSearchCV)
网格搜索的原理以及实战以及相关API(GridSearchCV)
热门文章
最新文章
相关产品
云迁移中心
推荐文章
更多