ring3硬件断点

4个断点寄存器DR0~DR3用来设置断点的线性地址。

DR6为状态寄存器,DR7为控制寄存器。

DR4和DR5保留。当CR4.DE==1时,访问DR4和DR5产生#UD异常;IF CR4.DE==0,访问DR4和DR5将是对DR6和DR7的访问。

下面这张表非常清楚:
   |---------------|----------------|
Dr0|                 用于一般断点的线性地址                    
   |---------------|----------------|
Dr1|                 用于一般断点的线性地址                    
   |---------------|----------------|
Dr2|                 用于一般断点的线性地址                    
   |---------------|----------------|
Dr3|                 用于一般断点的线性地址                    
   |---------------|----------------|
Dr4|                     保留                                
   |---------------|----------------|
Dr5|                     保留                                
   |---------------|----------------|
Dr6|                              |BBB                     BBB B |
   |                              |TSD                      3 2 1 0 |
   |---------------|----------------|
Dr7|LEN RWE   ...       LEN  RWE     |  G               GL GL GL GL GL |
   | 3   3    ...                    0    0          |  D               EE 33 22 11 00 |
   |---------------|----------------|
31                                        15                                0 0

L0~L3 局部断点有效位 对应DR0~DR3 发生任务切换时,处理器就会对L0~L3消位 
G0~G3全局断点有效位 对应DR0~DR3 SetThreadContext设置了这几个位也是不奏效的 应该是在实模式下用

LEN0:占两个位,开始于位17,用于控制Dr0的断点长度,可能取值:
00  1字节
01  2字节
10  保留
11  4字节
RWE0:从第15位开始,占两个位,控制Dr0的断点是读、写还是执行断点或是I/O端口断点:
00  只执行
01 写入数据断点
10 I/O端口断点(只用于pentium+,需设置CR4的DE位)
11 读或写数据断点
RWE1~3,LEN1~3分别用于控制Dr1~3的断点方式,含义如上。

要设置断点的话这些信息基本上已经够了。

OD提供的硬件断点功能有DWORD,WORD,BYTE之分,这个是跟内存地址有关。例如:

addr == 4n 时可以设dword断点
addr == 4n + 2 时可以设word断点
addr == 2n+1 时只能byte断点。
比如说在 00401000处,你可以设三种断点
在 00401002处,你只能设word和byte断点
在 00401005处,你只能设byte断点

如果想直接用MOV指令访问DRx寄存器,你需要在实地址模式,系统管理模式(smm)或者在保护模式(CPL设0)。

windows系统中你可以用GetThreadContext或者Wow64GetThreadContext(64位系统)。内核模式下可以用PsGetThreadContext或者捕获异常然后读取。

SetThreadContext设置的线程上下文是对当前线程有效的,那么为什么OD的硬件断点能够对当前进程有效?
因为OD是遍历线程下断,新建线程也下断。

使用SetThreadContext的注意事项:

·获取线程context的时机。载入目标进程发生第一次EXCEPT_BREAKPOINT 时发生在APC中,线程真实的CONTEXT暂时被存放在栈上,当APC结束调用NtContinue返回内核时写回去,如果此时调用SetThreadContext,断点只在APC期间有效,但是我们可以直接改写在栈上的CONTEXT,这样就可以提前设置断点了。

·打开目标进程的权限要够。

只要能使用Drx的断点功能就可以配合SEH、调试API进行一些反跟踪。

下面是一个anti-OD的示例:

  1. // OD 每次获得被调试程序的控制权后 都会把Drx的值设为自己的设定值
  2. // 倘若没有设硬件断点 就是Drx每次都会请0
  3. #include "stdafx.h"
  4. #include <stdio.h>
  5. #include <windows.h>
  6. void InitDetect()
  7. {
  8. CONTEXT context;
  9. HANDLE hThread = GetCurrentThread();
  10. context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
  11. GetThreadContext(hThread, &context);
  12. context.Dr0 = 0xFF;
  13. context.Dr1 = 0xFE;
  14. context.Dr2 = 0xFD;
  15. context.Dr3 = 0xFC;
  16. SetThreadContext(hThread, &context);
  17. }
  18. // 只针对OD 其他调试器未验证 微软的调试器就无效
  19. // anti OD断点
  20. BOOL IsDebuged()
  21. {
  22. CONTEXT context;
  23. HANDLE hThread = GetCurrentThread();
  24. context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
  25. GetThreadContext(hThread, &context);
  26. printf("Dr0:%x\n", context.Dr0);
  27. printf("Dr1:%x\n", context.Dr1);
  28. printf("Dr2:%x\n", context.Dr2);
  29. if (context.Dr0 != 0xFF || context.Dr1 != 0xFE || context.Dr2 != 0xFD)
  30. {
  31. return TRUE;
  32. }
  33. return FALSE;
  34. }
ring3硬件断点
// OD 每次获得被调试程序的控制权后 都会把Drx的值设为自己的设定值
// 倘若没有设硬件断点 就是Drx每次都会请0 #include "stdafx.h"
#include <stdio.h>
#include <windows.h> void InitDetect()
{
CONTEXT context;
HANDLE hThread = GetCurrentThread();
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(hThread, &context);
context.Dr0 = 0xFF;
context.Dr1 = 0xFE;
context.Dr2 = 0xFD;
context.Dr3 = 0xFC; SetThreadContext(hThread, &context);
} // 只针对OD 其他调试器未验证 微软的调试器就无效
// anti OD断点
BOOL IsDebuged()
{
CONTEXT context;
HANDLE hThread = GetCurrentThread();
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(hThread, &context); printf("Dr0:%x\n", context.Dr0);
printf("Dr1:%x\n", context.Dr1);
printf("Dr2:%x\n", context.Dr2);
if (context.Dr0 != 0xFF || context.Dr1 != 0xFE || context.Dr2 != 0xFD)
{
return TRUE;
}
return FALSE;
}

jpg改rarring3硬件断点

上一篇:Python多线程下的_strptime问题


下一篇:深入浅出经典面试题:从浏览器中输入URL到页面加载发生了什么 - Part 3