脱壳的艺术(精品)

上传人:壹****1 文档编号:439190724 上传时间:2022-12-12 格式:DOC 页数:38 大小:693.50KB
返回 下载 相关 举报
脱壳的艺术(精品)_第1页
第1页 / 共38页
脱壳的艺术(精品)_第2页
第2页 / 共38页
脱壳的艺术(精品)_第3页
第3页 / 共38页
脱壳的艺术(精品)_第4页
第4页 / 共38页
脱壳的艺术(精品)_第5页
第5页 / 共38页
点击查看更多>>
资源描述

《脱壳的艺术(精品)》由会员分享,可在线阅读,更多相关《脱壳的艺术(精品)(38页珍藏版)》请在金锄头文库上搜索。

1、脱壳的艺术Mark Vincent Yason概述:脱壳是门艺术脱壳既是一种心理挑战,同时也是逆向领域最为激动人心的智力游戏之一。为了甄别或解决非常难的反逆向技巧,逆向分析人员有时不得不了解操作系统的一些底层知识,聪明和耐心也是成功脱壳的关键。这个挑战既牵涉到壳的创建者,也牵涉到那些决心躲过这些保护的脱壳者。本文主要目的是介绍壳常用的反逆向技术,同时也探讨了可以用来躲过或禁用这些保护的技术及公开可用的工具。这些信息将使研究人员特别是恶意代码分析人员在分析加壳的恶意代码时能识别出这些技术,当这些反逆向技术阻碍其成功分析时能决定下一步的动作。第二个目的,这里介绍的信息也会被那些计划在软件中添加一些

2、保护措施用来减缓逆向分析人员分析其受保护代码的速度的研究人员用到。当然没有什么能使一个熟练的、消息灵通的、坚定的逆向分析人员止步的。关键词:逆向工程、壳、保护、反调试、反逆向1简介 在逆向工程领域,壳是最有趣的谜题之一。在解谜的过程中,逆向分析人员会获得许多关于系统底层、逆向技巧等知识。壳(这个术语在本文中既指压缩壳也包括加密壳)是用来防止程序被分析的。它们被商业软件合法地用于防止信息披露、篡改及盗版。可惜恶意软件也基于同样的理由在使用壳,只不过动机不良。由于大量恶意软件存在加壳现象,研究人员和恶意代码分析人员为了分析代码,开始学习脱壳的技巧。但是随着时间的推移,为防止逆向分析人员分析受保护的

3、程序并成功脱壳,新的反逆向技术也被不断地添加到壳中。并且战斗还在继续,新的反逆向技术被开发的同时逆向分析人员也在针锋相对地发掘技巧、研究技术并开发工具来对付它们。本文主要关注于介绍壳所使用的反逆向技术,同时也探讨了躲过/禁用这些保护措施的工具及技术。可能有些壳通过抓取进程映像(dump)能够轻易被搞定,这时处理反逆向技术似乎没有必要,但是有些情况下加密壳的代码需要加以跟踪和分析,例如:需要躲过部分加密壳代码以便抓取进程映像、让输入表重建工具正确地工作。深入分析加密壳代码以便在一个反病毒产品中整合进脱壳支持。此外,当反逆向技术被恶意程序直接应用,以防止跟踪并分析其恶意行为时,熟悉反逆向技术也是很

4、有价值的。本文绝不是一个完整的反逆向技术的清单,因为它只涵盖了壳中常用的、有趣的一些技术。建议读者参阅最后一节的链接和图书资料,以了解更多其他逆向及反逆向的技术。笔者希望您觉得这些材料有用,并能应用其中的技术。脱壳快乐!2 调试器检测技术 本节列出了壳用来确定进程是否被调试或者系统内是否有调试器正在运行的技术。这些调试器检测技术既有非常简单(明显)的检查,也有涉及到native APIs和内核对象的。2.1 PEB.BeingDebugged Flag : IsDebuggerPresent()最基本的调试器检测技术就是检测进程环境块(PEB)1中的BeingDebugged标志。kernel

5、32!IsDebuggerPresent() API检查这个标志以确定进程是否正在被用户模式的调试器调试。下面显示了IsDebuggerPresent() API的实现代码。首先访问线程环境块(TEB)2得到PEB的地址,然后检查PEB偏移0x02位置的BeingDebugged标志。moveax, large fs: 18hmov eax, eax+30hmovzxeax, byte ptr eax+2retn除了直接调用IsDebuggerPresent(),有些壳会手工检查PEB中的BeingDebugged标志以防逆向分析人员在这个API上设置断点或打补丁。示例下面是调用IsDebug

6、gerPresent() API和使用PEB.BeingDebugged标志确定调试器是否存在的示例代码。;call kernel32!IsDebuggerPresent()callIsDebuggerPresenttesteax,eaxjnz.debugger_found;check PEB.BeingDebugged directlyMoveax,dword fs:0x30;EAX = TEB.ProcessEnvironmentBlockmovzxeax,byte eax+0x02;AL = PEB.BeingDebuggedtesteax,eaxjnz.debugger_found由于

