首页
社区
课程
招聘
[原创]C/C++ 自写补丁-设置硬件断点 x86_x64
发表于: 2024-10-9 11:10 3293

[原创]C/C++ 自写补丁-设置硬件断点 x86_x64

2024-10-9 11:10
3293

描述:
1、与软件断点与内存断点不同,硬件断点不依赖被调试程序,而是依赖于CPU中的调试寄存器。
2、调试寄存器有8个,分别为Dr0-Dr7。
3、用户最多能够设置4个硬件断点,这是由于只有Dr0~Dr3用于存储线性地址。
4、其中,Dr4和Dr5是保留的。

1)Dr0-Dr3用于设置硬件断点,由于只有4个断点寄存器,所以最多只能设置4个硬件调试断点。
2)Dr7是最重要的寄存器:
L0/G0 ~ L3/G3:控制Dr0-Dr3是否有效,局部还是全局;每次异常后,Lx都被清零,Gx不清零。
断点长度(LENx):00(1字节)、01(2字节)、11(4字节)、10(8字节)
断点类型(R/Wx):00(执行断点)、01(写入断点)、11(访问断点)

1)硬件调试断点产生的异常是 STATUS_SINGLE_STEP(单步异常)
2)检测Dr6寄存器的B0~B3:哪个寄存器触发的异常

硬件断点设置与线程、寄存器有关,并且还有读、写、访问、字节大小等一些设置,下面用代码实现这一系列设置和删除的操作,创建一个HardwareBreakpoint.cpp,写如下内容:

再创建一个HardwareBreakpoint.h文件,写如下内容:


也可使用HijackTingMix.zip静态库,库里为加强版避免了GetThreadContext和SetThreadContext被hook了,不能设置的问题,

#include "HardwareBreakpoint.h"
#include <vector>
#include <TlHelp32.h>
 
#define BITSET(a,x) (a|=1<<x)
#define BITGET(a,x) (a&(1<<x))
 
enum HWBP_MODE
{
    MODE_DISABLED = 0,    //00
    MODE_LOCAL = 1,       //01
    MODE_GLOBAL = 2       //10
};
struct DR7
{
    BYTE HWBP_MODE[4];
    BYTE HWBP_TYPE[4];
    BYTE HWBP_SIZE[4];
};
class HardwareBreakpoint
{
public:
 
    ULONG_PTR hwbpAddr;   // 断点位置
    int threadId;         // 线程ID
    HWBP_DRX Drx;         // 第几个寄存器
    HWBP_TYPE Type;       // 读、写、执行
    HWBP_SIZE Size;       // 字节
    HardwareBreakpoint()  // 初始化
    {
        hwbpAddr = 0;
        threadId = 0;
        Drx = Dr0;
        Type = TYPE_EXECUTE;
        Size = SIZE_1;
    }
 
    bool operator ==(const HardwareBreakpoint& p)
    {
        return hwbpAddr == p.hwbpAddr;
    }
};
ULONG_PTR dr7uint(DR7* dr7)
{
    ULONG_PTR ret = 0;
    if (BITGET(dr7->HWBP_MODE[0], 0))
        BITSET(ret, 0);
    if (BITGET(dr7->HWBP_MODE[0], 1))
        BITSET(ret, 1);
    if (BITGET(dr7->HWBP_MODE[1], 0))
        BITSET(ret, 2);
    if (BITGET(dr7->HWBP_MODE[1], 1))
        BITSET(ret, 3);
    if (BITGET(dr7->HWBP_MODE[2], 0))
        BITSET(ret, 4);
    if (BITGET(dr7->HWBP_MODE[2], 1))
        BITSET(ret, 5);
    if (BITGET(dr7->HWBP_MODE[3], 0))
        BITSET(ret, 6);
    if (BITGET(dr7->HWBP_MODE[3], 1))
        BITSET(ret, 7);
    if (BITGET(dr7->HWBP_TYPE[0], 0))
        BITSET(ret, 16);
    if (BITGET(dr7->HWBP_TYPE[0], 1))
        BITSET(ret, 17);
    if (BITGET(dr7->HWBP_SIZE[0], 0))
        BITSET(ret, 18);
    if (BITGET(dr7->HWBP_SIZE[0], 1))
        BITSET(ret, 19);
    if (BITGET(dr7->HWBP_TYPE[1], 0))
        BITSET(ret, 20);
    if (BITGET(dr7->HWBP_TYPE[1], 1))
        BITSET(ret, 21);
    if (BITGET(dr7->HWBP_SIZE[1], 0))
        BITSET(ret, 22);
    if (BITGET(dr7->HWBP_SIZE[1], 1))
        BITSET(ret, 23);
    if (BITGET(dr7->HWBP_TYPE[2], 0))
        BITSET(ret, 24);
    if (BITGET(dr7->HWBP_TYPE[2], 1))
        BITSET(ret, 25);
    if (BITGET(dr7->HWBP_SIZE[2], 0))
        BITSET(ret, 26);
    if (BITGET(dr7->HWBP_SIZE[2], 1))
        BITSET(ret, 27);
    if (BITGET(dr7->HWBP_TYPE[3], 0))
        BITSET(ret, 28);
    if (BITGET(dr7->HWBP_TYPE[3], 1))
        BITSET(ret, 29);
    if (BITGET(dr7->HWBP_SIZE[3], 0))
        BITSET(ret, 30);
    if (BITGET(dr7->HWBP_SIZE[3], 1))
        BITSET(ret, 31);
    return ret;
}
 
