脱壳学习(二)- 反“反调试”篇

简介: 脱壳学习(二)- 反“反调试”篇

前言


继上一篇《脱壳学习计划1——计算机底层基础》有人私信说想看后续之后,我们就冲冲把2给肝出来了。


今天这篇主要讲述常见的反调试技术和如何绕过反调试的实例。调试无论是在脱壳还是PWN及逆向中都有着很重要的意义,反调试被程序作者用来保护程序不被调试,以此来保护自己的秘密。不过逆行分析人员也有自己的破解反调试的方法,就是“反反调试”


常见反调试


以下是我们经常会遇到到的一些反调试技术,为了好记一点,总结分为以下三类:通过调试的痕迹去识别是否正在被调试、识别调试器行为、干扰调试器功能


1.调试痕迹识别


WindowsAPI

手动检测数据结构

系统痕迹检测


这里最常见得就是手动检测数据结构,也就是检测PEB(PEB表存放进程信息)表BeingDebugged,ProcessHeap,NTGlobalFlag属性,这里有个小知识,32位程序PEB得地址用的是fs:[30],64位程序的地址为gs:[60],位于用户地址空间,进程环境块的地址对于每个进程来说是固定的。如果发现程序中出现引用PEB的地址然后出现程序退出的地址比如sub_401000,那大概率是进行了反调试。

绕过:fs段寄存器偏移0x30h,用ctrl+G可以找到PEB。第一个fs:[30h]+2指向了PEB的BeingDubgged,这是检验反调试的一种技术。BeingDubgged=1的时候就是被调试,这里是第一处反调试。然后我们通常会在fs:[30h]+2把01修改为00或使用插件:PhantOM,勾选hide from PEB。

[fs:[30h]+18]+10,ProcessHeap也是用来测试反调试的的标志。fs:30h+68,NtGlobalFlag反调试。同样是BeingDubgged原理,通过修改调试标志来绕过。

 

2.识别调试器的行为


INT扫描

执行代码校验和检查

时钟监测

判断父进程是否是explorer.exe


这里常用就是时钟监测,计算时间差值,反调试。如果时间过长,判断文件当前正在被调试,就删除文件。我们在OD里找到这个时钟的地方,QueryPerformanceCounter,GetTickCount,

使用nop(汇编代码无操作空指令)就可以绕过,其实原理就是破坏他程序监测反调试的功能。其他几种也是同样的道理,检测都是又程序编写,代码控制,我们只要破坏掉就可以了。

 


3.干扰调试器的功能


使用TLS回调

使用异常

插入中断


这里最常用的也是TLS回调,因为现在OD的插件越来越牛,新版的OD看不出有什么区别,最简单的方法,扔到CFF去看一下目录结构,可以很明确的看到TLS目录(全保护)

然后我们打开IDA可以看到调用的函数

可以看到字符如果当前窗口类名为OLLYDBG“,就退出程序。这个是最简单的干扰,实际上现在常用的OD都已经会隐藏自己的窗口类名了,插件的功能越来越多,TLS回调对于反调试的干扰越来越弱。



实例


以上就是比较常见的反调试。下面就是一个简单的小实例。这里VMProtect3.5进行全保护加壳。代码就很简单,c语言helloword!。

先点击运行,VMP3.5的全保护首先就是要过掉BeingDebugger和NTGLObalflags,我这里用的程序是64位,所以PEB地址为gs:[60],BeingDebugger和NTGLObalflags的地址PEB+2 -> BeingDebugger,PEB + BC ->NTGLObalflags。

删除所有断点:

然后给这两个函数下断点 设置条件断点

NtQueryInformationProcess:函数就可以获取调试端口。若处于调试状态 , 第三个参数会被置为0xFFFFFFFF(-1);若处于非调试状态,第三个参数值会被设置为0。

设定条件断点rdx == 0x07 || rdx ==0x1E


NtSetInformationThread:使用Windows的一个未公开函数的方法,你可以在当前线程里调用NtSetInformationThread,调用这个函数时,如果在第二个参数里指定0x11这个值(意思是ThreadHideFromDebugger),等于告诉操作系统,将所有附加的调试器统统取消掉。设定条件断点rdx == 0x11

然后运行 执行顺序可能不一样 但处理方法一样 我这里先断在了

NtQueryInformationProcess:rdx == 0x07 把r8 置为nullptr(0)

684b16ca850567385f4d6dbd89127aa9_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png再运行,NtQueryInformationProcess:rdx ==0x1E 把r8 置为nullptr(0)执行到返回值

ret返回 并将RAX返回值C0000353

在运行,NtSetInformationThread:rdx == 0x11 将rdx置为3后,禁用这两个断点。

在这两个函数下硬件断点

ntclose 硬件断点:NtClose函数在释放无效句柄时。如果没有被调试,那么函数返回FALSE。如果处于调试状态则会抛出异常C0000008H 并设置条件 rcx == 0xDEADC0DE


NtQuerySystemInformation硬件断点:被 ntdll.dll 导出,当第一个参数传入 0x23 (SystemInterruptInformation) 时,会返回一个SYSTEM_KERNEL_DEBUGGER_INFORMATION 结构,里面的成员KdKdDebuggerEnable 和 KdDebuggerNotPresent 标志系统是否启用内核调试。并设置条件 rcx == 0x23

然后运行如果执行到NtQuerySystemInformation 且rcx==0x23 执行到返回 然后将RAX变为status_unsuccessful(0xC0000001)

然后运行到ntclose 并将RCX设置为0(flase)

然后清除(禁用)所有断点然后运行

也是成功的绕过了反调试,shift+F9运行在进行调试中就不会有任何报错。


以上就是此次关于反调试技术的一些想法分享,下一篇晚点见~


相关文章
|
数据安全/隐私保护
搞个脚本—自动赚猿分(脱壳篇)
搞个脚本—自动赚猿分(脱壳篇)
|
安全 Android开发
[笔记]安卓逆向之动态调试
[笔记]安卓逆向之动态调试
106 0
|
小程序 JavaScript 安全
小程序逆向分析 (一)
小程序逆向分析 (一)
小程序逆向分析 (一)
|
缓存 Java 数据安全/隐私保护
动态调试(24)
debugServer的权限问题
112 0
动态调试(24)
|
安全 编译器 数据库
IDA静态逆向分析工具使用详解
IDA静态逆向分析工具
458 0
|
存储 安全 Java
【Android 逆向】整体加固脱壳 ( 脱壳起点 : 整体加固脱壳 | Dalvik 脱壳机制 : 利用 DexClassLoader 加载过程进行脱壳 | 相关源码分析 )
【Android 逆向】整体加固脱壳 ( 脱壳起点 : 整体加固脱壳 | Dalvik 脱壳机制 : 利用 DexClassLoader 加载过程进行脱壳 | 相关源码分析 )
289 0