具体实施方式
这里将详细地对示例性实施例进行说明,其示例表示在附图中。下面的描述涉及附图时,除非另有表示,不同附图中的相同数字表示相同或相似的要素。以下示例性实施例中所描述的实施方式并不代表与本申请实施例相一致的所有实施方式。相反,它们仅是与如所附权利要求书中所详述的、本申请实施例的一些方面相一致的装置和方法的例子。
在本申请实施例使用的术语是仅仅出于描述特定实施例的目的,而非旨在限制本申请实施例。在本申请实施例和所附权利要求书中所使用的单数形式的“一种”、“所述”和“该”也旨在包括多数形式,除非上下文清楚地表示其他含义。还应当理解,本文中使用的术语“和/或”是指并包含一个或多个相关联的列出项目的任何或所有可能组合。
应当理解,尽管在本申请实施例可能采用术语第一、第二、第三等来描述各种信息,但这些信息不应限于这些术语。这些术语仅用来将同一类型的信息彼此区分开。例如,在不脱离本申请实施例范围的情况下,第一信息也可以被称为第二信息,类似地,第二信息也可以被称为第一信息。取决于语境,如在此所使用的词语“如果”可以被解释成为“在……时”或“当……时”或“响应于确定”。
当今用于对Android APP进行加壳的各类APP加壳工具的加壳方式不统一,导致需要定制化脱壳方案。并且,各类APP加壳工具更新较快,会不断增加增加脱壳难度的措施,导致脱壳方案普遍容易失效。为此,本申请提出了一种通用的APP脱壳方案。
如图1所示,一种脱壳软件可以运行于计算机设备上,以该计算机设备的操作***为安卓(Android)***为例,该计算机设备上可运行有安卓虚拟机(Dalvik VirtualMachine,DVM)及脱壳软件。在硬件层面,该计算机设备可包括处理器、内部总线、网络接口、存储器(包括内存以及非易失性存储器),当然还可能包括其他业务所需要的硬件。其中,在存储器内可以存储有上述脱壳软件对应的计算机程序,处理器可从非易失性存储器中读取对应的计算机程序到内存中然后运行。当然,除了软件实现方式之外,本申请并不排除其他实现方式,比如逻辑器件抑或软硬件结合的方式等等,也就是说以下处理流程的执行主体并不限定于各个逻辑单元,也可以是硬件或逻辑器件。
图2是根据一示例性实施例示出的一种应用程序脱壳方法的流程。该方法基于上述图1所示的计算机设备来实现。如图2所示,所述方法包括步骤101~104,其中:
步骤101,通过DVM将待脱壳应用程序的加壳Dex代码加载到内存中。
当需要对某种加壳APP进行脱壳时,用户可以通过互联网下载该加壳APP的安装包(AndroidPackage,APK),并安装到上述计算机设备上,安装后,APP程序以Dex文件的形式存在于非易失性存储器中,以备后续脱壳。其中,Dex文件包含加壳Dex代码,是可以直接在DVM中加载并运行的文件。在安装完成之后,Dex文件是通过特定的加壳手段进行加壳的。在APP被运行的过程中,上述计算机设备首先从非易失性存储器中读取APP的加壳Dex文件,并将加载到内存中,然后,对加壳Dex文件进行脱壳得到脱壳后的代码,最终,DVM运行脱壳后的代码。
步骤102,对于所述待脱壳应用程序的目标类,定位所述目标类对应的Dex代码所处的内存片段。
通常,APP的代码由各个类Class组成,如:启动类Class(为最先被执行的程序入口)。一般由于APP是按照Class对代码进行加壳,所以,在对APP的加壳Dex代码进行脱壳时,需要预先确定该APP的代码所包含的各个Class,并根据实际需要,确定脱壳工作所针对的一个或多个Class,并逐一针对各个Class进行脱壳,得到各个Class的脱壳后代码。本文中,将确定的需要脱壳的Class称为目标类。
在一实施例中,在DVM将待脱壳APP的加壳Dex代码全部加载到内存中之后,可以通过动态插桩技术,来定位所述目标类对应的Dex代码所处的内存片段(即内存中的某个存储片段)。在将Dex代码加载到内存之后,每个Class在内存中会对应于一片内存片段,用以存储该Class所对应的代码。本实施例通过定位所述目标类对应的Dex代码所处的内存片段,可为后续主动加载该目标类的代码作好准备。其中,“动态插桩”是在保证被测程序原有逻辑完整性的基础上,在程序中***一些探针(本质上就是进行信息采集的代码段),通过探针的执行并抛出程序运行的特征数据,通过对这些数据的分析,可以获得程序的控制流和数据流信息,进而得到逻辑覆盖等动态信息,从而实现测试目的的方法。本实施例可以在DVM的开源代码中进行动态插桩来实现。
步骤103,在主动加载时刻,将所述内存片段中的Dex代码主动加载到所述DVM使用的内存对象中。
通常,在APP的加壳代码(即Dex代码)被加载到内存之后,在被执行之前,需要对加壳代码进行脱壳,否则无法正常执行。而在DVM执行完毕脱壳代码之后,需要重新为Dex代码加上“壳”,以确保外界无法获取到该APP的脱壳代码。可见,加壳代码一般只在加载并执行过程中的一小段时间内被脱壳,在这一小段时间中,内存中的Dex代码相对较为完善,是后续修复Dex代码的好时机。也就是说,为实现APP的Dex代码的脱壳,需要确定一个主动加载时刻,以在该主动加载时刻,将所述内存片段中的Dex代码主动加载到所述DVM使用的内存对象中,以在内存对象中生成上述目标类的类对象(class object)。其中,所述主动加载时刻在所述加壳Dex代码被全部加载到所述内存中之后,且在所述内存中的Dex代码被运行结束之前。在该主动加载时刻,内存的Dex代码是被脱壳后的数据较为完善,是适合进行脱壳的好时机。其中,该内存对象可以是DVM在执行Dex代码过程中所需要的一片内存空间。
在一可选实施例中,可通过如下过程来确定以上主动加载时刻:
步骤11,利用动态插桩技术,监测所述DVM的加载完成时刻,所述加载完成时刻是完成加载所述加壳Dex代码到所述内存中的时刻。
本实施例中,可通过在DVM的开源代码进行动态插桩,来监测所述DVM的各个工作状态。其中,DVM的各个工作状态如下:
1、代码加载完成;2、代码脱壳完成;3、代码开始运行;4、代码运行结束。
通过监测到DVM的各个工作状态,也便可以获得DVM在达到各个工作状态的时间点并记录相应的时刻。
步骤12,根据监测所得的所述加载完成时刻,确定所述主动加载时刻。
例如,将加载完成并完成脱壳之后、且在开始运行脱壳代码之前的某个时刻确定为主动加载时刻;或者,将开始运行脱壳代码之后、且在执行结束之前的某个时刻确定为主动加载时刻;或者,根据经验,将所述DVM的加载完成时刻后相隔一经验时长的时刻,确定为主动加载时刻;等等。
在步骤104中,将所述内存对象中的Dex代码还原为所述目标类对应的脱壳Dex代码,并生成包含所述脱壳Dex代码的Dex文件。
由于本申请提供的是一种通用型的软件脱壳方案,对于不同类型的软件加固手段,均需要脱壳成功。实际运行过程中,虽然对目标类的代码进行主动加载,可以获得存在于内存对象中的较为完整的脱壳Dex代码,但是,通常还是会存在一些特殊的对抗措施(如:对代码进行某种规则的替换或混淆,对代码作一些偏移等),为此,需要根据内存对象中的Dex代码进行还原,以更为完整的脱壳Dex代码。
在一实施例中,步骤104可以具体包括:
步骤1041:将预设的多个还原规则中的一个或多个确定为目标还原规则,其中,所述还原规则包括但不限于:简易型还原规则、数据重组型还原规则、数据替换型还原规则等。
步骤1042:利用所述目标还原规则,将所述内存对象中的Dex代码还原为所述目标类对应的脱壳Dex代码。
以下对举例对各个还原规则进行叙述。
在一实施例中,当所述目标还原规则为简易型还原规则时,所述步骤1042具体包括:
a)根据所述内存对象中的Dex文件头,确定Dex长度。
例如,将Dex文件头中的dataSize字段和dataOff字段之间的数据长度,确定为Dex长度。
b)从所述内存对象中提取与所述Dex长度对应的脱壳Dex代码。
可见,当内存对象中加载的脱壳代码比较完整时,可以运用简易型还原规则来确定需要提取的Dex数据的长度,并直接从内存中提取(Dump)相应的脱壳Dex代码,这种方式速度最快。当然,若检测到采用该简易型还原规则无法成功还原出较为完整的脱壳代码时,可以选择其他规则来继续还原。
在另一实施例中,当所述目标还原规则为数据重组型还原规则时,所述步骤1042具体包括:
c)确定内存对象中的所述Dex代码的数据偏移特性。
在对APP代码进行加壳时,可以采用将指定代码进行偏移的这一手段来实现。而这一手段通常是有规律可循的,当找到代码偏移的规律后,便可以按照规律还原出偏移前的代码。
d)根据预先确定的数据偏移特性和Dex重组规则的对应关系,确定与Dex代码的数据偏移特性对应的目标Dex重组规则。
通过对已存在的各种软件加壳手段(即代码偏移手段)的调研,可以预先确定得到各种数据偏移特性和Dex重组规则的对应关系,通过该对应关系,在获得Dex代码的数据偏移特性的前提下,便可以确定与之对应的Dex重组规则。
e)基于所述目标Dex重组规则,对所述内存对象中的Dex代码进行重新组合,得到脱壳Dex代码。
Dex重组规则指示了如何对偏移后的代码进行重新组合。在一种例子中,偏移可能是将一段目标Code分成了两段,并将其中一段Code在原来的位置基础上偏移一定的程度(也可视为在两段Code间增加一定程度的间隔),为此,Dex重组规则可以指示目标代码被分为几段Code,Code与Code之间的间隔长度,等等。通过消除上述Code与Code之间的间隔长度,便可以重新组合得到偏移前的目标代码。
在又一实施例中,当所述目标还原规则为数据替换型还原规则时,所述步骤1042具体包括:
f)确定Dex代码中包含的待替换数据。
g)按照预设的数据替换规则,将待替换数据替换为原始数据,得到脱壳Dex代码。
在有些加壳手段中,并不像“代码偏移手段”那样,仅仅是对指定代码进行偏移,而是将指定代码替换为另一段代码,对于这一种加壳手段,则无法通过重组来还原。一般地,“将指定代码替换为另一段代码”的这一种方式也是有规律可循的,“被替换代码”和“替换后代码”之间的对应关系是确定的。基于这一规律,可以确定出Dex代码中包含的待替换数据,并将待替换数据替换为原始数据,得到脱壳Dex代码。
需说明的是,可按照一定的次序来对内存对象中的Dex代码进行还原,比如,先采用简易型还原规则进行还原,如果不成功,则再采用数据重组型还原规则或数据替换型还原规则进行还原。需要说明的是,可以逐一针对每一Class,还原出脱壳后的Dex代码,并将还原得到的Dex代码放入预先生成的Dex文件中,并将该Dex文件存储于本地指定路径下。
实际运用过程中,在还原Dex代码的过程中难免会出现一些异常情况,这些异常情况可能会造成还原无法成功。在可选的实施例中,为应对这一问题,需要增加容错机制。具体地,在将内存对象中的Dex代码还原为目标类对应的脱壳Dex代码之前,还包括如下步骤:
当检测到所述Dex代码中的Dex头文件异常时,根据预设的头文件异常处理规则对异常的Dex头文件(Dex Header)进行处理,得到正常的Dex代码。
例如,根据Dex文件格式,检测Dex Header的一些关键性的偏移特性,以根据偏移特性对Dex Header进行处理,以消除偏移所造成的Dex Header异常。
在另一可选实施例中,该方法还包括如下步骤:
当还原所述目标类的脱壳Dex代码失败时,取消对该目标类的脱壳任务并执行对该待脱壳应用程序的其他类的脱壳任务。通常,需要针对多个Class逐一还原出脱壳代码,然而,有可能某些Class由于某些原因无法正常还原出Dex代码,这势必会阻碍生成Dex文件的效率(Dex文件是包含每个Class还原完成后所得的脱壳代码的)。为此,为提高生成效率,可以有针对性地跳过无法脱壳的Class,尽量保证生成一份可用的Dex代码,其中,在某种程度上,缺少某些Class的脱壳代码的Dex文件仍然有价值,依然可以用于代码分析工作(如恶意软件识别)。
通过以上技术方案可以看出,本申请提供了一种通用对加壳代码进行脱壳的方案,可以不受APP的加壳规则的限制,实现对大多数APP的脱壳过程,从而有助于分析出恶意APP。
与上述应用程序脱壳方法的实施例对应,本申请实施例还提供了应用程序脱壳装置的实施例,以下将结合图3~图4进行介绍。
如图3所示,在一实施例中,一种应用程序脱壳装置200可以存在计算机设备中(例如,以软件代码的形式),该装置200包括:
DVM加载单元201,通过安卓虚拟机DVM将待脱壳应用程序的加壳Dex代码加载到内存中;
定位单元202,对于所述待脱壳应用程序的目标类,定位所述目标类对应的Dex代码所处的内存片段;
类主动加载单元203,在主动加载时刻,将所述内存片段中的Dex代码主动加载到所述DVM使用的内存对象中,所述主动加载时刻在所述加壳Dex代码被全部加载到所述内存中之后,且在所述内存中的Dex代码被运行结束之前;及,
Dex生成单元204,将所述内存对象中的Dex代码还原为所述目标类对应的脱壳Dex代码,并生成包含所述脱壳Dex代码的Dex文件。
如图4所示,在另一实施例中,在上述图3所示的装置的基础上,还包括:
DVM监测单元205,利用动态插桩技术,监测所述DVM的加载完成时刻,所述加载完成时刻是完成加载所述加壳Dex代码到所述内存中的时刻。
主动加载时刻确定单元206,根据监测所得的所述加载完成时刻,确定所述主动加载时刻。
在一可选实施例中,所述Dex生成单元204可具体包括:
规则确定单元241,将预设的多个还原规则中的一个或多个确定为目标还原规则,所述还原规则包括:简易型还原规则、和/或数据重组型还原规则、和/或数据替换型还原规则;
数据还原单元242,利用所述目标还原规则,将所述内存对象中的Dex代码还原为所述目标类对应的脱壳Dex代码。
在一实施例中,当所述目标还原规则为简易型还原规则时,所述数据还原单元242可以具体包括:
长度确定子单元,根据所述内存对象中的Dex文件头,确定Dex长度;
提取单元,从所述内存对象中提取与所述Dex长度对应的脱壳Dex代码。
可选地,所述长度确定子单元将所述Dex文件头中的dataSize字段和dataOff字段之间的数据长度,确定为Dex长度。
在一实施例中,当所述目标还原规则为数据重组型还原规则时,所述数据还原单元242可以具体包括:
偏移特性确定单元,确定所述内存对象中的所述Dex代码的数据偏移特性;
重组规则确定单元,根据预先确定的数据偏移特性和Dex重组规则的对应关系,确定与所述Dex代码的数据偏移特性对应的目标Dex重组规则;
重组单元,基于所述目标Dex重组规则,对所述内存对象中的Dex代码进行重新组合,得到脱壳Dex代码。
在一实施例中,当所述目标还原规则为数据替换型还原规则时,所述数据还原单元242可以具体包括:
待替换数据确定单元,确定所述Dex代码中包含的待替换数据;
替换单元,按照预设的数据替换规则,将所述待替换数据替换为原始数据,得到脱壳Dex代码。
需说明的是,本文记载的方法实施例的内容和装置实施例的内容,在不相冲突的情况下,可以互为补充。
本申请实施例还提供了一种计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现以下步骤:
通过安卓虚拟机DVM将待脱壳应用程序的加壳Dex代码加载到内存中;
对于所述待脱壳应用程序的目标类,定位所述目标类对应的Dex代码所处的内存片段;
在主动加载时刻,将所述内存片段中的Dex代码主动加载到所述DVM使用的内存对象中,所述主动加载时刻在所述加壳Dex代码被全部加载到所述内存中之后,且在所述内存中的Dex代码被运行结束之前;
将所述内存对象中的Dex代码还原为所述目标类对应的脱壳Dex代码,并生成包含所述脱壳Dex代码的Dex文件。
上述实施例阐明的***、装置、模块或单元,具体可以由计算机芯片或实体实现,或者由具有某种功能的产品来实现。一种典型的实现设备为计算机,计算机的具体形式可以是个人计算机、膝上型计算机、蜂窝电话、相机电话、智能电话、个人数字助理、媒体播放器、导航设备、电子邮件收发设备、游戏控制台、平板计算机、可穿戴设备或者这些设备中的任意几种设备的组合。
为了描述的方便,描述以上装置时以功能分为各种单元分别描述。当然,在实施本申请时可以把各单元的功能在同一个或多个软件和/或硬件中实现。
本领域内的技术人员应明白,本发明的实施例可提供为方法、***、或计算机程序产品。因此,本发明可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本发明可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本发明是参照根据本发明实施例的方法、设备(***)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
在一个典型的配置中,计算设备包括一个或多个处理器(CPU)、输入/输出接口、网络接口和内存。
内存可能包括计算机可读介质中的非永久性存储器,随机存取存储器(RAM)和/或非易失性内存等形式,如只读存储器(ROM)或闪存(flash RAM)。内存是计算机可读介质的示例。
计算机可读介质包括永久性和非永久性、可移动和非可移动媒体可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括,但不限于相变内存(PRAM)、静态随机存取存储器(SRAM)、动态随机存取存储器(DRAM)、其他类型的随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、快闪记忆体或其他内存技术、只读光盘只读存储器(CD-ROM)、数字多功能光盘(DVD)或其他光学存储、磁盒式磁带,磁带磁磁盘存储或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。按照本文中的界定,计算机可读介质不包括暂存电脑可读媒体(transitory media),如调制的数据信号和载波。
还需要说明的是,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、商品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、商品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、商品或者设备中还存在另外的相同要素。
本领域技术人员应明白,本申请的实施例可提供为方法、***或计算机程序产品。因此,本申请可采用完全硬件实施例、完全软件实施例或结合软件和硬件方面的实施例的形式。而且,本申请可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本申请可以在由计算机执行的计算机可执行指令的一般上下文中描述,例如程序模块。一般地,程序模块包括执行特定任务或实现特定抽象数据类型的例程、程序、对象、组件、数据结构等等。也可以在分布式计算环境中实践本申请,在这些分布式计算环境中,由通过通信网络而被连接的远程处理设备来执行任务。在分布式计算环境中,程序模块可以位于包括存储设备在内的本地和远程计算机存储介质中。
本说明书中的各个实施例均采用递进的方式描述,各个实施例之间相同相似的部分互相参见即可,每个实施例重点说明的都是与其他实施例的不同之处。尤其,对于***实施例而言,由于其基本相似于方法实施例,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。
以上所述仅为本申请的实施例而已,并不用于限制本申请。对于本领域技术人员来说,本申请可以有各种更改和变化。凡在本申请的精神和原理之内所作的任何修改、等同替换、改进等,均应包含在本申请的权利要求范围之内。