// 保存所有下断点的线程ID和相应寄存器
std::vector<HardwareBreakpoint> hwbrk;
// 设置硬件断点,在线程里调用
int RunHwBreakpoint(HANDLE HThread, HWBP_DRX Drx, HWBP_TYPE Type, HWBP_SIZE Size, ULONG_PTR breakpoint)
{
    SuspendThread(HThread);
    CONTEXT context = { 0 };
    context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    GetThreadContext(HThread, &context);
 
    if (Drx == Dr0) { context.Dr0 = breakpoint; }
    if (Drx == Dr1) { context.Dr1 = breakpoint; }
    if (Drx == Dr2) { context.Dr2 = breakpoint; }
    if (Drx == Dr3) { context.Dr3 = breakpoint; }
 
    HWBP_MODE hwbpMode;
    DR7 dr7;
    hwbpMode = MODE_LOCAL;
    dr7.HWBP_MODE[Drx] = hwbpMode;
    dr7.HWBP_TYPE[Drx] = Type;
    dr7.HWBP_SIZE[Drx] = Size;
    context.Dr7 |= dr7uint(&dr7);
 
    SetThreadContext(HThread, &context);
    ResumeThread(HThread);
    // 将当前断点信息存入 vector
    HardwareBreakpoint* h = new HardwareBreakpoint();
    h->hwbpAddr = breakpoint;
    h->threadId = GetThreadId(HThread);
    h->Drx = Drx;
    hwbrk.push_back(*h);
    delete[] h;
    h = NULL;
    return 1;
}
 
DWORD WINAPI BPThreadProc(LPVOID lpParameter)
{
    HardwareBreakpoint* h = (HardwareBreakpoint*)lpParameter;
    if (!h)return 0;
 
    if (h->threadId) {
        //方式一:对指定的线程下硬件断点
        HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, h->threadId);
        if (hThread)
        {
            RunHwBreakpoint(hThread, h->Drx, h->Type, h->Size, h->hwbpAddr);  //下硬件断点
            CloseHandle(hThread);
            return 1;
        }
    }
    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())
                    {
                        HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, te.th32ThreadID);
                        if (hThread)
                        {
                            RunHwBreakpoint(hThread, h->Drx, h->Type, h->Size, h->hwbpAddr);  //下硬件断点
                            CloseHandle(hThread);
                        }
                    }
                } while (Thread32Next(hSnap, &te));
            }
        }
        if (hSnap) CloseHandle(hSnap);
    }
    return 1;
}
 
// 设置硬件断点
ULONG_PTR SetHwBreakpoint(int ThreadId, HWBP_DRX Drx, HWBP_TYPE Type, HWBP_SIZE Size, ULONG_PTR breakpoint)
{
    HardwareBreakpoint* h = new HardwareBreakpoint();
    h->threadId = ThreadId;
    h->Drx = Drx;
    h->Type = Type;
    h->Size = Size;
    h->hwbpAddr = breakpoint;
 
    HANDLE handle = CreateThread(NULL, NULL, BPThreadProc, (LPVOID)h, NULL, NULL);
    WaitForSingleObject(handle, INFINITE); //等待异常消息
    CloseHandle(handle);
    delete[] h;
    h = NULL;
    return breakpoint;
}
 
// 删除硬件断点 DelHwBreakpoint(ExceptionInfo->ContextRecord, 0x123456);
bool DelHwBreakpoint(PCONTEXT context, ULONG_PTR breakpoint)
{
    if (hwbrk.size() <= 0) return false;
    for (auto& h : hwbrk)
    {
        if (h.hwbpAddr == breakpoint)
        {
            int FlagBit = 0;
            if (h.Drx == Dr0)
            {
                FlagBit = 0;
                context->Dr0 = 0;
            }
            if (h.Drx == Dr1)
            {
                FlagBit = 2;
                context->Dr1 = 0;
            }
            if (h.Drx == Dr2)
            {
                FlagBit = 4;
                context->Dr2 = 0;
            }
            if (h.Drx == Dr3)
            {
                FlagBit = 6;
                context->Dr3 = 0;
            }
            context->Dr7 &= ~(1 << FlagBit);
            context->Dr7 &= ~(1 << (FlagBit + 1));
 
            // 删除用过的元素
            for (int i = hwbrk.size() - 1; i >= 0; i--) {
                if (hwbrk[i] == h) {
                    hwbrk.erase(hwbrk.begin() + i);
                }
            }
            return true;
        }
    }
    return false;
}
#include "HardwareBreakpoint.h"
#include <vector>
#include <TlHelp32.h>
 
#define BITSET(a,x) (a|=1<<x)
#define BITGET(a,x) (a&(1<<x))
 
enum HWBP_MODE
{
    MODE_DISABLED = 0,    //00
    MODE_LOCAL = 1,       //01
    MODE_GLOBAL = 2       //10
};
struct DR7
{
    BYTE HWBP_MODE[4];
    BYTE HWBP_TYPE[4];
    BYTE HWBP_SIZE[4];
};
class HardwareBreakpoint
{
public:
 
    ULONG_PTR hwbpAddr;   // 断点位置
    int threadId;         // 线程ID
    HWBP_DRX Drx;         // 第几个寄存器
    HWBP_TYPE Type;       // 读、写、执行
    HWBP_SIZE Size;       // 字节
    HardwareBreakpoint()  // 初始化
    {
        hwbpAddr = 0;
        threadId = 0;
        Drx = Dr0;
        Type = TYPE_EXECUTE;
        Size = SIZE_1;
    }
 
    bool operator ==(const HardwareBreakpoint& p)
    {
        return hwbpAddr == p.hwbpAddr;
    }
};
ULONG_PTR dr7uint(DR7* dr7)
{
    ULONG_PTR ret = 0;
    if (BITGET(dr7->HWBP_MODE[0], 0))
        BITSET(ret, 0);
    if (BITGET(dr7->HWBP_MODE[0], 1))
        BITSET(ret, 1);
    if (BITGET(dr7->HWBP_MODE[1], 0))
        BITSET(ret, 2);
    if (BITGET(dr7->HWBP_MODE[1], 1))
        BITSET(ret, 3);
    if (BITGET(dr7->HWBP_MODE[2], 0))
        BITSET(ret, 4);
    if (BITGET(dr7->HWBP_MODE[2], 1))
        BITSET(ret, 5);
    if (BITGET(dr7->HWBP_MODE[3], 0))
        BITSET(ret, 6);
    if (BITGET(dr7->HWBP_MODE[3], 1))
        BITSET(ret, 7);
    if (BITGET(dr7->HWBP_TYPE[0], 0))
        BITSET(ret, 16);
    if (BITGET(dr7->HWBP_TYPE[0], 1))
        BITSET(ret, 17);
    if (BITGET(dr7->HWBP_SIZE[0], 0))
        BITSET(ret, 18);
    if (BITGET(dr7->HWBP_SIZE[0], 1))
        BITSET(ret, 19);
    if (BITGET(dr7->HWBP_TYPE[1], 0))
        BITSET(ret, 20);
    if (BITGET(dr7->HWBP_TYPE[1], 1))
        BITSET(ret, 21);
    if (BITGET(dr7->HWBP_SIZE[1], 0))
        BITSET(ret, 22);
    if (BITGET(dr7->HWBP_SIZE[1], 1))
        BITSET(ret, 23);
    if (BITGET(dr7->HWBP_TYPE[2], 0))
        BITSET(ret, 24);
    if (BITGET(dr7->HWBP_TYPE[2], 1))
        BITSET(ret, 25);
    if (BITGET(dr7->HWBP_SIZE[2], 0))
        BITSET(ret, 26);
    if (BITGET(dr7->HWBP_SIZE[2], 1))
        BITSET(ret, 27);
    if (BITGET(dr7->HWBP_TYPE[3], 0))
        BITSET(ret, 28);
    if (BITGET(dr7->HWBP_TYPE[3], 1))
        BITSET(ret, 29);
    if (BITGET(dr7->HWBP_SIZE[3], 0))
        BITSET(ret, 30);
    if (BITGET(dr7->HWBP_SIZE[3], 1))
        BITSET(ret, 31);
    return ret;
}
 
// 保存所有下断点的线程ID和相应寄存器
std::vector<HardwareBreakpoint> hwbrk;
// 设置硬件断点,在线程里调用
int RunHwBreakpoint(HANDLE HThread, HWBP_DRX Drx, HWBP_TYPE Type, HWBP_SIZE Size, ULONG_PTR breakpoint)
{
    SuspendThread(HThread);
    CONTEXT context = { 0 };
    context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    GetThreadContext(HThread, &context);
 
    if (Drx == Dr0) { context.Dr0 = breakpoint; }
    if (Drx == Dr1) { context.Dr1 = breakpoint; }
    if (Drx == Dr2) { context.Dr2 = breakpoint; }
    if (Drx == Dr3) { context.Dr3 = breakpoint; }
 
    HWBP_MODE hwbpMode;
    DR7 dr7;
    hwbpMode = MODE_LOCAL;
    dr7.HWBP_MODE[Drx] = hwbpMode;
    dr7.HWBP_TYPE[Drx] = Type;
    dr7.HWBP_SIZE[Drx] = Size;
    context.Dr7 |= dr7uint(&dr7);
 
    SetThreadContext(HThread, &context);
    ResumeThread(HThread);
    // 将当前断点信息存入 vector
    HardwareBreakpoint* h = new HardwareBreakpoint();
    h->hwbpAddr = breakpoint;
    h->threadId = GetThreadId(HThread);
    h->Drx = Drx;
    hwbrk.push_back(*h);
    delete[] h;
    h = NULL;
    return 1;
}
 
DWORD WINAPI BPThreadProc(LPVOID lpParameter)
{
    HardwareBreakpoint* h = (HardwareBreakpoint*)lpParameter;
    if (!h)return 0;
 
    if (h->threadId) {
        //方式一:对指定的线程下硬件断点
        HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, h->threadId);
        if (hThread)
        {
            RunHwBreakpoint(hThread, h->Drx, h->Type, h->Size, h->hwbpAddr);  //下硬件断点
            CloseHandle(hThread);
            return 1;
        }
    }
    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())
                    {
                        HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, te.th32ThreadID);
                        if (hThread)
                        {
                            RunHwBreakpoint(hThread, h->Drx, h->Type, h->Size, h->hwbpAddr);  //下硬件断点
                            CloseHandle(hThread);
                        }
                    }
                } while (Thread32Next(hSnap, &te));
            }
        }
        if (hSnap) CloseHandle(hSnap);
最后于 2024-10-9 15:34 被wtujoxk编辑 ,原因:
上传的附件:
收藏
免费 4
支持
分享
最新回复 (5)
雪    币: 1392
活跃值: (5017)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
2
10年前用这个方案做过war3的外挂,避免crc校验。
2024-10-9 11:21
1
雪    币: 3398
活跃值: (3777)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
希望大佬编译个vs2013版的。
2024-10-9 12:56
0
雪    币: 515
活跃值: (682)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
院士 希望大佬编译个vs2013版的。[em_13]
增加了一个其它语言调用示例,你自己封装一下就是可以在其它版本或语言调用了!
2024-10-9 15:35
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
Safengine Shielden 保护程序 有反硬件断点 无法劫持
2024-10-10 04:04
0
雪    币: 12201
活跃值: (4948)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6


下载凭证已过期,请刷新页面重新尝试下载。

刷新一下网页,可以下

奇怪

最后于 2024-10-10 11:26 被xie风腾编辑 ,原因:
2024-10-10 11:25
0
游客
登录 | 注册 方可回帖
返回
//