多摘自NU1L的《0到1》
抵御静态分析
花指令:
指在程序中完全冗余,不会影响程序功能,但会干扰逆向的指令。没有固定形式。
脏字节:
会导致反汇编或反编译解析错误的多余字节(或指令)
反正就是很奇怪的指令多半就有问题
遇到花指令或者脏字节需要仔细分析上下文,找到有毛病的指令或字节进行patch
指令替换(变形)
还有一些题目为达成混淆效果,会故意将一些指令用其他指令来实现相同或类似的功能。如
1 | call addr |
代码自修改(SMC)
原理就是在算法脚本中认为地写一段代码将可执行代码修改,让 真正执行的代码不在静态分析中出现。
一般,SMC的代码在ida工具中会被识别为数据,但会将该数据的地址当作函数指针并进行调用。
解决方案:
- 静态分析SMC代码的自修改过程并复现出真正执行的代码
- 动态分析至SMC代码解密完毕出并设置断点,然后往下接着分析
加密
主要是指对数据,代码,指令等进行加密保护,VMProtect是一种很强的加密壳。(这个就先记到这个程度)
反调试
概念:指在程序代码中运用若干种反调试技术,干扰对某个进程进行动态调试、逆向分析的手段。
简单来说就是:检测到你正在动态调试程序,然后执行干扰代码。
如:
- Windows下正在被调试的进程的PEB中的BeingDebugged字段会被置为true,由此诞生了
IsDebuggerPresent()
API,用来检测当前进程是否正在被调试。 - Linux下调用的ptrace也是类似的道理
Windows API:
- IsDebuggerPresent()
- CheckRemoteDebuggerPresent()
- NtQueryInformationProcess()
绕过方法:
- 手动:找到反调试语句所在,进行相应修改绕过
- ScyllaHide
时间间隔检测
单步跟踪的时候指令运行所耗费的时间长得多,基于此来检测
如:x86cpu中存在一个TSC(时间戳计数器)的64位寄存器RDTSC
指令会将TSC的值读入EDX:EAX寄存器中。一般实现这种反调试只需探测TSC的低32位变化量(即EAX的变化量)。绕过方法:在没有变化量下界的情况下,将所有相关RDTSC(0F 32)
指令替换成xor eax(33 C0)
基于异常的反调试
这个还没见过,所以先不细学,记个大概
绕过方法一般是对所使用的调试器进行配置,使之忽略程序产生的特定异常。
对于x64dbg而言:顶部菜单->选项->选项->异常->添加上次忽略上一个产生的异常类型。其他调试器同理。
TLS反调试
**Thread local Storage(TLS)**,即线程本地存储,是为解决一个进程中多个线程同时访问全局变量而提供的机制。Windows提供了TLS回调函数机制,借此实现反调试。
解决方案:IDA静态分析下可以很好地识别TLS回调函数。动态调试以x64dbg为例,顶部菜单->选项->选项->事件中勾选“TLS回调函数”项,再调试程序,会停在TLS回调函数被调用前,然后再跟踪分析
特定调试器检测
就是检测所用调试器
断点检测
这个大概看了一遍,没太搞懂,先放着(也还没见过)
Comments