zoukankan      html  css  js  c++  java
  • 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.   
    4. #include "stdafx.h"  
    5. #include <stdio.h>  
    6. #include <windows.h>  
    7.   
    8. void InitDetect()  
    9. {  
    10.     CONTEXT context;  
    11.     HANDLE hThread = GetCurrentThread();  
    12.     context.ContextFlags = CONTEXT_DEBUG_REGISTERS;  
    13.     GetThreadContext(hThread, &context);  
    14.     context.Dr0 = 0xFF;  
    15.     context.Dr1 = 0xFE;  
    16.     context.Dr2 = 0xFD;  
    17.     context.Dr3 = 0xFC;  
    18.       
    19.     SetThreadContext(hThread, &context);  
    20. }  
    21.   
    22. // 只针对OD 其他调试器未验证 微软的调试器就无效  
    23. // anti OD断点   
    24. BOOL IsDebuged()  
    25. {  
    26.     CONTEXT context;  
    27.     HANDLE hThread = GetCurrentThread();  
    28.     context.ContextFlags = CONTEXT_DEBUG_REGISTERS;  
    29.     GetThreadContext(hThread, &context);  
    30.   
    31.     printf("Dr0:%x ", context.Dr0);  
    32.     printf("Dr1:%x ", context.Dr1);  
    33.     printf("Dr2:%x ", context.Dr2);  
    34.     if (context.Dr0 != 0xFF || context.Dr1 != 0xFE || context.Dr2 != 0xFD)  
    35.     {  
    36.         return TRUE;  
    37.     }  
    38.     return FALSE;  
    39. }  
    // 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
    ", context.Dr0);
    	printf("Dr1:%x
    ", context.Dr1);
    	printf("Dr2:%x
    ", context.Dr2);
    	if (context.Dr0 != 0xFF || context.Dr1 != 0xFE || context.Dr2 != 0xFD)
    	{
    		return TRUE;
    	}
    	return FALSE;
    }


    jpg改rar


  • 相关阅读:
    php上传文件大小限制
    phpStudy for Linux (lnmp+lamp一键安装包)
    linux 常见问题
    Cmake设置环境变量
    NSIS Installer(被NSI脚本编译出来的target)获取命令行参数
    VS2010 Command Prompt Error:Cannot determine the location of the VS Common Tools folder
    关于老驱动不能在windows 8下正常安装的问题
    去除安装程序的窗口显示(类似于后台安装)
    NSIS操作系统环境变量
    NSIS检测操作系统x64还是x86的问题。
  • 原文地址:https://www.cnblogs.com/kuangke/p/6259203.html
Copyright © 2011-2022 走看看