信息安全工程学院逆向工程技术lybliu@cuit.edu.cn,QQ:16807256(教务处教务管理教师课件)授课教师:刘云本信息安全工程学院一个简单的加壳软件的例子:加壳前:信息安全工程学院加壳后:信息安全工程学院信息安全工程学院信息安全工程学院程序运行壳代码解密得到原来的代码:信息安全工程学院加壳程序给原程序加壳的过程:1.添加一个分节;2.为新分节添加代码(这个代码即为壳代码,用于解密加密后的section)3.找到第一个代码节(即有executable属性的节)4.将找到的代码节进行加密。第13章脱壳技术壳和病毒很类似,都需要比原程序代码更早地获取控制权。壳修改了原程序的组织结构和执行流程,能够比原程序提前获得控制权,而不会影响原程序执行。13.1.1壳的加载过程脱壳技术一般壳的主要加载过程实际上可以将外壳程序看做是程序的一个子函数,这个子函数的两个主要功能就是解密+LoadPE(加载原始程序)壳的加载过程IAT和重定位表项的处理即:PE加载器信息安全工程学院脱壳技术1.保存程序入口参数加壳程序初始化是保存各个寄存器的值,外壳执行完毕后,再恢复各个寄存器的值最后再跳到原程序执行。通常使用pushad/popad,pushfd/popfd等指令来保存和恢复现场。壳的加载过程PUSHAD(压栈)外壳开始时保护现场POPAD(出栈)外壳结束时恢复现场,OEP(原始入口点)一般就在附近信息安全工程学院2.获取壳自己所需要使用的API的地址一般外壳的输入表中只有GetProcAddress、GetMoudleHandle和LoadLibrary这几个API函数,甚至只有kernel32.dll以及GetProcAddress,而壳运行一般需要更多的API函数,为了隐藏这些API,它一般只在壳的代码中用显式方式动态加载这些API函数。一般是通过三个函数来完成:壳的加载过程信息安全工程学院脱壳技术HINSTANCELoadLibrary(LPCTSTRlpLibFileName)//dll文件名返回值:成功返回模块句柄,失败返回NULLFARPROCGetProcAddress(HMODULEhModule,//DLL模块句柄LPCSTRlpProcName)//函数名HMODULEGetModuleHandle(LPCTSTRlpModuleName)//dll文件名返回值:成功返回模块句柄,失败返回NULL一些程序甚至连GetProcAddress函数都不用,而是自己写个相同功能的函数实现。信息安全工程学院脱壳技术3.解密原始程序各个区块(section)的数据壳出于保护原程序的目的,一般都会加密或者压缩原程序各个区块。在程序执行时,会由外壳程序将各个区块的数据进行解密,以让程序正常运行。壳一般是按区块进行加密的,那么解密时也是按照区块进行解密的,并且会把解密的区块数据按照区块的定义放在合适的内存位置中。壳的加载过程脱壳技术外壳程序解密和解压缩各个区段将解压后的程序写入到内存中对应的位置壳的加载过程脱壳技术4.IAT初始化由于加壳时外壳程序自己构建了一个输入表,并让PE头文件中的输入表指针指向了自建的输入表。所以,PE装载器只会对自建的输入表进行填写。原来PE的输入表的填写,只好由外壳程序来实现。外壳要做就是将这个新的输入表结构从头到尾扫描一遍,对每一个DLL所引入的所有函数重新获取地址,并填写在IAT中。壳的加载过程脱壳技术5、重定位项处理进行重定位项处理的主要是在被加壳的DLL文件中,因为原程序的最终加载过程是由外层程序来加载到内存中,而DLL文件由于被加载时需要进行重定位处理,所以针对加壳后的DLL文件,外壳程序需要进行重定位(因为EXE总是会被加载到优先加载的基地址(如0x00400000),所以不要进行重定位处理)。壳的加载过程信息安全工程学院脱壳技术6.跳转到程序入口点(OEP)OEP(OriginalEntryPoint)原始入口点,当程序完成上述操作后,就会跳转到原始的程序入口点去执行,因此这里就是外壳程序和原始程序的“分界线”,我们进行脱壳时就是找到程序的原始入口点,然后将相应的程序代码从内存空间中拷贝出来(dump)得到原始程序。壳的加载过程脱壳技术脱壳就是找到程序的原始入口点,然后dump出内存中数据到文件,并修复成一个可运行文件。手动脱壳步骤脱壳有时可以使用“脱壳机”,脱壳机就是专门针对一些常见壳而开发的脱壳软件,但往往这些脱壳机是针对一些比较标准的加壳软件,程序外壳稍加改动,脱壳机便无法正常脱壳,因此有很大局限性,掌握手动脱壳的方法对一些变形的壳会很有帮助。信息安全工程学院脱壳技术手动脱壳主要分四步:1、查壳2、查找程序的原始入口点(OEP)3、抓取内存映像文件4、PE文件(输入表)重建手动脱壳步骤查壳查壳寻找OEPDump文件修复通过OD动态调试跟踪到入口处PEiD、FiOD、LoadPE等工具读取内存数据并写入文件利用ImportREC等工具修复输入表或手动修复脱壳技术查壳可以通过查壳软件来查询,一般使用PEiD和Fi来进行查询,查壳软件查到的壳不一定准确。手动脱壳步骤PEiD查壳结果:使用Fi查壳结果:脱壳技术手动脱壳步骤脱壳技术寻找OEP就是寻找程序的原始入口点。由于程序在运行时会完成解密和解压缩操作,最后会跳转到程序原始入口点,因此通过动态跟踪就可以找到程序入口位置。脱壳方法脱壳技术寻找OEP一般通过以下方法:方法一:单步跟踪法(根据跨段指令寻找OEP)该方法针对一些简单的壳可以使用这种方法,用OD载入程序后,单步执行F8,一直跟踪到程序大跳转时,开始dump内存。脱壳方法脱壳技术方法二:ESP定律法(根据堆栈平衡原理找OEP)由于外壳程序在开始运行时需要保护现场,结束后恢复现场,从而保持堆栈平衡。外壳执行前外壳执行后脱壳方法,在外壳执行完pushad/pushfd后,对ESP指向的内存地址设置硬件访问断点(hresp),然后F9运行程序,很快就可达OEP脱壳方法演示:寻找rebpe.exe的OEP(原始入口点)脱壳技术方法三:利用内存访问断点找OEP使用内存访问断点来进行脱壳需要明白以下几个问题:1.什么是内存断点2.如何在寻找OEP时使用内存访问断点i.内存断点就是通过将需要设置断点的内存页设置为不可访问属性,这样,当程序访问相关内存地址时就会发生异常,从而中断下来。一般分为内存访问和内存写入这两种断点。需要注意的是内存访问断点是以页为单位设置(4KB),所以一次设置是对一片内存区域设置断点。脱壳方法内存访问一次性断点Alt+M:MemoryMap信息安全工程学院脱壳技术ii、如何使用内存断点来访问OEP壳如果要把原来的代码运行起来就必须要解压和解密原来的代码,而这一过程正是对代码段(code段)的写入。解压和解密完毕后,外壳程序需要从壳代码区段JMP到原来的代码段,而这也正是对代码段的执行访问。因此如果载入OD后,直接对code段下内存访问断点,程序一定会中断在对code段的写入代码上面。脱壳方法脱壳技术两次内存访问一次性断点法:两次内存访问一次性断点就是通过两次内存断点的方式来找到OEP。第一次访问第二次访问设置内存访问断点时,可以第一次在.rsrc区段设置访问断点,.text区段已经解压完毕,第二次时可以在.text设置访问断点,这次会停在外壳跳转到.text位置处。脱壳方法解压顺序脱壳技术方法四:根据编译语言寻找OEP各类语言都有自己的入口特征,一般在主函数(Main函数)之前都会执行一些初始化函数,一般可以利用这些特征寻找OEP。在VC6编写的函数中一般都有如下一下函数会被调用。GetCommandLineA(w),GetModuleHandleA(W),GetVersion、GetStartupInfoA(W),因此针对VC6.0可以尝试利用这些函数来设置断点,寻找OEP。脱壳方法脱壳技术抓取内存映像,也叫转储(Dump),就是将指定内存地址中的映像文件读取出来,然后保存成文件。脱壳是应该在程序到达OEP时进行dump,因为这时程序已经将原始程序还原并初始化好,如果程序运行过程中再进行Dump,那么这时已经不是程序最初状态。Dump原理Dump常用软件有LordPE、ProcDump以及OD自带的脱壳插件。Dump程序主要分以下几个步骤:1、在系统中找到目标进程。2、在进程中确定映像文件的大小3、把进程中的数据保存到文件抓取内存映像演示:使用LordPE来dump脱壳技术1、在系统中查找目标进程就是通过类似任务管理器的方式将进程枚举出来然后查找特定进程。主要通过以下三个基本的API即可实现:GcreateToolHelp32Snapshot,Process32First,Process32Next。2、确定要dump的文件的大小,一种最简单的方法就是通过PE文件格式中的SizofImage(PE文件头偏移为0x50位置)获取内存镜像大小。另外就是通过Win32API函数Module32Next获取。这个地方需要注意的是,通过SizofImage获取的大小是镜像文件在内存中进行扩展对齐后的大小,因此如果存入文件时的对齐粒度不同的话,应该调整节表信息。抓取内存映像脱壳技术3、获得映像文件的基地址和大小后,Dump工具会通过ReadProcessMemory来读取内存中数据,并保存到文件。读取成功后,一些Dump工具会检查IMAGE_DOS_SIGNATURE和IMAGE_NT_SIGNATURE是否完整,如果不完整则会将保存在磁盘上的原始文件的头部读取出来替换到dump下来的数据文件,并将程序入口点修改为OEP。抓取内存映像脱壳技术由于dump是脱壳过程中的一个关键步骤,因此许多壳会采用Anti-Dump技术来防止被脱壳。为了顺利脱壳,必须绕过这些Anti-Dump技术。1、纠正SizeOfImage由于在Dump文件是,Dump文件是通过MODULEENTRY32结构来获取映像大小的,因此一些壳为了保护自己,通常会在MODULEENTRY32结构中的modBaseSize中填入错误的值,从而让Dump工具读取错误的数据。抓取内存映像脱壳技术为了防止外壳做这种破坏,一种方法是跟踪外壳执行过程,然后跳过指定的代码,而另外一种则是通过LordPE来进行修正,LordPE进行修正时是直接从磁盘文件PE头的SizeOfImage来修正错误。抓取内存映像脱壳技术2、修改内存属性当PE文件被加载到内存中时,其所有段的属性都是可读的,这样Dump工具打开进程时,就可以读取数据。但是如果外壳将某块间设置为不可读,那么我们利用Dump工具就无法访问内存。抓取内存映像脱壳技术这时可以利用调试器的权限设置,将相应的区段修改为可读属性,即可进行访问,并dump内存数据。在OD中找到对应的区段,右键-设置访问即可修改相应的属性。抓取内存映像ImportREC重建输入表由于许多加密壳会将原始程序的IAT(ImportAddressTable)导入地址表进行加密,因此Dump下来的文件需要进行输入表的修复操作。一般可以使用ImportREC来进行修复。使用ImportREC必须满足以下三点:①目标文件已经完全被dump,保存为一个新的文件;②目标文件必须在运作中;③事先找到目标程序的原始入口点(OEP)或IAT的偏移大小。使用ImprotREC修复输入表。信息安全工程学院END