• 2564阅读
  • 0回复

[转贴]Windows系统下的反调试机制(翻译自Symantec官网) [复制链接]

上一主题 下一主题
离线iokey
 

发帖
15
金钱
854
威望
759
贡献值
0
诚信值
0
社区警告
0
纠纷记录
0
冻结资金
0
保证金
0
只看楼主 倒序阅读 楼主   发表于: 2019-06-23
转自看雪 *9:oTN  
原文地址 |GuIp8~  
we'<Y  
/ hUuQDJ  
[1]引言 s_]p6M  
/H#- \r&r  
本文对基于Windows NT的操作系统上使用的几种反调试技术进行了分类和介绍。 iVq4&X_x  
 .G}E  
反调试技术是程序检测它是否在调试器(Debugger)下运行的方法。反调试技术被用于商业可执行程序的保护,加壳工具以及病毒等,以杜绝或减缓软件被逆(向工程) XL[/)lX{  
u] C/RDTH  
我们假设程序是在r3 debugger下进行分析的,例如Windows平台上的OD。本文面向逆向工程师和恶意软件分析师。 { 3``To$  
请注意,我们将纯粹谈论通用的反调试和反跟踪技术。此文不会涉及特定的调试器检测,例如窗口或进程的枚举,注册表扫描等。 >! +.M9  
]zp5 6U|xa  
[2]反调试和反跟踪技术 ;>^oe:@  
1I({2@C  
- 利用内存差 p- 5)J&  
2p\CCzw  
(1) kernel32!IsDebuggerPresent xml@]N*D#E  
如果正在调试进程,则IsDebuggerPresent返回1,否则返回0。此API只读取PEB!BeingDebugged 的byte-flag(位于PEB结构中的偏移 2)。 DLMG <4Cd~  
绕过它就只需要 PEB!BeingDebugged 设置为 0 4d&#NP  
例: o(xRq;i  
  1. call IsDebuggerPresent
  2. test eax, eax
  3. jne @DebuggerDetected
  4. ...
IV{,'+hT  
[8*Ovd  
(2) PEB!IsDebugged '\%c "?  
n}==  
该字段引用进程的Process Environment Block(进程环境块/区间?)中的第二个字节. 被调试期间会由系统设置为非0, 该字节可以被重置为0,而不会对程序的执行过程产生影响(因为这是一个信息标志). .DSn H6O  
2 qRX A  
例: 3wXmX  
  1. mov eax, fs:[30h]
  2. mov eax, byte [eax+2]
  3. test eax, eax
  4. jne @DebuggerDetected
  5. ...
/lAB  
;\`~M  
(3) PEB!NtGlobalFlags xe^*\6Y  
当有进程被创建时,系统会设置一些标志,这些标志将定义各种API对此进程的行为。这些标志可以在PEB中被读取,位于偏移量0x68的DWORD中. *8}Y0V\s  
默认情况下,根据是否在Debugger下创建了进程而设置不同的NtGlobalFlags标志。如果调试了该进程,将出现一些控制ntdll中的常规堆栈操作的flags: \)'nxFKqV  
F(去)L(掉)G_HEAP_ENABLE_TAIL_CHECK, >cwyb9;!kK  
F(去)L(掉)G_HEAP_ENABLE_FREE_CHECK, -q7A\8C  
F(去)L(掉)G_HEAP_VALIDATE_PARAMETERS. )6|7L)Dk  
可以通过重置NtGlobalFlags字段来绕过这种反调试技术。 QS2J271E}  
例: Zu(eYH=Q  
  1. mov eax, fs:[30h]
  2. mov eax, [eax+68h]
  3. and eax, 0x70
  4. test eax, eax
  5. jne @DebuggerDetected
  6. ...
~~:w^(s9  
"8K >Yu17  
(4) Heap flags(堆栈标志) 8r[ZGUV  
vQrce&  
如前所述,NtGlobalFlags标注常规堆栈将会出现什么样的行为。虽然很容易修改PEB字段,但如果堆栈的行为与程序未被调试的时候的行为方式不同,则可能会出现问题。这是一个挺厉害的反调试机制,因为进程堆很多,并且它们的chunks可以单独受F(去)L(掉)G_HEAP_* flags(例如chunk尾端)的影响。堆栈头部也会受到影响。例如,检查堆栈头中的字段ForceFlags(偏移量0x10)可用于检测Debugger的存在与否。 9tZ)#@\  
?]%JQ]Gf*  
有两种简单的方法来避开这种检测机制: #.O,JG#H  
SQ#6~zxl  
- 1.创建一个未被调试的进程,并在创建进程后附加调试器(一个简单的解决方案是创建进程挂起,直至运行达到Entry-Point,将Entry-Point跳转至无​​限循环,恢复进程,附加调试器,并恢复原始Entry-Point)。 ?fv?6r  
xGbr>OqkTX  
- 2.通过注册表项“HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options”强制NtGlobalFlags为我们要调试的进程赋值:创建一个名为你要运行的进程名称的子键(非值),并在这个子键,String值“GlobalFlags”设置为空。 "%~\kJ(G  
gyH'92ck  
例: e;b,7Qw  
  1. mov eax, fs:[30h]
  2. mov eax, [eax+18h] ;process heap
  3. mov eax, [eax+10h] ;heap flags
  4. test eax, eax
  5. jne @DebuggerDetected
  6. ...
~82[pY  
1|Y(XB^os(  
(5) Vista anti-debug (没起名字) N[ 4v6GS  
x_1JQDE  
我估计没人再用Vista了,再加上我对Vista机制也不熟悉,就偷了个懒。原文如下: `B+%W  
{#q']YDe`  
Here's an anti-debug specific to Windows Vista that I found by comparing memory dumps of a program running with and without control of a debugger. I'm not sure of its realiability, but it's worth mentionning (tested on Windows Vista 32 bits, SP0, English version). <*L=u;  
r}) 2-3ZA9  
When a process is debugged, its main thread TEB, at offset 0xBFC, contains a pointer to a unicode string referencing a system dll. Moreover, the string follows this pointer (therefore, located at offset 0xC00 in the TEB). If the process is not debugged, the pointer is set to NULL and the string is not present. T!$7:% D  
 f])?Gw  
