静态反调试

静态反调试技术只需要在程序运行之前进行一次破解即可解除全部限制,且不需要二次操作。而且静态反调试技术对于操作系统的依赖性非常大,相同的反调试技术在不同的操作系统表现可能不同。

(待补充)

参考:

https://xz.aliyun.com/t/5685

https://xz.aliyun.com/t/5732/

https://xz.aliyun.com/t/6133


花指令

去花:

IDA - 用 U 取消对应代码段的定义,然后在跳转位置出用热键 C 重新定义即可,中间的垃圾代码nop掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import idautils
def nop(addr,endaddr):
while(addr<endaddr):
PatchByte(addr,0x90)
addr+=1
def undefine(addr,endaddr):
while addr<endaddr:
MakeUnkn(addr,0)
addr+=1
def dejunkcode(addr,endaddr):
while addr<endaddr:
MakeCode(addr)
# 匹配模版
if Byte(addr)==0xe8 and Byte(addr+6)==0x12 and Byte(addr+7)==0x83:
next=addr+10
nop(addr,next)
addr=next
continue
addr+=ItemSize(addr)
dejunkcode(0x00401000,0x00411E40)

SMC

SMC(自修改代码,Self-Modifying Code),就是在真正执行某一段代码时,程序会对自身的该段代码进行自修改,只有在修改后的代码才是可汇编,可执行的。在程序未对该段代码进行修改之前,在静态分析状态下,均是不可读的字节码,IDA之类的反汇编器无法识别程序的正常逻辑。是一种反调试代码技术。

还原方法

  1. 首先确定需要加密的代码部分;
  2. 通过vs查看反汇编(或者OD、IDA等)可以确定对应部分的反汇编代码;
  3. 将这段代码手工用16进制编辑器覆盖为加密后的数据;
  4. 程序执行时则运行事先写好的代码先进行解密再运行。

参考

https://blog.csdn.net/qq_41923479/article/details/80377708
https://blog.csdn.net/palmer9/article/details/105034093

脚本

IDA - File - Script file

1
2
3
4
5
6
7
8
9
10
11
#include <idc.idc>

static main()
{
auto addr = 0x00401216;
auto i = 0;
for(i=0;i<=0x43E;i++)
{
PatchByte(addr+i,Byte(addr+i)^Byte(0x00409080+i));
}
}

MOV混淆

OLLVM混淆(LLVM)

  1. 基于SnowGirlsdeflat,利用angr框架实现去除控制流平坦化。

    python deflat.py -f check_passwd_x8664_flat --addr 0x400530

  2. LLVM多种格式

    xx.c (源代码)

    xx.ll (LLVM字节码的文本表示)

    xx.s (机器汇编码表示的汇编文件)

    xx.bc (LLVM字节码的二进制形式)

    xx.out (可执行的二进制文件)

    img

常用转换:

1
2
3
4
5
clang test.bc -o test
llvm-dis test.bc -o test.ll
llvm-as test.ll -o test.bc
llc test.bc -o test.s
lli test.bc

TLS反调试

ThreadLocalStorage(TLS),是Windows为解决一个进程中多个线程同时访问全局变量而提供的机制。TLS可以简单地由操作系统代为完成整个互斥过程,也可以由用户自己编写控制信号量的函数。当进程中的线程访问预先制定的内存空间时,操作系统会调用系统默认的或用户自定义的信号量函数,保证数据的完整性与正确性。

而当Coder选择使用自己编写的信号量函数时,在应用程序初始化阶段,系统将要调用一个由用户编写的初始化函数以完成信号量的初始化以及其他的一些初始化工作。此调用必须在程序真正开始执行到入口点之前就完成,以保证程序执行的正确性。

TLS回调函数的执行,与数据的初始化,都在程序入口点之前执行,TLS是整个程序最早运行的地方,所以可以用这个特性,执行一些特殊操作。然后在最后程序退出时还会调用一次。

TLS反调试:

往定义的TLS函数里写代码。 OD调试程序的时候,要先找到程序的入口点,跟拿着钥匙开门一样,找到孔,才能插钥匙。TLS回调函数,由于可以在程序中最早运行的时候执行,可以把在调试器检测到入口点之前,它自己检测是否存在调试。例如,检测加载环境是不是“OllyDbg”等。

解法:

可以通过patch掉TLS回调来反反调试,但既然它用到了isDebuggerPresent,我们也可以通过nop填充来让调试能够继续运行。

SEH

如果程序引发了异常,程序将利用Windows的一种异常处理机制 SEH(Structured Exception Handling)机制处理异常,在处理过程中对程序进行一定的修改。常见形式:__try{...} __except(filter){...}

由于SEH中的很多代码不会被IDA反编译出来,所以它常常被用来反静态分析:程序员在try块中的某些情况下故意触发一些异常,来执行except块中他们想要隐藏起来的代码。

简而言之,就像它们的名字一样,程序先执行try块中的逻辑,如果try中产生了一些异常的情况(可以简单理解为程序发生了一些意外),就会执行except中的代码来处理异常;反之,如果try块中没有产生异常,except块就不会被执行。