飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3301|回复: 6

[原创] C/C++ Dll劫持 -- 硬件断点的实现 类型、大小设置

[复制链接]
  • TA的每日心情
    奋斗
    2024-10-21 16:09
  • 签到天数: 93 天

    [LV.6]常住居民II

    发表于 2024-7-28 15:59:19 | 显示全部楼层 |阅读模式
    本帖最后由 wtujoxk 于 2024-7-28 16:00 编辑

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

    下面帖上我学习的完整类:HwBreakpoint.cpp




    [C++] 纯文本查看 复制代码
    #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) {
                    MessageBoxW(NULL, L"没有可用的硬件断点", L"提示", MB_OK);
                    return -1; // 没有空闲的调试寄存器
            }
    
            if (drIndex == 0)context.Dr0 = breakpoint;
            if (drIndex == 1)context.Dr1 = breakpoint;
            if (drIndex == 2)context.Dr2 = breakpoint;
            if (drIndex == 3)context.Dr3 = breakpoint;
    
            SetBits(context.Dr7, 16 + drIndex * 4, 2, Type);  // 设置读取、写入、执行
            SetBits(context.Dr7, 18 + drIndex * 4, 2, Size);  // 设置1、2、4、8字节
            SetBits(context.Dr7, drIndex * 2, 1, 1);          // 启用断点
            SetThreadContext(HThread, &context);
            ResumeThread(HThread);
            // 将当前断点信息存入 vector
            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;
    }
    
    // 设置硬件断点
    ULONGLONG 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 breakpoint;
    }
    
    // 删除硬件断点 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;
                            }
                            // 此设置来自:[url=https://github.com/x64dbg/TitanEngine/]https://github.com/x64dbg/TitanEngine/[/url]
                            //DeleteHardwareBreakPoint 方法
                            context->Dr7 &= ~(1 << FlagBit);
                            context->Dr7 &= ~(1 << FlagBit + 1);
                            // 删除用过的元素
                            //hwbrk.erase(std::find(hwbrk.begin(), hwbrk.end(), h));
                            hwbrk.erase(std::remove(hwbrk.begin(), hwbrk.end(), h), hwbrk.end());
                    }
            }
            return true;
    }



    头文件:HwBreakpoint.h
    [C++] 纯文本查看 复制代码
    #include <windows.h>
    #include <vector>
    #include <TlHelp32.h>
    #include <iostream>
    
    enum HWBRK_TYPE
    {
            TYPE_EXECUTE = 0,      //00 执行
            TYPE_WRITE = 1,        //01 写
            TYPE_READWRITE = 3,    //10 读
    };
    
    enum HWBRK_SIZE
    {
            SIZE_1 = 0,        //00
            SIZE_2 = 1,        //01
            SIZE_8 = 2,        //10 64位系统
            SIZE_4 = 3,        //11
    };
    
    class HwBreakpoint
    {
    public:
    
            ULONGLONG hwbpAddr;    // 断点位置
            int threadId;          // 线程
            int iReg;              // 第几个寄存器
            HWBRK_TYPE Type;       // 读、写、执行
            HWBRK_SIZE Size;       // 字节
            HwBreakpoint()         // 初始化
            {
                    hwbpAddr = 0;
                    threadId = 0;
                    iReg = 0;
                    Type = TYPE_EXECUTE;
                    Size = SIZE_1;
            }
    
            bool operator ==(const HwBreakpoint& p)
            {
                    return hwbpAddr == p.hwbpAddr;
            }
    };
    
    /************************************************************************
    SetHwBreakpoint:   设置线程硬件断点
    ThreadId:          线程ID,0为所有线程下断,否则指定线程下断
    Type:              参考 enum HWBRK_TYPE
    Size:              参考 enum HWBRK_SIZE
    breakpoint:        断点位置
    调用:SetHwBreakpoint(MainThreadId, HWBRK_TYPE_CODE, HWBRK_SIZE_1, bp2);
    返回:返回值为传入的断点地址
    /************************************************************************/
    ULONGLONG SetHwBreakpoint(int ThreadId, HWBRK_TYPE Type, HWBRK_SIZE Size, ULONGLONG dwAddr);
    
    /************************************************************************
    DelHwBreakpoint:  删除硬件断点
    context:          PCONTEXT指针:ExceptionInfo->ContextRecord
    dwAddr:           断点地址:0x123456
    调用:            DelHwBreakpoint(ExceptionInfo->ContextRecord, 0x123456);
    /************************************************************************/
    bool DelHwBreakpoint(PCONTEXT context, ULONGLONG dwAddr);


    调用:调用很简单,看一下头文件声明,不考虑线程……和对指定线程下断
    附件: HwBreakpoint.rar (2.54 KB, 下载次数: 29, 售价: 5 枚飘云币)

    评分

    参与人数 4威望 +4 飘云币 +3 收起 理由
    xsping838 + 1 感谢发布原创作品,PYG有你更精彩!
    飞天 + 1 + 1 PYG有你更精彩!
    jim66xy + 1 + 1 PYG有你更精彩!
    dujinshan + 1 + 1 PYG有你更精彩!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    擦汗
    2025-1-8 23:57
  • 签到天数: 376 天

    [LV.9]以坛为家II

    发表于 2024-7-28 22:18:47 | 显示全部楼层
    下载下来看看
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    前天 12:15
  • 签到天数: 374 天

    [LV.9]以坛为家II

    发表于 2024-7-29 00:04:15 | 显示全部楼层
    谢谢楼主分享~
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    前天 08:19
  • 签到天数: 325 天

    [LV.8]以坛为家I

    发表于 2024-7-31 08:02:21 | 显示全部楼层
    谢谢楼主分享~
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2024-5-30 20:36
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2024-8-7 10:53:22 | 显示全部楼层
    谢谢楼主分享
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表