Example: a2W}Wb+  
  1. call GetVersion
  2. cmp al, 6
  3. jne @NotVista
  4. push offset _seh
  5. push dword fs:[0]
  6. mov fs:[0], esp
  7. mov eax, fs:[18h] ; teb
  8. add eax, 0BFCh
  9. mov ebx, [eax] ; pointer to a unicode string
  10. test ebx, ebx ; (ntdll.dll, gdi32.dll,...)
  11. je @DebuggerNotFound
  12. sub ebx, eax ; the unicode string follows the
  13. sub ebx, 4 ; pointer
  14. jne @DebuggerNotFound
  15. ;debugger detected if it reaches this point
  16. ;...
h"VQFqQy  
uY0V!W  
- 利用系统差 /nXp5g^6(  
Wz$%o'OnC  
(1) NtQueryInformationProcess MhC 74G  
n<MMO=+bg  
ntdll!NtQueryInformationProcess 是ZwQueryInformationProcess系统调用的打包 M,V+bt  
'G 6TSl  
它的原型如下: <B6@q4Q  
  1. NTSYSAPI NTSTATUS NTAPI NtQueryInformationProcess(
  2. IN HANDLE ProcessHandle,
  3. IN PROCESS_INFORMATION_CLASS ProcessInformationClass,
  4. OUT PVOID ProcessInformation,
  5. IN ULONG ProcessInformationLength,
  6. OUT PULONG ReturnLength
  7. );
eydVWVN  
f uojf+i  
当被call时的ProcessInformationClass被设置为7(ProcessDebugPort constant)时,进程被调试的话,系统会将ProcessInformation 设置为 -1. ;SQ<^ "eK  
H3{x; {.b  
这是一个强大的反调试机制,没有很简单的方法来绕开。但是,如果跟踪程序,则可以在syscall返回时修改ProcessInformation。 GypZ!)1   
pM~Xh ]/  
另一种解决方案是使用系统驱动Hook ZwNtQueryInformationProcess !- f>*|@  
:1u>T3L.z  
绕过NtQueryInformationProcess将能绕过许多反调试机制的检测(例如CheckRemoteDebuggerPresent或UnhandledExceptionFilter) k hT&[!J{>  
1A^iUC5)  
例: 9dA(f~  
g!n1]- 1  
  1. push 0
  2. push 4
  3. push offset isdebugged
  4. push 7 ;ProcessDebugPort
  5. push -1
  6. call NtQueryInformationProcess
  7. test eax, eax
  8. jne @ExitError
  9. cmp isdebugged, 0
  10. jne @DebuggerDetected
  11. ...
 p>v,b&06  
mY-Z$8r  
(2) kernel32!CheckRemoteDebuggerPresent J*6I@_{/ U  
8)/i\=N3;  
此API有两个参数:Process Handle,Ptr* DWORD. 如果调用成功,则在调试进程时,DWORD值将设置为1。 Wu)ATs}  
Sp)KtMV  
内部来说,此API将ProcessInformationClass设置为ProcessDebugPort (7)后调用ntdll!NtQueryInformationProcess Okk[}G)  
eux _tyC  
例: 7=XQgbY/  
  1. push offset isdebugged
  2. push -1
  3. call CheckRemoteDebuggerPresent
  4. test eax, eax
  5. jne @DebuggerDetected
  6. ...