7、这些检查很明显,壳一般都会用后面章节将会讨论的垃圾代码或者反反编译技术进行混淆。对策人工将PEB.BeingDebugged标志置0可轻易躲过这个检测。在数据窗口中Ctrl+G(前往表达式)输入fs:30,可以在OllyDbg中查看PEB数据。另外Ollyscript命令dbh可以补丁这个标志。dbh最后,Olly Advanced3 插件有置BeingDebugged标志为0的选项。2.2 PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlagsPEB.NtGlobalFlag PEB另一个成员被称作NtGlobalFlag(偏移0x68),壳也通

8、过它来检测程序是否用调试器加载。通常程序没有被调试时,NtGlobalFlag成员值为0,如果进程被调试这个成员通常值为0x70(代表下述标志被设置):FLG_HEAP_ENABLE_TAIL_CHECK(0X10)FLG_HEAP_ENABLE_FREE_CHECK(0X20)FLG_HEAP_VALIDATE_PARAMETERS(0X40)这些标志是在ntdll!LdrpInitializeExecutionOptions()里设置的。请注意PEB.NtGlobalFlag的默认值可以通过gflags.exe工具或者在注册表以下位置创建条目来修改:HKLMSoftwareMicrosof

9、tWindows NtCurrentVersionImage File Execution OptionsHeap Flags 由于NtGlobalFlag标志的设置,堆也会打开几个标志,这个变化可以在ntdll!RtlCreateHeap()里观测到。通常情况下为进程创建的第一个堆会将其Flags和ForceFlags4分别设为0x02(HEAP_GROWABLE)和0 。然而当进程被调试时,这两个标志通常被设为0x50000062(取决于NtGlobalFlag)和0x40000060(等于Flags AND 0x6001007D)。默认情况下当一个被调试的进程创建堆时下列附加的堆标志将被

10、设置:HEAP_TAIL_CHECKING_ENABLED(0X20)HEAP_FREE_CHECKING_ENABLED(0X40)示例下面的示例代码检查PEB.NtGlobalFlag是否等于0,为进程创建的第一个堆是否设置了附加标志(PEB.ProcessHeap):;ebx = PEBMovebx,fs:0x30;Check if PEB.NtGlobalFlag != 0Cmpdword ebx+0x68,0jne.debugger_found;eax = PEB.ProcessHeapMoveax,ebx+0x18;Check PEB.ProcessHeap.FlagsCmpdwo

11、rd eax+0x0c,2jne.debugger_found;Check PEB.ProcessHeap.ForceFlagsCmpdword eax+0x10,0jne.debugger_found对策可以将 PEB.NtGlobalFlag和PEB.HeapProcess标志补丁为进程未被调试时的相应值。下面是一个补丁上述标志的ollyscript示例:Varpebvarpatch_addrvarprocess_heap/retrieve PEB via a hardcoded TEB address( first thread: 0x7ffde000)Movpeb,7ffde000+3

12、0/patch PEB.NtGlobalFlagLeapatch_addr,peb+68movpatch_addr,0/patch PEB.ProcessHeap.Flags/ForceFlagsMovprocess_heap,peb+18leapatch_addr,process_heap+0cmovpatch_addr,2leapatch_addr,process_heap+10movpatch_addr,0同样地Olly Advanced插件有设置PEB.NtGlobalFlag和PEB.ProcessHeap的选项。2.3 DebugPort: CheckRemoteDebuggerP

13、resent()/NtQueryInformationProcess()Kernel32!CheckRemoteDebuggerPresent()是另一个可以用于确定是否有调试器被附加到进程的API。这个API内部调用了ntdll!NtQueryInformationProcess(),调用时ProcessInformationclass参数为ProcessDebugPort(7)。而NtQueryInformationProcess()检索内核结构EPROCESS5的DebugPort成员。非0的DebugPort成员意味着进程正在被用户模式的调试器调试。如果是这样的话,ProcessInf

14、ormation 将被置为0xFFFFFFFF ,否则ProcessInformation 将被置为0。Kernel32!CheckRemoteDebuggerPresent()接受2个参数,第1个参数是进程句柄,第2个参数是一个指向boolean变量的指针,如果进程被调试,该变量将包含TRUE返回值。BOOL CheckRemoteDebuggerPresent( HANDLEhProcess, PBOOL pbDebuggerPresent)ntdll!NtQueryInformationProcess()有5个参数。为了检测调试器的存在,需要将ProcessInformationclass参数设为ProcessDebugPort(7):NTSTATUS NTAPI NtQueryInformationProcess(HANDLE ProcessHandle,PROCESSINFOCLASS ProcessInformationClass,PVOID ProcessInformation,ULONG ProcessInformationLength,PULONG ReturnLength)示例下面的例子显示了如何调用CheckRemoteDebuggerPresent()和NtQueryInformationProcess()来

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号