zoukankan      html  css  js  c++  java
  • Debug Hook

    • 命名

      关于这个命名是我自己这样说的,至于这种HOOK技术,先前在一个开源项目中叫做RemoteHook,我比较喜欢自己的这种命名,所以就叫Debug Hook。如果有错误,请指出。

    • 先来说说调试的原理

      在Windows操作系统,有两种方法可以来调试一个进程。

      1: CreateProcess()

      可以使用此函数来启动调试一个进程。

      CreateProcess(FileFullPath,NULL,NULL,NULL, false,DEBUG_PROCESS         |DEBUG_ONLY_THIS_PROCESS| CREATE_NEW_CONSOLE,
      NULL,NULL,&StartupInfo,&ProcessInfo) 
          

      2:DebugActiveProcess(ProcessID)

       可以使用此函数来附加到一个进程来进行调试。

      我们使用以上两种方法中的任何一种方法来调试一个进程,每当被调试进程发生调试事件的时候,OS都会暂停其运行。并向调试器报告相应的事件,调试器处理之后就可以继续运行。

    • 利用调试技术来HOOK API函数的相关步骤如下

      利用调试技术来HOOK API函数的相关步骤如下

      1对想要钩取的进程进行附加操作,使之成为被调试者。

      2将要钩取的API的起始地址的第一个字节修改为0xcc(或者使用硬件断点)。

      3当调用目标API的时候,控制权就转移到调试器进程。

      4执行需要的操作。

      5脱钩,将API 函数的第一个字节恢复。

      6运行相应的API。

        1 #include<Windows.h>
        2 #include<iostream>
        3 #include<stdio.h>
        4 
        5 using namespace std;
        6 
        7 LPVOID WriteFileAddress = NULL;
        8 CREATE_PROCESS_DEBUG_INFO CreateProcessDebugInfomation;
        9 BYTE INT3 = 0xCC, OldByte = 0;
       10 
       11 BOOL OnCreateProcessDebugEvent(LPDEBUG_EVENT pde)
       12 {
       13     // WriteFile()函数地址
       14     WriteFileAddress = GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile");
       15 
       16     // API Hook - WriteFile()
       17     //将WriteFile函数的首个字节改为0xcc
       18     memcpy(&CreateProcessDebugInfomation, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO));
       19     ReadProcessMemory(CreateProcessDebugInfomation.hProcess, WriteFileAddress,
       20                       &OldByte, sizeof(BYTE), NULL);
       21     WriteProcessMemory(CreateProcessDebugInfomation.hProcess, WriteFileAddress,
       22                        &INT3, sizeof(BYTE), NULL);
       23 
       24     return TRUE;
       25 }
       26 
       27 BOOL OnExceptionDebugEvent(LPDEBUG_EVENT pDebugEvent)
       28 {
       29     CONTEXT Context;
       30     PBYTE lpBuffer = NULL;
       31     DWORD dwNumOfBytesToWrite, dwAddrOfBuffer, i;
       32     PEXCEPTION_RECORD pExceptionRecord = &pDebugEvent->u.Exception.ExceptionRecord;
       33 
       34     // BreakPoint exception 
       35     if( EXCEPTION_BREAKPOINT == pExceptionRecord->ExceptionCode )
       36     {
       37         // 发生异常的地方是否为我们要钩取的函数
       38         if( WriteFileAddress == pExceptionRecord->ExceptionAddress )
       39         {
       40             // #1. Unhook
       41             //   先恢复,以免进入死循环
       42             WriteProcessMemory(CreateProcessDebugInfomation.hProcess, WriteFileAddress,
       43                                &OldByte, sizeof(BYTE), NULL);
       44 
       45             // #2. 获得线程上下背景文  为了修改EIp的值,来使进程恢复正常运行
       46             Context.ContextFlags = CONTEXT_CONTROL;
       47             GetThreadContext(CreateProcessDebugInfomation.hThread, &Context);
       48 
       49             // #3. WriteFile() 根据ESP来获得WriteFile 函数的参数,以达到修改数据的目的
       50            
       51             ReadProcessMemory(CreateProcessDebugInfomation.hProcess, (LPVOID)(Context.Esp + 0x8),
       52                               &dwAddrOfBuffer, sizeof(DWORD), NULL);
       53 
       54             ReadProcessMemory(CreateProcessDebugInfomation.hProcess, (LPVOID)(Context.Esp + 0xC),
       55                               &dwNumOfBytesToWrite, sizeof(DWORD), NULL);
       56 
       57             // #4.
       58             lpBuffer = (PBYTE)malloc(dwNumOfBytesToWrite+1);
       59             memset(lpBuffer, 0, dwNumOfBytesToWrite+1);
       60 
       61             // #5. WriteFile() 
       62             ReadProcessMemory(CreateProcessDebugInfomation.hProcess, (LPVOID)dwAddrOfBuffer,
       63                               lpBuffer, dwNumOfBytesToWrite, NULL);
       64             printf("
      ### original string ###
      %s
      ", lpBuffer);
       65 
       66             // #6. 修改数据
       67             for( i = 0; i < dwNumOfBytesToWrite; i++ )
       68             {
       69                 if( 0x61 <= lpBuffer[i] && lpBuffer[i] <= 0x7A )
       70                     lpBuffer[i] -= 0x20;
       71             }
       72 
       73             printf("
      ### converted string ###
      %s
      ", lpBuffer);
       74 
       75             // #7. 调用原函数
       76             WriteProcessMemory(CreateProcessDebugInfomation.hProcess, (LPVOID)dwAddrOfBuffer,
       77                                lpBuffer, dwNumOfBytesToWrite, NULL);
       78             
       79            
       80             free(lpBuffer);
       81 
       82             // 设置EIP的值来实现正常运行,注意EIP的值为0xcc的下一条指令的地址。
       83             Context.Eip = (DWORD)WriteFileAddress;
       84             SetThreadContext(CreateProcessDebugInfomation.hThread, &Context);
       85 
       86             // 运行
       87             ContinueDebugEvent(pDebugEvent->dwProcessId, pDebugEvent->dwThreadId, DBG_CONTINUE);
       88             Sleep(0);
       89 
       90             // 再次钩取
       91             WriteProcessMemory(CreateProcessDebugInfomation.hProcess, WriteFileAddress,
       92                                &INT3, sizeof(BYTE), NULL);
       93 
       94             return TRUE;
       95         }
       96     }
       97 
       98     return FALSE;
       99 }
      100 
      101 void DebugLoop()
      102 {
      103     DEBUG_EVENT DebugEvent;
      104     DWORD dwContinueStatus;
      105 
      106     // 等待调试事件
      107     while( WaitForDebugEvent(&DebugEvent, INFINITE) )
      108     {
      109         dwContinueStatus = DBG_CONTINUE;
      110 
      111         // 调试事件为创建进程
      112         if( CREATE_PROCESS_DEBUG_EVENT == DebugEvent.dwDebugEventCode )
      113         {
      114             OnCreateProcessDebugEvent(&DebugEvent);
      115         }
      116         // 调试事件
      117         else if( EXCEPTION_DEBUG_EVENT == DebugEvent.dwDebugEventCode )
      118         {
      119             if( OnExceptionDebugEvent(&DebugEvent) )
      120                 continue;
      121         }
      122         // 调试进程退出
      123         else if( EXIT_PROCESS_DEBUG_EVENT == DebugEvent.dwDebugEventCode )
      124         {
      125           
      126             break;
      127         }
      128 
      129       
      130         ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, dwContinueStatus);
      131     }
      132 }
      133 
      134 int main(int argc, char* argv[])
      135 {
      136     DWORD dwProcessID;
      137     cout << "Input ProcessID" << endl;
      138     cin >> dwProcessID;
      139 
      140     // Attach Process
      141     
      142     if( !DebugActiveProcess(dwProcessID) )
      143     {
      144         printf("DebugActiveProcess(%d) failed!!!
      "
      145                "Error Code = %d
      ", dwProcessID, GetLastError());
      146         return 1;
      147     }
      148 
      149     // 调试事件循环
      150     DebugLoop();
      151 
      152     return 0;
      153 }

      参考《逆向工程核心原理》

  • 相关阅读:
    Fidder4 顶部提示 “The system proxy was changed,click to reenable fiddler capture”。
    redis 哨兵 sentinel master slave 连接建立过程
    虚拟点赞浏览功能的大数据量测试
    python基础练习题(题目 字母识词)
    python基础练习题(题目 回文数)
    python基础练习题(题目 递归求等差数列)
    python基础练习题(题目 递归输出)
    python基础练习题(题目 递归求阶乘)
    python基础练习题(题目 阶乘求和)
    python基础练习题(题目 斐波那契数列II)
  • 原文地址:https://www.cnblogs.com/banchen/p/6696562.html
Copyright © 2011-2022 走看看