wtujoxk 发表于 2024-7-25 17:53

Dll劫持 -- 硬件断点的实现

本帖最后由 wtujoxk 于 2024-7-25 19:19 编辑

前言,这是菜鸟学习Dll劫持硬件断点的过程,参考了几篇文章

下面帖上我学习的完整类:HwBreakpoint.cpp
#include "HwBreakpoint.h"

// 保存所有下断点的线程ID和相应寄存器
std::vector<HwBreakpoint> hwbrk;
void SetBits(DWORD_PTR& dw, int lowBit, int bits, int newValue)
{
      DWORD_PTR mask = (1 << bits) - 1;
      dw = (dw & ~(mask << lowBit)) | (newValue << lowBit);
}

// 设置硬件断点,在线程里调用
int RunHwBreakpoint(HANDLE HThread, HWBRK_TYPE Type, HWBRK_SIZE Size, ULONGLONG breakpoint)
{
      SuspendThread(HThread);
      CONTEXT context = { 0 };
      context.ContextFlags = CONTEXT_ALL;
      GetThreadContext(HThread, &context);
      // 找到一个空闲的调试寄存器
      int drIndex = -1, st = 0, le = 0;
      for (int i = 0; i < 4; ++i) {
                if ((context.Dr7 & (3 << (16 + i * 2))) == 0) {
                        drIndex = i;
                        break;
                }
      }
      if (drIndex == -1) return -1; // 没有空闲的调试寄存器

      //std::cout << "drIndex:" << drIndex << std::endl;
      if (drIndex == 0)context.Dr0 = breakpoint;
      if (drIndex == 1)context.Dr1 = breakpoint;
      if (drIndex == 2)context.Dr2 = breakpoint;
      if (drIndex == 3)context.Dr3 = breakpoint;

      if (Type == HWBRK_TYPE_CODE)       st = 0;
      if (Type == HWBRK_TYPE_READWRITE)st = 3;
      if (Type == HWBRK_TYPE_WRITE)      st = 1;

      if (Size == HWBRK_SIZE_1)          le = 0;
      if (Size == HWBRK_SIZE_2)          le = 1;
      if (Size == HWBRK_SIZE_4)          le = 3;
      if (Size == HWBRK_SIZE_8)          le = 2;
      SetBits(context.Dr7, 16 + drIndex * 4, 2, st);// 读取、写入、执行
      SetBits(context.Dr7, 18 + drIndex * 4, 2, le);// 1、2、4、8字节
      SetBits(context.Dr7, drIndex * 2, 1, 1);      //
      SetThreadContext(HThread, &context);
      ResumeThread(HThread);
      HwBreakpoint* h = new HwBreakpoint();
      h->hwbpAddr = breakpoint;
      //h->threadId = GetThreadId(HThread);
      h->iReg = drIndex;
      hwbrk.push_back(*h);
      return 0;
}

DWORD WINAPI BPThreadProc(LPVOID lpParameter)
{
      HwBreakpoint* h = (HwBreakpoint*)lpParameter;
      if (!h)return false;

      if (h->threadId) {
                //方式一:对指定的线程下硬件断点
                HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, h->threadId);
                if (hThread)
                {
                        RunHwBreakpoint(hThread, h->Type, h->Size, h->hwbpAddr);//下硬件断点
                        CloseHandle(hThread);
                        return TRUE;
                }
      }
      else
      {
                //方式二:对所有线程下硬件断点,加壳程序容易出错
                HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetCurrentProcessId());
                if (hSnap != INVALID_HANDLE_VALUE)
                {
                        THREADENTRY32 te;
                        te.dwSize = sizeof(THREADENTRY32);
                        if (Thread32First(hSnap, &te))
                        {
                              do
                              {    // 因为线程会挂起,排除自己的线程
                                        if (te.th32OwnerProcessID == GetCurrentProcessId() && te.th32ThreadID != GetCurrentThreadId())
                                        {
                                                //printf("当前进程: %d, 线程: %d, 优先级: %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
                                                HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, te.th32ThreadID);
                                                if (hThread)
                                                {
                                                      RunHwBreakpoint(hThread, h->Type, h->Size, h->hwbpAddr);//下硬件断点
                                                      CloseHandle(hThread);
                                                }
                                        }
                              } while (Thread32Next(hSnap, &te));
                        }
                }
                if (hSnap) CloseHandle(hSnap);
      }
      return true;
}

// 设置硬件断点
bool SetHwBreakpoint(int ThreadId, HWBRK_TYPE Type, HWBRK_SIZE Size, ULONGLONG breakpoint)
{
      HwBreakpoint* h = new HwBreakpoint();
      h->threadId = ThreadId;
      h->Type = Type;
      h->Size = Size;
      h->hwbpAddr = breakpoint;

      HANDLE handle = CreateThread(NULL, NULL, BPThreadProc, (LPVOID)h, NULL, NULL);
      if (handle)CloseHandle(handle);

      return true;
}