WO*yJ`9]  
zO{$kT\r&  
(3) UnhandledExceptionFilter ^&<~6y}U^  
~\dpD  
当发生异常时,使用Windows XP SP>=2,Windows 2003和Windows Vista时,操作系统处理异常的常用方法是: bGRI^ [8#+  
O<4i)Lx2  
- 如果有异常,将控制权传递给每个进程的Vectored Exception Handlers。 vl$! To9R"  
:NU-C!eT  
- 如果异常未被处理,则将控制权传递给每个线程顶部SEH handler,由生成异常的线程中的FS:[0]指向。如果异常未被SEH中的前一个SEH handler所处理,则SEH形成SEH链并且依次调用SEH。 a:@9GmtV&  
]i*q*]x2u  
- 如果任何先前的处理方法尚未成功处理异常,则最终的SEH处理程序(由系统设置)将调用kernel32!UnhandledExceptionFilter。该函数将决定它应该做什么,具体取决于是否调试过程。 )hk=wu6  
C>cc! +n%H  
- 如果未被调试,它将调用用户定义的过滤器函数(通过kernel32!SetUnhandledExceptionFilter设置)。 ^vm[`M  
i]GBu  
- 如果已被调试,程序将被终止。 pH#&B_S6z=  
hM E|=\  
UnhandledExceptionFilter中的调试器检测是使用ntdll!NtQueryInformationProcess进行的。 etf ft8  
4,9AoK)yp  
例: =f@O~nGm  
  1. push @not_debugged
  2. call SetUnhandledExceptionFilter
  3. xor eax, eax
  4. mov eax, dword [eax] ; trigger exception
  5. ;program terminated if debugged
  6. ;...
  7. @not_debugged:
  8. ;process the exception
  9. ;continue the execution
  10. ;...
tYIHsm\b  
322W"qduTZ  
^7q=E@[e  
-----------------------------------------------分割线----------------------------------------------------------------------- $gDp-7  
U[d/ `  
今天实在太晚了,明天还得早起,就先翻译这些,如果觉得还需要继续翻译的请留言咯。:D L1BpkB  
uZZ[`PA(  
广海社区提醒您:
1.忘记账号、密码、安全问题等常见站务问题,请查看论坛左上角站点帮助
2.请理性对待商业信息,如有交易,强烈建议您选择广海中介进行交易
3.欢迎购买广海社区广告位,感谢您的支持,报价及位置详见广海社区广告服务
4.特殊会员售价50元,积分(金钱和威望)无限,更多权限,欢迎到广海淘宝购买
5.广海社区唯一域名ghoffice.net,唯一QQ190959022,其他均为假冒,谨防上当受骗
6.如您被骗,请查看广海社区举报中心,按照要求和流程提交举报材料,未经核实的举报帖子将一律删除
7.如您发现违规违法内容,欢迎点击帖子右下角举报按钮进行举报,也可到站务办公版块匿名发帖举报
免责声明
文中内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。 私下交易造成损失的,本站概不负责。
 
快速回复
限150 字节
批量上传需要先选择文件,再选择上传
 
上一个 下一个