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;
}
附件:
wtujoxk 发表于 2024-7-25 21:30
看到你发的帖子去学习的硬件断点,你试试就知道了
硬件断点就是鸡肋,不稳定,而且麻烦复杂,失效或不起作用或出错都不好找原因。不再折腾了,我还是老老实实的用inline hook吧。 该代码能对付这个吗?
简易的反补丁 CrackMe 64 位
https://www.52pojie.cn/thread-1917353-1-1.html
(出处: 吾爱破解论坛)
虽然不知道有啥用,但是感觉以后会有用。给大佬点赞!!!! 学习了,顶一下 向大佬学习{:1_893:} 刚发贴时,大佬说有问题,现在的是已经修复好了? 朱朱你堕落了 发表于 2024-7-25 21:27
刚发贴时,大佬说有问题,现在的是已经修复好了?
看到你发的帖子去学习的硬件断点,你试试就知道了 董督秀 发表于 2024-7-25 21:36
该代码能对付这个吗?
简易的反补丁 CrackMe 64 位
因为你这个是cm,但是写补丁要方案!调试程序不在行 学到了,希望以后用得上
页:
[1]
2