转自看雪
PxAUsY 原文地址 v35!?
5{ K>a@AXC bM@8[&ta [1]引言
g$?kL K
^6fg,& 本文对基于Windows NT的操作系统上使用的几种反调试技术进行了分类和介绍。
"gIjU~'A A#;TY:D2 反调试技术是程序检测它是否在调试器(Debugger)下运行的方法。反调试技术被用于商业可执行程序的保护,加壳工具以及病毒等,以杜绝或减缓软件被逆(向工程)
mMt~4(5 w^EUBRI- 我们假设程序是在r3 debugger下进行分析的,例如Windows平台上的OD。本文面向逆向工程师和恶意软件分析师。
ta 请注意,我们将纯粹谈论通用的反调试和反跟踪技术。此文不会涉及特定的调试器检测,例如窗口或进程的枚举,注册表扫描等。
=6YffXa_s "|,;~k1 [2]反调试和反跟踪技术
PI-o)U$Ehv T[(4z@d`5 - 利用内存差
cXDG(.!n7B ]ykMh (1) kernel32!IsDebuggerPresent
!C6[m1F 如果正在调试进程,则IsDebuggerPresent返回1,否则返回0。此API只读取PEB!BeingDebugged 的byte-flag(位于PEB结构中的偏移 2)。
-a+oQP]O 绕过它就只需要 PEB!BeingDebugged 设置为 0
x<=<Lx0B; 例:
sUe<21: - call IsDebuggerPresent
- test eax, eax
- jne @DebuggerDetected
- ...
]r&dWF o[Gp *o\ (2) PEB!IsDebugged
!
<
O,xI' 8+|7*Ud
该字段引用进程的Process Environment Block(进程环境块/区间?)中的第二个字节. 被调试期间会由系统设置为非0, 该字节可以被重置为0,而不会对程序的执行过程产生影响(因为这是一个信息标志).
c{(4s6D (~U1X4 例:
M[:},?ah0 - mov eax, fs:[30h]
- mov eax, byte [eax+2]
- test eax, eax
- jne @DebuggerDetected
- ...
IKs2.sj"o 6'a
1]K (3) PEB!NtGlobalFlags
.9uw@Eq 当有进程被创建时,系统会设置一些标志,这些标志将定义各种API对此进程的行为。这些标志可以在PEB中被读取,位于偏移量0x68的DWORD中.
L"x9O'U 默认情况下,根据是否在Debugger下创建了进程而设置不同的NtGlobalFlags标志。如果调试了该进程,将出现一些控制ntdll中的常规堆栈操作的flags:
h*lU&8)m\ F(去)L(掉)G_HEAP_ENABLE_TAIL_CHECK,
{G i:W/jJ F(去)L(掉)G_HEAP_ENABLE_FREE_CHECK,
znq/
%7 F(去)L(掉)G_HEAP_VALIDATE_PARAMETERS.
]"X} FU 可以通过重置NtGlobalFlags字段来绕过这种反调试技术。
.dw;b~p 例:
b%_[\(( - mov eax, fs:[30h]
- mov eax, [eax+68h]
- and eax, 0x70
- test eax, eax
- jne @DebuggerDetected
- ...
+Rq7m] )4O* D92 (4) Heap flags(堆栈标志)
}"
\
jB #J w\pOn 如前所述,NtGlobalFlags标注常规堆栈将会出现什么样的行为。虽然很容易修改PEB字段,但如果堆栈的行为与程序未被调试的时候的行为方式不同,则可能会出现问题。这是一个挺厉害的反调试机制,因为进程堆很多,并且它们的chunks可以单独受F(去)L(掉)G_HEAP_* flags(例如chunk尾端)的影响。堆栈头部也会受到影响。例如,检查堆栈头中的字段ForceFlags(偏移量0x10)可用于检测Debugger的存在与否。
\L5h&