• debuger!


      1 #include <windows.h>
      2 #include <string>
      3 #include <iostream>
      4 
      5 using namespace std;
      6 
      7 /*先声明一些Debug消息处理函数供调用*/
      8 void OnProcessCreated(const CREATE_PROCESS_DEBUG_INFO*);
      9 void OnThreadCreated(const CREATE_THREAD_DEBUG_INFO*);
     10 void OnException(const EXCEPTION_DEBUG_INFO*);
     11 void OnProcessExited(const EXIT_PROCESS_DEBUG_INFO*);
     12 void OnThreadExited(const EXIT_THREAD_DEBUG_INFO*);
     13 void OnOutputDebugString(const OUTPUT_DEBUG_STRING_INFO*);
     14 void OnRipEvent(const RIP_INFO*);
     15 void OnDllLoaded(const LOAD_DLL_DEBUG_INFO*);
     16 void OnDllUnloaded(const UNLOAD_DLL_DEBUG_INFO*);
     17 
     18 
     19 void main()
     20 {
     21     //定义两个结构供api填值
     22     STARTUPINFO    si={0};
     23     
     24     PROCESS_INFORMATION pi = { 0 };
     25     
     26     if (!CreateProcess(
     27         TEXT("C:\windows\notepad.exe"), //打开的程序名称,这里用TEXT宏包含了一下
     28         NULL,
     29         NULL,
     30         NULL,
     31         FALSE,
     32         DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,//只调试当前进程
     33         NULL,
     34         NULL,    //当前目录
     35         &si,    //启动信息
     36         &pi))    //进程信息
     37     {
     38         std::cout<<GetLastError()<<endl;
     39         return;
     40     }
     41     
     42     BOOL waitEvent = TRUE;
     43     
     44     DEBUG_EVENT debugEvent;
     45     while (waitEvent == TRUE && WaitForDebugEvent(&debugEvent, INFINITE)) {
     46         //WaitForDebugEvent接收OS的调试消息事件
     47         switch (debugEvent.dwDebugEventCode) {
     48             
     49         case CREATE_PROCESS_DEBUG_EVENT:
     50             OnProcessCreated(&debugEvent.u.CreateProcessInfo);
     51             break;
     52             
     53         case CREATE_THREAD_DEBUG_EVENT:
     54             OnThreadCreated(&debugEvent.u.CreateThread);
     55             break;
     56             
     57         case EXCEPTION_DEBUG_EVENT:
     58             OnException(&debugEvent.u.Exception);
     59             break;
     60             
     61         case EXIT_PROCESS_DEBUG_EVENT:
     62             OnProcessExited(&debugEvent.u.ExitProcess);
     63 //要注意这里是如何退出循环的:引入一个BOOL类型的waitEvent变量,在处理EXIT_PROCESS_DEBUG_EVENT之后将它的值改成FALSE
     64             waitEvent = FALSE;
     65             break;
     66             
     67         case EXIT_THREAD_DEBUG_EVENT:
     68             OnThreadExited(&debugEvent.u.ExitThread);
     69             break;
     70             
     71         case LOAD_DLL_DEBUG_EVENT:
     72             OnDllLoaded(&debugEvent.u.LoadDll);
     73             break;
     74             
     75         case UNLOAD_DLL_DEBUG_EVENT:
     76             OnDllUnloaded(&debugEvent.u.UnloadDll);
     77             break;
     78             
     79         case OUTPUT_DEBUG_STRING_EVENT:
     80             OnOutputDebugString(&debugEvent.u.DebugString);
     81             break;
     82             
     83         case RIP_EVENT:
     84             OnRipEvent(&debugEvent.u.RipInfo);
     85             break;
     86             
     87         default:
     88             std::cout << TEXT("Unknown debug event.") << std::endl;
     89             break;
     90         }
     91         
     92         if (waitEvent == TRUE) {
     93             ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
     94         }
     95         else {
     96             break;//waitEvent != TRUE 时退出循环
     97         }
     98     }
     99 
    100 }
    101 
    102 void OnProcessCreated(const CREATE_PROCESS_DEBUG_INFO* pInfo) {
    103     
    104     std::cout<<TEXT("Debuggee was created.")<<endl;
    105 }
    106 
    107 
    108 
    109 void OnThreadCreated(const CREATE_THREAD_DEBUG_INFO* pInfo) {
    110     
    111     std::cout<<TEXT("A new thread was created.")<<endl;
    112 }
    113 
    114 
    115 
    116 void OnException(const EXCEPTION_DEBUG_INFO* pInfo) {
    117     
    118     std::cout<< TEXT("An exception was occured.")<<endl;
    119 }
    120 
    121 
    122 
    123 void OnProcessExited(const EXIT_PROCESS_DEBUG_INFO* pInfo) {
    124     
    125     std::cout<<TEXT("Debuggee was terminated.")<<endl;
    126 }
    127 
    128 
    129 
    130 void OnThreadExited(const EXIT_THREAD_DEBUG_INFO* pInfo) {
    131     
    132     std::cout<<TEXT("A thread was terminated.")<<endl;
    133 }
    134 
    135 
    136 
    137 void OnOutputDebugString(const OUTPUT_DEBUG_STRING_INFO* pInfo) {
    138     
    139     std::cout<<TEXT("Debuggee outputed debug string.")<<endl;
    140 }
    141 
    142 
    143 
    144 void OnRipEvent(const RIP_INFO* pInfo) {
    145     
    146     std::cout<<TEXT("A RIP_EVENT occured.")<<endl;
    147 }
    148 
    149 
    150 
    151 void OnDllLoaded(const LOAD_DLL_DEBUG_INFO* pInfo) {
    152     
    153     std::cout<<TEXT("A dll was loaded.")<<endl;
    154 }
    155 
    156 
    157 
    158 void OnDllUnloaded(const UNLOAD_DLL_DEBUG_INFO* pInfo) {
    159     
    160     std::cout<<TEXT("A dll was unloaded.")<<endl;
    161 }
    typedef struct _DEBUG_EVENT {
      DWORD dwDebugEventCode;        //从这确定union联合域内是什么内容
      DWORD dwProcessId;           //PID
      DWORD dwThreadId;            //线程ID
      union {
        EXCEPTION_DEBUG_INFO Exception;  
        CREATE_THREAD_DEBUG_INFO CreateThread;
        CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
        EXIT_THREAD_DEBUG_INFO ExitThread;
        EXIT_PROCESS_DEBUG_INFO ExitProcess;
        LOAD_DLL_DEBUG_INFO LoadDll;
        UNLOAD_DLL_DEBUG_INFO UnloadDll;
        OUTPUT_DEBUG_STRING_INFO DebugString;
        RIP_INFO RipInfo;
      } u;
    } DEBUG_EVENT, 
     *LPDEBUG_EVENT;
    //然后从各种event_info_struct中取得调试信息

     --各种事件的处理--------------------------------------

    RIP_EVENT

    关于这种调试事件的文档资料非常少,只要输出一条信息或者干脆忽略它即可。

    OUTPUT_DEBUG_STRING_EVENT

    被调试进程调用OutputDebugString()时就会引发该类调试事件,OUTPUT_DEBUG_STRING_INFO结构体描述了关于该事件的详细信息。

    typedef struct _OUTPUT_DEBUG_STRING_INFO {
      LPSTR lpDebugStringData;    //字符串在被调试进程的进程空间内的地址
      WORD  fUnicode;              //是否Unicode编码
      WORD  nDebugStringLength;    //以字符为单位的字符串的长度
    } OUTPUT_DEBUG_STRING_INFO, *LPOUTPUT_DEBUG_STRING_INFO;
        

    字符串是在被调试进程的地址空间内,我们就要使用ReadProcessMemory函数读取这个字符串。下面的代码展示了这个过程:

    void OnOutputDebugString(const OUTPUT_DEBUG_STRING_INFO* pInfo) {
        
        BYTE* pBuffer = (BYTE*)malloc(pInfo->nDebugStringLength);//申请的大小刚好
        
        SIZE_T bytesRead;    //读取的字数
        
        ReadProcessMemory(    //读入buffer
            g_hProcess,    //g_hProcess==pi.hProcess;
            pInfo->lpDebugStringData,
            pBuffer, 
            pInfo->nDebugStringLength,
            &bytesRead);
        
        std::cout << TEXT("Debugger debug string: ") << pBuffer <<  std::endl;
        
        free(pBuffer);
    }

    ----------------读取寄存器和内存(OD的寄存器窗口和数据窗口)--------------------

    获取寄存器的值

    每个线程都有一个上下文环境(context),它包含了有关线程的大部分信息,例如线程栈的地址,线程当前正在执行的指令地址等。上下文环境保存在寄存器中,系统进行线程调度的时候会发生上下文切换,实际上就是将一个线程的上下文环境保存到内存中,然后将另一个线程的上下文环境装入寄存器。

    在实际上下文中谈CONTEXT结构
    CONTEXT结构包括以下部分:
    
       CONTEXT_CONTROL:包含CPU的控制寄存器,比如指今指针,堆栈指针,标志和函数返回地址..AX, BX, CX, DX, SI, DI
         CONTEXT_INTEGER:用于标识CPU的整数寄存器.DS, ES, FS, GS
       CONTEXT_FLOATING_POINT:用于标识CPU的浮点寄存器.
         CONTEXT_SEGMENTS:用于标识CPU的段寄存器.SS:SP, CS:IP, FLAGS, BP
       CONTEXT_DEBUG_REGISTER:用于标识CPU的调试寄存器.  
       CONTEXT_EXTENDED_REGISTERS:用于标识CPU的扩展寄存器I
       CONTEXT_FULL:相当于CONTEXT_CONTROL or CONTEXT_INTEGER or   CONTEXT_SEGMENTS,即这三个标志的组合
    
    我们可以使用GetThreadContext函数来查看线程内核对象的内部,并获取当前CPU寄存器状态的集合。
    
    BOOL GetThreadContext (
    
    HANDLE  hThread,
    
    PCONTEXT  pContext);
    
    若要调用该函数,只需指定一个CONTEXT结构,对某些标志(该结构的ContextFlags成员)进行初始化,指明想要收回哪些寄存器,并将该结构的地址传递给GetThreadContext 。然后该函数将数据填入你要求的成员。
    
    在调用GetThreadContext函数之前,应该调用SuspendThread,否则,线程可能刚好被调度,这样一来,线程的上下文就和所获取的信息不一致了。
    
    示例代码如下: 
    
             CONTEXT Context;                  //定义一个CONTEXT结构
    
             Context.ContextFlags = CONTEXT_CONTROL;    //告诉系统我们想获取线程控制寄存器的内容   
    
             GetThreadContext(hThread, &Context);      //调用GetThreadContext获取相关信息
    
    Ps:在调用GetThreadContext函数之前,必须首先初始化CONTEXT结构的ContextFlags成员。
    
    要获得线程的所有重要的寄存器(也就是微软认为最常用的寄存器),应该像下面一样初始化ContextFlags:
    
    Context.ContextFlags = CONTEXT_FULL;
    
    在WinNT. h头文件中,定义了CONTEXT_FULL为CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS。
    
    当然,我们还可以通过调用SetThreadContext函数来改变结构中的成员,并把新的寄存器值放回线程的内核对象中
    
    BOOL SetThreadContext (
    
    HANDLE  hThread,
    
    CONST CONTEXT  *pContext);
    
    同样,如果要改变哪个线程的上下文,应该先暂停该线程。       
    
             CONTEXT Context;      //定义一个CONTEXT结构      
    
             SuspendThread(hThread);  //挂起线程  
    
             Context.ContextFlags = CONTEXT_CONTROL;   //获取当前上下文的值
    
             GetThreadContext(hThread, &Context);
    
             Context.Eip = 0x00010000;      //Eip字段存储的是指令指针,现在让指令指针指向地址 0x00010000;
    
             Context.ContextFlags = CONTEXT_CONTROL;
    
             SetThreadContext(hThread, &Context);   //重新设置线程上下文
    
             ResumeThread(hThread);         //恢复线程,现在线程开始从0x00010000这个地方开始执行指令
  • 相关阅读:
    基于php缓存的详解
    Nginx 的 Location 配置指令块
    Nginx负载均衡与反向代理的配置实例
    Linux下mysql定时备份及恢复
    KVO的底层实现
    小谈KVC中KeyPath的集合运算符
    iOS开发中常用的单例
    内存中的5大区域
    需要记住的几个ASCII码
    结构体-内存对齐
  • 原文地址:https://www.cnblogs.com/Rrouned/p/3418140.html
Copyright © 2020-2023  润新知