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("\n### original string ###\n%s\n", 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("\n### converted string ###\n%s\n", 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!!!\n"
    145                "Error Code = %d\n", dwProcessID, GetLastError());
    146         return 1;
    147     }
    148
    149     // 调试事件循环
    150     DebugLoop();
    151
    152     return 0;
    153 }

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

时间: 2024-11-06 04:20:21

Debug Hook的相关文章

FREERTOS 手册阅读笔记

郑重声明,版权所有! 转载需说明. FREERTOS堆栈大小的单位是word,不是byte. 根据处理器架构优化系统的任务优先级不能超过32,If the architecture optimized method is used then configMAX_PRIORITIES cannot be greater than 32. vTaskDelay() delay from call the vTaskDelay vTaskDelayUntil delay from last wake

我的学习笔记_Windows_HOOK编程 2009-12-03 11:19

一.什么是HOOK? "hook"这个单词的意思是"钩子","Windows Hook"是Windows消息处理机制的一个重要扩展,程序猿能够通过它来钩住(截获)感兴趣的消息,并用事先编好的一个函数(钩子过程)来处理这些消息!当然,这个处理是在消息到达目标窗体之前进行的. 钩子过程(hook procedure)实际上是一个用来处理消息的函数,通过系统调用,程序猿能够把它挂入系统或进程的钩子链中,让它成为一个钩子.每当系统中产生特定的消息时,钩子

孙鑫视频VC++深入详解学习笔记

Lesson1: Windows程序运行原理及程序编写流程 Lesson2: 掌握C++基本语法 Lesson3: MFC框架程序剖析 Lesson4: 简单绘图 Lesson5: 文本编程 Lesson6: 菜单编程 Lesson7: 对话框编程 Lesson9: 定制应用程序的外观 Lesson10: 绘图控制 Lesson11 图形的保存和重绘 Lesson12 文件操作 Lesson 13: 文档串行化 Lesson14 网络编程 Lesson 15 多线程 Lesson 16 线程同步

孙鑫视频VC++深入详解学习笔记(全)

Lesson1: Windows程序运行原理及程序编写流程 窗口产生过程,句柄原理,消息队列,回调函数,窗口关闭与应用程序退出的工作关系,使用VC++的若干小技巧,stdcall与Lessonecl调用规范的比较,初学者常犯错误及注意事项. 1.       Windows API与Win32 SDK 操作系统提供了各种方便开发Windows应用程序的编程接口,所的函数都在Windows.h头文件中声明.Win32 SDK(Software Development Kit): 即Windows

android hook 框架 libinject2 简介、编译、运行

简介: libinject 最开始是2011年看雪android安全版版主之一‘古河’大神发布的一份android平台的注入库:  发个Android平台上的注入代码  ,网上很多随后发布的注入代码都是其变种,不过我这几天尝试运行那份代码,发现有些问题,本博运行和分析的代码是另外一位大神的改进版本,在我的环境里运行注入和挂钩都成功了 : Android中的so注入(inject)和挂钩(hook) - For both x86 and arm ,为了表示区别,我把这个项目称为  libinjec

COM接口函数通用Hook方法

本文是我的本科学位论文, 今发表在此, 以示原创之据 第1章 绪论 研究背景 研究意义 相关技术简介 COM概述 COM内存模型描述及C语言和C++语言实现 调用约定 Hook API原理 Windows钩子原理及进程注入 开发及调试环境 第2章 问题抽象及关键技术研究 实验01:通过调试器查看C++类的虚函数表 实验02:通过函数指针调用C++虚函数 实验03:交换两个相同C++类的虚函数表 实验04-1:替换C++虚函数表中的虚函数(__thiscall)地址 实验04-2:替换C++虚函数

HDU1698 Just a Hook 【线段树】+【成段更新】+【lazy标记】

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 15889    Accepted Submission(s): 7897 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing

Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发

hook开发是Liferay客制扩展的一种方式,比插件灵活,即可以扩展liferay门户,也能对原有特性进行更改,Liferay有许多内置的服务,比如用hook甚至可以覆盖Liferay服务. 可作为系统服务挂钩(Liferay Service Hook),还有其他类型的hook... Liferay6.2 时的hook开发比较有限,而在Liferay7则大为不同,OSGi services的彻底改进至Liferay的底层模型框架,使得Liferay可以支持更多的定制扩展!OSGi plugin

MPI Debug Tips

debug一个并行程序(parallel program)向来是件很麻烦的事情(Erlang等functional programming language另当别论), 对于像MPI这种非shared memory的inter-process model来说尤其如此. 与调试并行程序相关的工具 非开源工具 目前我所了解的商业调试器(debugger)有: TotalView Allinea DDT 据说parallel debug的能力很屌, 本人没用过表示不知,说不定只是界面做得好看而已. 不