首页
论坛
课程
招聘
wwzzww
雪    币: 7140
活跃值: 活跃值 (12)
能力值: ( LV9,RANK:270 )
在线值:
发帖
34
回帖
20
粉丝
2

[原创]windows常用的反调试技术-静态反调试技术

2019-2-21 20:54 3883

[原创]windows常用的反调试技术-静态反调试技术

2019-2-21 20:54
3883
1.反调试技术的简单总结。根据破解的方法反调试技术大致可以分为静态与动态两组。调试运用了静态调试技术的程序文件的时候,只要在开始破解一次就可以全部解除反调试限制,动态调试要一边调试一边破解。简单的总结如下图所示。

2.静态反调试技术
          主要用来检测自身是否处于被调试状态,若处于被调试状态,则执行非常规代码组织。

2.1 PEB
       利用PEB可以判断进程是否处于被调试状态,借助FS段寄存器所指的TEB 结构体可以获取进程的PEB结构体,FS[0x30]= address of PEB,或者先获取TEB再获取PEB,   FS[0x18]=address of TEB

       2.1.1 BeingDebugged(0x2)
       BeingDebug成员用来判断进程是否处于被调试状态,被调试的时候他的值为1.
       IsDebuggerPresent(),用来对PEB进行判断
       破解:直接用od将BeingDebugged设置为0就行了

       2.1.2 Process Heap(0x18)
      
       PEB.Process Heap指向HEAP指针结构体
       GetProcessHeap()可以访问PEB,ProcessHep成员
       程序正常运行时 Heap.Flags成员(0xC)值为0x2,Heap.ForceFlags值为0x0,调试状态的时候这些值会改变
       破解:将相应的值正常设置为0x2和0x0就可以了

       2.1.3 NtGlobalFlag(0x68)
       调试的时候NtGlobalFlag会被设置成0x70,检测改制就可以检测程序是否处于调试状态。
       破解,将PEB.NtGlobalFlag值为0就可以了,附加调试的时候,NtGlobalFlag的值是不变的
   
 2.2 NtQueryInformationProcess()
        通过该函数可以获取各种与进程相关的信息
       
      设置第二个参数ProcessInformationClass为指定值,并调用该函数,相关信息就会被设置到第三个参数ProcessInformation里面
       ProcessInformationClass是枚举类型

       2.2.1 ProcessDebugPort(0x7)传入的是值
       进程处于调试状态就会为它分配一个调试端口,Debug Port,进程处于调试的时候,变量dwDebugPort被设置为0xffffffff,非调试状态的时候,dwDebugPort被设置为0x0
       checkRemoteDebuggerPresent()函数会调用ProcessDebugPort进行检测,不仅仅可以用来检测当前进程,还可以用来检测其它进程是否处于调试状态。
        2.2.2  ProcessDebugObjectHandle(0x1E)
        调试的时候会生成调试对象(DebugObject),,若进程处于调试状态的时候,调试对象句柄值就存在,处于非调试状态的时候,调试对象句柄值为NULL.
 
        2.2.3 ProcessDebugFlags(0x1f)
        检测Debug Flags(调试标志)的值可以判断进程处于调试状态,通过函数第三个参数就可以获取调试标志的值,若为0,则处于调试状态,若为1,则处于非调试状态。
       
         2.2.4破解之法
        对函数再特定参数之下的返回值进行操作,若只是调用几次,则可以在调试器中手动输入,若反复操作,则需要进行API勾去。

2.3 NtQuerySystemInformation()
         基于调试环境的反调试技术。
         ntdll!NtQuerySystemInformation()API是一个系统函数,用来获取当前运行的OS信息
        
        SystemInformationClass指定要的系统信息类型,将某结构体的地址传递给sytemInformation参数,API返回的时候,该结构体中就填充着相关信息。
      
         2.3.1systemKernelDebuggerInformation(0x23)
        当调用NtQuerySystemInfromation()API的时候,第一个参数SystemInformationClass的值被设置为systemKernelDebuggerInfromation(0x32的时候,函数调用返回的时候,若系统处于调试状态下,DebuggerEnable的值设置为1

 2.4  NtQueryObject()
         某个调试器调试进程的时候,会创建一个调试对象类型的内核对象。检测该对象存在就可以判断程序是否处于调试状态。
          ntdll!,NtQueryObject()用来获取系统各种内核对象的信息。         
NTSTATUS NtQueryObject(
_In_opt_  HANDLE  Handle,
_In_        OBJECT_INFORMATION_CLASS objectInformationClass,
_Out_opt_ PVOID   ObjectInformation,
_In_ ULONG ObjectInformationLength,
_Out_opt_ PULONG ReturnLength
);
        向第二个参数 ObjectInformationClass赋与某个特定的值,调用该函数后,包含相关信息的结构体指针就返回给第三个参数 ObjectInformation.
        使用objeceAllTypesInformation值获取系统所有对象信息,然后从中检测是否存在调试对象。
        破解,将程序的输入值ObjeceAllTypesInformation(3)修改为零然后再执行函数,这样就无法检测到调试器的存在了。

2.5  ZwSetInformationThread()
       强制分离调试者和被调试者的调试技术。利用 ZwSetInformationThread() 该API,被调试这可以将自身从调试器中分离出来。
NTSYSAPI NTSTATUS ZwSetInformationThread(
  HANDLE          ThreadHandle,
  THREADINFOCLASS ThreadInformationClass,
  PVOID           ThreadInformation,
  ULONG           ThreadInformationLength
);
      该函数拥有2个参数,第一个参数ThreadHandle()用来接受当前线程句柄,第二个参数ThreadinformationClass用来表示当前线程的信息类型,若器值设置为ThreadHideFromDebugger(x011),调用该函数后,调试进程就会被分离处理啊。ZwSetInformationThread()API不会对正常运行的进程产生任何影响,但是若是运行的是调试器程序,该API就会将调试器终止,同时终止自身进程。
       破解之法,将参数 ThreadHideFromDebugger(x011), 设置为0就可以了。


2.6 TLS回调函数
       不能将TLS回调本身看作一种反调试技术,但是由于回调函数会先于EP代码执行,所以反调试技术中经常使用它。TLS回调函数内部使用IsDebuggerPresent()等函数判断调试与否,然后再决定是否集训运行程序

2.7 ETC
       不必非要判断判断自身是否处于被调试状态,更简单的方式是,判断当前系统是否为逆向分析专用系统,若是,则直接停止程序。这样就出现了各种反调试技术,这些技术能够从系统轻松获取各种信息(进程,文件,窗口注册表,主机名,计算机名,用户名,环境变量等)。这些反调试技术通常通过借助Win32API获取系统信息来具体实现。
      (1)检测OD窗口->FindWindow().
        (2)检测OD进程->CreateToolhelp32Snapshot()。
        (3)检测计算机名->GetComputerName().
        (4)检查程序运行路径中的一些关键字->GetComputerName()
        (5)检测虚拟机是否处于运行状态,查看虚拟机特有的进程名称VMWareTray.exe等
        

      强大的od有很多反调试插件可以使用,可以让我们更加顺利的调试,当然有时候插件也不是万能的,所以我们需要了解相关的原理。

最后于 2019-2-22 14:57 被wwzzww编辑 ,原因: 错字
最新回复 (6)
黑洛
雪    币: 5270
活跃值: 活跃值 (50)
能力值: ( LV5,RANK:70 )
在线值:
发帖
6
回帖
365
粉丝
3
黑洛 活跃值 1 2019-2-22 00:12
2
0
ZwSetInformationThread  这个函数的效果说明有误,ThreadHideFromDebugger的表现为使调试器无法接受到调试事件,造成调试器被调试器退出的应该是其他原因。
五天
雪    币: 351
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
7
回帖
122
粉丝
0
五天 活跃值 2019-2-22 13:06
3
0
感谢大佬分享
killpy
雪    币: 40
活跃值: 活跃值 (21)
能力值: ( LV8,RANK:130 )
在线值:
发帖
32
回帖
597
粉丝
6
killpy 活跃值 2 2019-2-22 13:06
4
0
不错 很好的总结
Editor
雪    币: 4726
活跃值: 活跃值 (885)
能力值: (RANK:40 )
在线值:
发帖
788
回帖
1858
粉丝
54
Editor 活跃值 2019-2-25 09:51
5
0
感谢分享~ 
余生挚爱传奇
雪    币: 245
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
2
回帖
15
粉丝
0
余生挚爱传奇 活跃值 1 2019-5-6 07:46
6
0
这不是《逆向工程核心原理》里的内容吗?
niuzuoquan
雪    币: 265
活跃值: 活跃值 (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
1
回帖
405
粉丝
0
niuzuoquan 活跃值 2019-5-6 09:06
7
0
mark
游客
登录 | 注册 方可回帖
返回