汇编语言学习(6)

2019-08-03 15:03

2.11 Device Drivers

检测内核模式的调试器是否活跃于系统中的典型技术是访问他们的设备驱动程序。该技术相当简单,仅涉及调用kernel32!CreateFile()检测内核模式调试器(如SoftICE)使用的那些众所周知的设备名称。 示例

一个简单的检查如下: push NULL push 0

push OPEN_EXISTING push NULL

push FILE_SHARE_READ push GENERIC_READ

push .szDeviceNameNtice call [CreateFileA]

cmp eax,INVALID_HANDLE_VALUE jne .debugger_found

.szDeviceNameNtice db \

某些版本的SoftICE会在设备名称后附加数字导致这种检查失败,逆向论坛中相关的描述是穷举附加的数字直到发现正确的设备名称。新版壳也用设备驱动检测技术检测诸如Regmon和Filemon之类的系统监视程序的存在。 对策

一种简单的方法就是在kernel32!CreateFileW()内设置断点,断下来后,要么操纵FileName参数要么改变其返回值为INVALID_HANDLE_VALUE(0xFFFFFFFF)。 2.12 OllyDbg:Guard Pages 这个检查是针对OllyDbg的,因为它和OllyDbg的内存访问/写入断点特性相关。 除了硬件断点和软件断点外,OllyDbg允许设置一个内存访问/写入断点,这种类型的断点是通过页面保护11来实现的。简单地说,页面保护提供了当应用程序的某块内存被访问时获得通知这样一个途径。

页面保护是通过PAGE_GUARD页面保护修改符来设置的,如果访问的内存地址是受保护页面的一部分,将会产生一个

STATUS_GUARD_PAGE_VIOLATION(0x80000001)异常。如果进程被OllyDbg调试并且受保护的页面被访问,将不会抛出异常,访问将会被当作内存断点来处理,而壳正好利用了这一点。 示例

下面的示例代码中,将会分配一段内存,并将待执行的代码保存在分配的内存中,然后启用页面的PAGE_GUARD属性。接着初始化标设符EAX为0,然后通过执行内存中的代码来引发STATUS_GUARD_PAGE_VIOLATION异常。如果代码在OllyDbg中被调试,因为异常处理例程不会被调用所以标设符将不会改变。 ;set up exception handler

push .exception_handle push dword [fs:0] mov [fs:0],esp

;allocate memory

push PAGE_READWRITE push MEM_COMMIT push 0x1000 push NULL

call [VirtualAlloc] test eax,eax jz .failed

mov [.pAllocatedMem],eax

;store a RETN on the allocated memory mov byte [eax],0xC3

;then set the PAGE_GUARD attribute of the allocated memory lea eax,[.dwOldProtect] push eax

push PAGE_EXECUTE_READ | PAGE_GUARD push 0x1000

push dword [.pAllocatedMem] call [VirtualProtect]

;set marker (EAX) as 0 xor eax,eax

;trigger a STATUS_GUARD_PAGE_VIOLATION exception call [.pAllocatedMem]

;check if marker had not been changed (exception handler not called) test eax,eax

je .debugger_found

.exception_handler ;EAX = CONTEXT record mov eax,[esp+0xC]

;set marker (CONTEXT.EAX) to 0xFFFFFFFF

;to signal that the exception handler was called mov dword [eax+0xb0],0xFFFFFFFF xor eax,eax retn 对策

由于页面保护引发一个异常,逆向分析人员可以故意引发一个异常,这样异常处理例程将会被调用。在示例中,逆向分析人员可以用INT3指令替换掉RETN指令,一旦INT3指令被执行,Shift+F9强制调试器执行异常处理代码。这样当异常处理例程调用后,EAX将被设为正确的值,然后RETN指令将会被执行。

如果异常处理例程里检查异常是否真地是STATUS_GUARD_PAGE_VIOLATION,逆向分析人员可以在异常处理例程中下断点然后修改传入的ExceptionRecord参数,

具体来说就是ExceptionCode, 手工将ExceptionCode设为STATUS_GUARD_PAGE_VIOLATION即可。

3 断点和补丁检测技

术 本节列举了壳最常用的识别软件断点、硬件断点和补丁的方法。

3.1 Software Breakpoint Detection

