分析加壳--加壳程序如何工作及如何识别

分析加壳--加壳程序如何工作及如何识别

前文 此系列文章仅是自己学习记录不做其它

加壳可执行程序文件的两个主要的目的是缩小程序的大小,保护对加壳程序的探测与分析。虽然加壳器的种类众多,但是它们遵循相似的模式:将一个可执行文件转换创建一个新的可执行文件,被转换的可执行文件将在这个新的可执行文件中作为数据存储,另外新的可执行文件还包括一个供操作系统调用的脱壳存根(stub)。下面首先以加壳程序如何工作及如何识别开始。
一、分析加壳
  代码加过壳后,通常只能获得加壳文件,而不以检查原始程序。要脱壳一个可执行文件,我们必须解开加壳所执行的操作,首先我们需要理解加壳器的工作原理。
  所有加壳器都是将一个可执行文件作为输入,输出一个新的可执行文件。被加壳的可执行文件经过压缩、加密或者其它转换,目的是使它们难以被识别、难以被逆向工程分析。如对抗反汇编、反调试和反虚拟化等。加壳器即可以打包整个可执文件,包括所有的数据和资源节,也可以仅打包代码节和数据节。
  要保持原程序的功能,加壳程序需要存储程序中的导入函数表信息。这些信息可以用任何格式存储。脱壳一个程序时,重构程序的导入函数表是一个具有挑战性且费时的操作,但这对分析程序功能又十分重要。
二、脱壳存根
  未加壳的程序是由操作系统加载,被加壳程序中的脱壳存根也是由操作系统加载的,然后它负责加载原始程序。程序的入口点指向脱壳存根,而不是原始代码。原始代码通常存储在加壳程序的一个或多个附加节中。
  分析者可以查看脱壳存根,理解脱壳存根的不同部分。因为脱壳存根不负责执行程序的主休功能,所以它通常很小。另外它的功能也很简单,只是脱壳程序。如果对加壳程序进行静态分析,那么你分析的是脱壳存根而不原始程序。
  脱壳存根执行以下三个操作:
  1、将原始程序脱壳到内存
  2、解析原始程序的所有导入函数。
  3、将程序转移到原始的程序入口点(OEP)
三、加载程序
  当加载一个程序时,加载器会先读取硬盘上程序的PE头部信息,然后根据PE头部信息为程序的各个节分配内存,然后加载器将这些复制到分配的内存空间中。
  加壳后程序一般会组成新的PE头信息,让加载器为它的节分配内存空间,它的节要么是原种程序的节,要么是脱壳存根创建的节。脱壳存根会脱壳每一个节的内容代码,并复制到分配的内存中去。
三、解析导入函数表
未加壳的PE文件中有一个节告诉加载器需要导入那些函数,同时还有一个节存储了导入的函数名字和地址。加载器读取导入信息,确定需要导那些函数,然后填入函数的地址。
加载器不能读取被加过壳的程序的导入函数表。对于加过的程序,脱壳存根负责解析导入函数表。
脱壳存根常用的方法是仅导入LoadLibrary和GetProcAddress两个函数。脱壳存根在脱出原始程序后,才能读取原始程序的导入函数表。为了将每个DLL加载到内存,脱壳存根将调用LoadLibrary函数导入每个库,然后调用GetProcAddress获取每个函数的内存地址。
另外一种是保持原始导入函数表不变,让加载器加载所有的DLL及导入函数,这是最简单的方法。
第三种不导入任何函数。加壳程序在不用函数的前提下,自己从库中查找所需要的函数,或者加壳程序先找到LoadLibrary和GetProcAddress函数,然后用它们定位其它库。这种方法的好处是不导入任何函数,但是这种方法,脱壳存根是很复杂的。
四、尾部跳转
脱壳存根脱壳完成,它就必须转到OEP运行。转到OEP的指令通常叫做尾部跳转指令。jmp指令是最单最流行的转移指令。所有多数的壳程序使用RET或者call指令来隐藏这种行为,或用其它函数来隐藏。
五、识别加壳程序
  是否加壳的特征
  1、程序中导入函数很少,仅有LoadLibrary GetProcAddress就要注意
  2、当用IDA打开程序时,自动分析只能识别少量代码就要注意
  3、当用OLD打开程序时,会有程序可能被加壳的提示
  4、程序的节名中有某加壳程序的标识VMP UPX
  5、程序拥有不正常的节大小,如text节原始数据大小为0,但虚拟大小非0

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值