静态反调试技术
反调试技术,恶意代码用它识别是否被调试,或者让调试器失效。恶意代码编写者意识到分析人员经常使用调试器来观察恶意代码的操作,因此他们使用反调试技术尽可能地延长恶意代码的分析时间。为了阻止调试器的分析,当恶意代码意识到自己被调试时,它们可能改变正常的执行路径或者修改自身程序让自己崩溃,从而增加调试时间和复杂度。很多种反调试技术可以达到反调试效果。这里介绍当前常用的几种反调试技术,同时也会介绍一些逃避反调试的技巧。
一.探测Windows调试器
恶意代码会使用多种技术探测调试器调试它的痕迹,其中包括使用Windows API、手动检测调试器人工痕迹的内存结构,查询调试器遗留在系统中的痕迹等。调试器探测是恶意代码最常用的反调试技术。
1.1 IsDebuggerPresent
IsDebuggerPresent 函数查询PEB结构中的IsDebugged标志位来查询进程是否处于被调试态,如果出去被调试状态,该标志位会为1,函数返回一个非0值。
return IsDebuggerPresent();
破解之法
可以修改PEB BeingDebugged 为0
1.2 CheckRemoteDebuggerPresent
CheckRemoteDebuggerPresent 和IsDebuggerPresent函数的工作原理相同,不过它可以检测系统中其他进程的情况。
1.3 NtQueryInformationProcess
这个NtDll函数中的原生态API 可以用来检索进程的相关信息。
1 NTSYSAPI NTSTATUS NTAPI NtQueryInformationProcess ( 2 IN HANDLE ProcessHandle, // 进程句柄 3 IN PROCESSINFOCLASS InformationClass, // 信息类型 4 OUT PVOID ProcessInformation, // 缓冲指针 5 IN ULONG ProcessInformationLength, // 以字节为单位的缓冲大小 6 OUT PULONG ReturnLength OPTIONAL // 写入缓冲的字节数 7 );
第二个参数是一个枚举类型,其中与反调试有关的成员有ProcessDebugPort(0x7)、ProcessDebugObjectHandle(0x1E)和ProcessDebugFlags(0x1F)。例如将该参数置为ProcessDebugPort,如果进程正在被调试,则返回调试端口,否则返回0。
CheckRemoteDebuggerPresent 调用函数为NtQueryInformationProcess
解决办法
可以对API进程HOOK来处理
1.4 GetLastError
1.5NtQuerySystemInfomation()
可以调用次函数来检测OS是否处于调试状态
1.6NtQueryObject()
系统中某个调试器调试进程的时候,会创建一个调试对象类型的内核对象。检测该对象是否存在就可以判断是否有进程在被调试。
1.7 ZwSetInformationThread()
次函数使用来设置线程信息的,第二个参数ThreadInfomationClass表示线程信息,若其值设置为ThreadHideFromDebugger(0x11),调用该函数后,调试进程会被分离出来,不会对正常运行的进程产生影响。
1.8 TLS回调函数
1.9 可以检测PEB结构中的相关结构来实现反调试。
BeingDebugged
若当前进程处于被调试状态,此值为1,没有被调试为0。
Ldr
主要是因为此结构是处于堆上的内存,被调试进程中未使用的堆内存会被填充为0xFEEEFEEE的内容
破解之法
将此段内存填充为0即可,但此种方法在Win7及以上是不适用的。
ProcessHeap
进程正常运行时。Heap.Flags成员(0XC)的值为0x2,Heap.ForceFlags成员(0x10)的值为0x0,若处于被调试状态,这些值会随之改变。
破解之法
修改成正常值即可
NTGlobalFlag(0x68)
进程被调试的时候,NTGlobalFlags成员的值会被设置为0x70
参考《逆向工程核心原理》