// 删除硬件断点 DelHwBreakpoint(ExceptionInfo->ContextRecord, 0x123456);
bool DelHwBreakpoint(PCONTEXT context, ULONGLONG breakpoint)
{
      if (hwbrk.empty()) return false;
      for (auto& h : hwbrk)
      {
                if (h.hwbpAddr == breakpoint)
                {
                        //std::cout << "dr7:" << breakpoint << std::endl;
                        int FlagBit = 0;
                        if (h.iReg == 0)
                        {
                              FlagBit = 0;
                              context->Dr0 = 0;
                        }
                        if (h.iReg == 1)
                        {
                              FlagBit = 2;
                              context->Dr1 = 0;
                        }
                        if (h.iReg == 2)
                        {
                              FlagBit = 4;
                              context->Dr2 = 0;
                        }
                        if (h.iReg == 3)
                        {
                              FlagBit = 6;
                              context->Dr3 = 0;
                        }
                        context->Dr7 &= ~(1 << FlagBit);
                        // 删除用过的元素
                        hwbrk.erase(std::find(hwbrk.begin(), hwbrk.end(), h));
                }
      }
      return true;
}

头文件:HwBreakpoint.h

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

enum HWBRK_TYPE
{
      HWBRK_TYPE_CODE,         // 执行
      HWBRK_TYPE_READWRITE,    // 读
      HWBRK_TYPE_WRITE,      // 写
};

enum HWBRK_SIZE
{
      HWBRK_SIZE_1,
      HWBRK_SIZE_2,
      HWBRK_SIZE_4,
      HWBRK_SIZE_8,
};

class HwBreakpoint
{
public:

      ULONGLONG hwbpAddr;    // 断点位置
      int threadId;          // 线程
      int iReg;            // 第几个寄存器
      HWBRK_TYPE Type;       // 读、写、执行
      HWBRK_SIZE Size;       // 字节
      HwBreakpoint()         // 初始化
      {
                hwbpAddr = 0;
                threadId = 0;
                iReg = 0;
                Type = HWBRK_TYPE_CODE;
                Size = HWBRK_SIZE_1;
      }

      bool operator ==(const HwBreakpoint& p)
      {
                return true;
      }
};

/************************************************************************
SetHwBreakpoint:   设置线程硬件断点
ThreadId:          线程ID,0为所有线程下断,否则指定线程下断
Type:            参考 enum HWBRK_TYPE
Size:            参考 enum HWBRK_SIZE
breakpoint:      断点位置
调用:SetHwBreakpoint(MainThreadId, HWBRK_TYPE_CODE, HWBRK_SIZE_1, bpAddr);
/************************************************************************/
bool SetHwBreakpoint(int ThreadId, HWBRK_TYPE Type, HWBRK_SIZE Size, ULONGLONG breakpoint);

/************************************************************************
DelHwBreakpoint:删除硬件断点
context:          PCONTEXT指针:ExceptionInfo->ContextRecord
dwAddr:         断点地址:0x123456
调用:            DelHwBreakpoint(ExceptionInfo->ContextRecord, 0x123456);
/************************************************************************/
bool DelHwBreakpoint(PCONTEXT context, ULONGLONG dwAddr);

下断点调用:
//下断点调用
SetHwBreakpoint(0, HWBRK_TYPE_CODE, HWBRK_SIZE_1, bp2);

清除硬件断点调用:
AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)ExceptionHandler);

DWORD NTAPI ExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo)
{
      if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == bpAddr)
      {               
                DelHwBreakpoint(ExceptionInfo->ContextRecord, bpAddr);
                // 这里执行自己的逻辑

                return EXCEPTION_CONTINUE_EXECUTION;
      }

      return EXCEPTION_CONTINUE_SEARCH;
}

附件:

朱朱你堕落了 发表于 2024-7-25 21:35

wtujoxk 发表于 2024-7-25 21:30
看到你发的帖子去学习的硬件断点,你试试就知道了

硬件断点就是鸡肋,不稳定,而且麻烦复杂,失效或不起作用或出错都不好找原因。不再折腾了,我还是老老实实的用inline hook吧。

董督秀 发表于 2024-7-25 21:36

该代码能对付这个吗?

简易的反补丁 CrackMe 64 位
https://www.52pojie.cn/thread-1917353-1-1.html
(出处: 吾爱破解论坛)

daxia520 发表于 2024-7-25 19:19

虽然不知道有啥用,但是感觉以后会有用。给大佬点赞!!!!

yang97 发表于 2024-7-25 19:32

学习了,顶一下

justwz 发表于 2024-7-25 20:10

向大佬学习{:1_893:}

朱朱你堕落了 发表于 2024-7-25 21:27

刚发贴时,大佬说有问题,现在的是已经修复好了?

wtujoxk 发表于 2024-7-25 21:30

朱朱你堕落了 发表于 2024-7-25 21:27
刚发贴时,大佬说有问题,现在的是已经修复好了?

看到你发的帖子去学习的硬件断点,你试试就知道了

wtujoxk 发表于 2024-7-25 21:50

董督秀 发表于 2024-7-25 21:36
该代码能对付这个吗?

简易的反补丁 CrackMe 64 位


因为你这个是cm,但是写补丁要方案!调试程序不在行

CodeZPro 发表于 2024-7-25 22:06

学到了,希望以后用得上
页: [1] 2
查看完整版本: Dll劫持 -- 硬件断点的实现