软件断点是通过修改目标地址代码为0xCC(INT3/Breakpoint Interrupt)来设置的断点。壳通过在受保护的代码段和(或)API函数中扫描字节0xCC来识别软件断点。 示例

检测可能和下面一样简单: cld

mov edi,Protected_Code_Start

mov ecx,Protected_Code_End - Protected_Code_Start mov al,0xcc repne scasb

jz .breakpoint_found

有些壳对比较的字节值作了些运算使得检测变得不明显,例如: if ( byte XOR 0x55 == 0x99 ) then breakpoint found Where: 0x99 == 0xCC XOR 0x55 对策

如果软件断点被发现了逆向分析人员可以使用硬件断点来代替。如果需要在API内部下断,但是壳又检测API内部的断点,逆向分析人员可以在最终被ANSI版API调用的UNICODE版的API下断(如:用LoadLibraryExW代替LoadLibraryA),或者用相应的native API来代替。

3.2 Hardware Breakpoint Detection 另一种断点称之为硬件断点,硬件断点是通过设置名为Dr0到Dr7的调试寄存器12来实现的。Dr0-Dr3包含至多4个断点的地址,Dr6是个标志,它指示哪个断点被触发了,Dr7包含了控制4个硬件断点诸如启用/禁用或者中断于读/写的标志。

由于调试寄存器无法在Ring3下访问,硬件断点的检测需要执行一小段代码。壳利用了含有调试寄存器值的CONTEXT结构,CONTEXT结构可以通过传递给异常处理例程的ContextRecord参数来访问。 示例

这是一段查询调试寄存器的示例代码: ; set up exception handler

push .exception_handler push dword [fs:0] mov [fs:0],esp

;eax will be 0xFFFFFFFF if hardware breakpoints are identified

xor eax,eax

;throw an exception

mov dword [eax],0

;restore exception handler pop dword [fs:0] add esp,4

;test if EAX was updated (breakpoint identified) test eax,eax

jnz .breakpoint_found :::

.exception_handler ;EAX = CONTEXT record mov eax,[esp+0xc]

;check if Debug Registers Context.Dr0-Dr3 is not zero cmp dword [eax+0x04],0 jne .hardware_bp_found cmp dword [eax+0x08],0 jne .hardware_bp_found cmp dword [eax+0x0c],0 jne .hardware_bp_found cmp dword [eax+0x10],0 jne .hardware_bp_found jmp .exception_ret

.hardware_bp_found

;set Context.EAX to signal breakpoint found mov dword [eax+0xb0],0xFFFFFFFF

.exception_ret

;set Context.EIP upon return add dword [eax+0xb8],6 xor eax,eax retn

有些壳也利用调试寄存器的值作为解密密钥的一部分。这些调试寄存器要么初始化为一个特定值要么为0。因此,如果这些调试寄存器被修改,解密将会失败。当解密的代码是受保护的程序或者脱壳代码的一部分的时候,将导致无效指令并造成程序一些意想不到的终止。 对策

如果壳没检测软件断点,逆向分析人员可以尝试使用软件断点,同样OllyDbg的内存读/写断点也可以使用。当逆向分析人员需要设置API断点的时候在

native或者是UNICODE版的API内部设软件断点也是可行的。

3.3 Patching Detection via Code Checksum Calculation 补丁检测技术能识别壳的代码是否被修改(代码被修改则意味着反调试例程已经被禁用了),其次也能识别是否设置了软件断点。补丁检测是通过代码校验来实现的,校验计算包括从简单到复杂的校验和/哈希算法。 示例

下面是一个比较简单的校验和计算的例子: mov esi,Protected_Code_Start

mov ecx,Protected_Code_End - Protected_Code_Start xor eax,eax .checksum_loop

movzx ebx,byte [esi] add eax,ebx rol eax,1 inc esi

loop .checksum_loop

cmp eax,dword [.dwCorrectChecksum] jne .patch_found 对策

如果代码校验例程识别出了软件断点,可以用硬件断点来代替。如果校验例程识别出了代码补丁,逆向分析人员可以通过在补丁地址设置内存访问断点来定位校验例程所在,一旦发现了校验例程,可以修改校验和为预期的值或者在比较失败后修改适当的标志。

http://hi.http://www.wodefanwen.com//hackbruce/blog/category/??±àó???


汇编语言学习(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:浙江海滨城投三期施组

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: