20241126 增加DLL,更新搜索算法极端情况搜索
描述:
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了,不能设置的问题,
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;
}
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);
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2024-11-27 11:23
被wtujoxk编辑
,原因: