免费教程_免费网赚教程_破解版软件-寂涯网络学习基地

当前位置: 主页 > 系统综合 > 软件破解 > 获取线程上下文api反调试技巧

获取线程上下文api反调试技巧

时间:2011-12-21 17:35来源:未知 整理:寂涯网络 点击:

自从有了海风的 StrongOD 插件,我一度以为利用 API 的反调试技巧都变成了绝唱,毕
竟 Ring3 再怎么努力,只要Ring0 轻轻一抹都成白费力气。不过偶然发现通过获取线程上下
文来反调试的技巧居然还 work,于是一阵窃喜,仔细分析后,觉得这个技巧仍然有效并不
全靠运气,而是正巧碰上了OD的“难言之隐”,就算StrongOD也无法轻易地解决这个问题。 
所谓线程上下文,就是线程的各种寄存器当前的值。获取线程上下文最直接的方法,就
是调用 GetThreadContext这个API。GetThreadContext的原型如下:  

BOOL WINAPI GetThreadContext(
  __in     HANDLE hThread,
  __inout  LPCONTEXT lpContext
)

没有繁琐的API属性设置,参数简单得难以置信:传入目标线程的句柄,就能得到上下
文。线程句柄就不解释了,看看这个lpContext,也就是保存上下文的结构体,究竟是个什
么东西。 
 
CONTEXT结构体的成员比较多,只好阉割一下,取重要的来看:
typedef struct DECLSPEC_ALIGN(16) _CONTEXT {
...
// Debug registers
//
DWORD64 Dr0;
DWORD64 Dr1;
DWORD64 Dr2;
DWORD64 Dr3;
DWORD64 Dr6;
DWORD64 Dr7 
...

} CONTEXT;   

Drx 是老朋友了,就是硬件调试寄存器,其中Dr0-3,就是对应OD里看到的四个硬件断
点,而 Dr7 则是状态控制寄存器。简单来说,如果用 OD 下了硬件断点,那么这五个寄存器
的值就至少有两个不为0。
核心代码如下:

main()
{
 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);
 printf("Dr3:%x\n",context.Dr3);
 printf("Dr7:%x\n",context.Dr7);

代码很短。首先是获取当前线程句柄,接着初始化 ContextFlags,这一步必不可少,
最后就是调用 GetThreadContext。为了便于观察,这里只是简单打印出五个寄存器的值,
方便对比硬件断点前后的变化。先看程序自己运行时线程上下文。

用 OD+最新版的SOD加载,随便设置4个硬件断点 

按 F9运行,

数值改变了,而且仔细观察,与硬件断点确实是一一对应的关系。这是正着使用上下文
检测调试技术,也就是检测 Drx 的值是否保持为0,那能不能反过来,测试 Drx 的值是否保
持非0呢?
技术需要想象力(寂涯网络www.jybase.net)。有了想象,就等于实现了一半,那么我们再来看看另一半该怎么实现: 

main()
{
 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);
 GetThreadContext(hThread,&context);
 printf("Dr0:%x\n",context.Dr0);
 printf("Dr1:%x\n",context.Dr1);
 printf("Dr2:%x\n",context.Dr2);
 printf("Dr3:%x\n",context.Dr3);}

代码大同小异,主要是多了一个SetThreadContext,这个 API用来设置线程的上下文,
参数与 GetThreadContext 完全一样。我们随便设置一下四个硬件寄存器的值。

接着用 OD 载入,这时查看 OD 的硬件断点,发现并不是我们设置的OxFF 之类的值,而
是保持 OD之前的状态。这样就可能导致OD 所记录的硬件断点,与实际的硬件断点不一致,
或许这算 OD 在设计上的一处考虑不周吧。删除全部的硬件断点,在调用SetThreadContext
的后一个指令上下断点。

现在可以 F9了,再看看打印的值 

我们明明通过 SetThreadContext 改变了硬件断点的值,为什么会被清0呢?这是因为
OD 在每次获得被调试程序的控制权后,都会将硬件寄存器的值修改为OD 自己所记录的值。

本页地址 http://www.jybase.net/ruanjianpojie/20111221725.html

百度搜索更多

谷歌搜索更多

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------

评价:
昵称: 验证码:点击我更换图片
推荐内容
赞助商
赞助商


关于本站免责声明视频更新google百度地图视频地图RRS订阅

如有什么问题请在本站留言,或发邮件到 hxt167#foxmail.com