描述:
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);
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-10-24 10:56
被wtujoxk编辑
,原因: