PE文件加壳简介

1 什么是加壳器

加壳器、也称为打包程序,能够隐藏PE文件中软件的正真意图的代码,还能缩小恶意代码可执行文件的大小。

1.1 加壳器的原理

虽然加壳器的种类繁多, 但是它们都遵循相似的模式:

  • 首先将原可执行文件转换为一个新可执行文件,原可执行文件在这个新可执行文件中作为数据存储
  • 另外新可执行文件还包括一个供操作系统调用的脱壳存根(stub)

在执行加壳之后,被加壳的可执行文件经过压缩加密或者其他转换, 并且实施一些反逆向技术实现,如反汇编、反调试和反虚拟化,目的是使它们难以被识别、难以被逆向工程分析。

1.2 脱壳存根

被加壳程序中的脱壳存根由操作系统加载, 然后它负责加载原始程序。可执行程序的入口点(EP)指向脱壳存根, 而不是原始代码。原始程序通常存储在加壳程序的一个或多个附加的节中,脱壳存根通常会执行以下操作

  • 将原始程序脱壳到内存中
  • 解析原始可执行文件的所有导入函数
  • 将可执行程序转移到原始的程序入口点(OEP)

1.3 脱壳存根解析导入函数表

Windows加载器不能读取被加壳可执行文件的导入函数表,所以原可执行文件的导入表由脱壳存根来恢复,常见由以下几种方法:

  • 脱壳存根仅导入LoadLibraryGetProcAddress两个函数,在脱壳原创性后读取其导入表,并利用LoadLibrary 加载原程序DLL,利用GetProcAddress获取DLL中函数地址
  • 脱壳存根保留原程序完整的导入表,让Windows加载器来导入原程序的DLL和函数,但是这种方法隐蔽性较差,静态分析就能读出原程序的所有DLL和函数
  • 脱壳存根仅保留原程序每个DLL中的一个函数,这个方法隐蔽性比上一个高,且由于脱壳存根不需要读取原程序导入库,所以代码比第一种简单
  • 脱壳存根不导入任何函数,包括LoadLibraryGetProcAddress,加壳程序在不用函数的前提下, 自己从库中查找所有需要的函数, 或者加壳程序首先找到LoadLibrary 函数和GetProcAddress函数, 然后用它们定位其他的库

1.4 尾部跳转

一旦脱壳存根完成脱壳, 它就必须转到OEP运行。转到OEP的指令通常被叫作尾部跳转指令。jump指令是最简单且最流行的转移运行指令。它非常普通, 所以多数恶意的加壳程序试图使用ret或者call指令来隐藏这种行为。

2 常见加壳器

2.1 加壳程序特征

  • 程序中导入函数很少, 导入函数仅有LoadLibraryGetProcAddress时, 应该引起特别注意
  • 当使用IDA Pro打开程序时, 通过自动分析, 只有少量代码被识别
  • 当使用OllyDbg打开程序时, 会有程序可能被加壳的警告
  • 程序的节名中包含某款加壳器的标识(如UPX0)
  • 程序拥有不正常的节大小, 例如.text节的原始数据大小为0, 但虚拟大小非零

2.2 常见加壳器以及脱壳策略

2.2.1 UPX

恶意代码最常使用的加壳器是Ultimate Packer for eXecutables (UPX),它具有很高的压缩速度,较小的空间占用,而且压缩例程需要的内存也很少

脱壳策略

通过OllyDump的Section Hop功能来查找OEP, 或者干脆仔细检查脱壳存根,直到找到尾部跳转为止,然后使用OllyDump转储文件, 并重构导入表, 就可以成功脱壳。

2.2.2 PE Compact

一个商业的加壳器,为性能和速度而设计。用PE Compact加壳的程序脱壳比较困难, 因为它包含反调试异常混淆代码,它允许第三方工具集成进去, 因此恶意代码编写者经常使用第三方工具, 这使脱壳变得更困难。

脱壳策略

手动脱壳PE Compact与脱壳UPX很大程度上是相似的。程序会产生几个异常, 所以你需要设置OllyDbg将异常传回程序

2.2.3 AS Pack

ASPack的目的是为了安全,它采用一些技术让脱壳变得十分困难。ASPack使用了自我修改代码,在ASPack加壳的程序上设置断点, 可以让程序立即终止,这让设置断点和分析它变得困难。

脱壳策略

可以在栈地址上设置硬件断点完成对AS Pack加壳程序的手动脱壳。另外,由千AS Pack十分流行,因此很多自动脱壳程序都能脱壳它。

2.2.4 Petite

Petile与AS Pack在许多方面有相似之处。Petite也使用反调试机制, 这让发现OEP变得更困难, 同 时为了干扰调试器, Petite代码使用了单步异常。

脱壳策略

可以将单步异常传回到应用程序来解决单步异常的问题,使用栈上的硬件断点查找OEP。

2.2.5 UPack / WinUPack

WinUpack使用一些安全机制让查找OEP变得困难, 同时它也有一些安全辅助技术, 如搜索尾部跳转和让OllyDump失效等。

脱壳策略

查找UPack加壳程序OEP的最好策略是在GetProcAddress函数上设置断点, 然后通过仔细地单步运行指令, 查找设置导入解析方法的循环。

2.2.6 Themida

Tbemida是一个非常复杂的壳, 拥有多种功能。其中大部分功能是反调试反逆向分析, 这保证它是一个非常安全的壳, 难以脱壳和分析。Tbemida包含阻止使用VMware调试器, 以及Process Monitor (procmon) 分析的功能。除此之外, Tbemida还有一个内核模块, 这让分析变得尤其困难。运行在内核中的代码限制很少, 并且分析程序通常运行在用户空间中, 因此分析会受到很多限制。由千Tbemida拥有这么多的功能, 因此使用它加壳的可执行文件变得异常笨重。Tbemida代码会在原始程序运行后一直运行。

脱壳策略

Tbemida如此多的功能与设置使得我们不能找到一种一直有效的脱壳策略。如果自动化工具不能脱壳, 则另一种较好的策略是使用ProcDump工具从内存中转储不在进行调试的进程。这个过程并不能完全恢复可执行文件, 但是它能让你在代码上运行Strings工具并做一些分析。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注