一种Android平台应用程序的脱壳方法及容器与流程

文档序号:14836180发布日期:2018-06-30 12:30阅读:310来源:国知局
一种Android平台应用程序的脱壳方法及容器与流程

本发明涉及信息安全技术领域,尤其涉及Android平台应用程序的脱壳方法及容器。



背景技术:

Android系统本身具有开源的特性,随着移动终端性能的不断提升,Android平台应用程序发展迅猛。然而,Android平台上的恶意应用也越来越多,严重危害了用户的隐私和资产安全。如今Android平台上的恶意应用大多会使用加固技术来隐藏其恶意代码的逻辑,以期绕过杀毒引擎的查杀,对用户造成严重危害。针对此问题,Android加固应用的脱壳技术应运而生。

现有针对Android应用的脱壳方案主要分为如下两种:第一种是通过一些动态调试工具在Android应用运行时把内存数据写入文件来实现,这种方式需要人工参与,需要root权限,且目前加固技术对这种方式采取了很多防护手段,导致这种脱壳方式的效率、成功率都很低。第二种方式是通过修改系统层虚拟机(如Dalvik虚拟机或ART虚拟机),以获取与dex文件相关的数据结构,将数据重新组成一个新的脱壳的文件。这种方式可以实现自动化的脱壳机,但是需要修改系统代码,并且每修改一次就需要重新刷机,使用更新起来非常繁琐,不太适合普通用户的使用场景。



技术实现要素:

本发明的目的在于提供一种Android平台应用程序的脱壳方法及容器,适合普通用户的使用场景,无需root权限,实现方便,脱壳效率高。

为了实现上述目的,本发明公开了一种Android平台应用程序的脱壳方法,应用于一位于应用层的预设的脱壳容器中,所述脱壳方法包括以下步骤:

获取外部输入的待脱壳应用程序的路径,并将该待脱壳应用,拷贝到脱壳容器的文件目录中;

解析待脱壳应用程序的Manifest文件,获取其主Activity及资源信息,所述资源信息至少包括资源路径;

根据待脱壳应用程序的路径,将该待脱壳应用程序的资源路径及代码加载到脱壳容器的进程空间中;所述代码加载包括以下步骤:启动所获取的主Activity,并将一替身Activity的启动参数发送给系统层,所述替身Activity为该脱壳容器中Manifest文件的Activity;系统层获取替身Activity的启动参数进行Activity管理;脱壳容器为该主Activity创建一新的ClassLoader对象,并将该ClassLoader对象绑定到系统层用于加载Activity类的加载器上;利用该ClassLoader对象调用加载类的函数完成代码加载;

获取该待脱壳应用程序的dex文件结构;

根据该dex文件结构对该待脱壳应用程序进行脱壳。

进一步的,Activity的管理包括生命周期管理、栈管理或真实性的校验。

进一步的,绑定ClassLoader对象的方法包括以下步骤:通过系统函数getPackageInfoNoCheck()构建待脱壳应用程序的LoadeAPK对象;将构造的ClassLoader对象替换待脱壳应用程序的mClassLoader成员变量;通过反射获得CurrentThread对象,并获得其中的成员变量mPackages,将已创建的LoadeAPK对象加入到mPackages的Map中。

进一步的,加载资源路径的方法包括:创建一个AssetManager对象,通过反射的方式调用AssetManager中的addAssetPath函数,将待脱壳应用程序的资源路径加载到AssetManager中;根据该AssetManager创建待脱壳应用的Resources对象;将创建的Resources对象添加到脱壳容器的资源缓存表中。

进一步的,根据该待脱壳应用程序的dex文件结构对该待脱壳应用程序进行脱壳包括以下步骤:根据dex文件在内存中对应的gDvm.userDexFiles结构体的大小开辟一个新的空间,用于存储修复后的dex文件;通过gDvm.userDexFiles结构体获取当前的DexFile结构体,解析DexFile结构体,确定需要修复的结构体;修复各结构体,并对所有DexClassData结构体进行重组,在内存中形成所述修复后的dex文件;将修复后的dex文件从内存中Dump至相应的输出目录。

为了实现上述目的,本发明还公开了一种脱壳容器,用于在Android平台应用层中对应用程序进行脱壳,所述脱壳容器包括解析模块、动态加载模块、核心脱壳模块,其中:

所述解析模块用于获取外部输入的待脱壳应用程序的路径,将该待脱壳应用,拷贝到脱壳容器的文件目录中;并解析待脱壳应用程序的Manifest文件,获取其主Activity及资源信息,所述资源信息至少包括资源路径;

所述动态加载模块用于根据待脱壳应用程序的路径,将该待脱壳应用程序的资源路径及代码加载到脱壳容器的进程空间中;所述代码加载包括以下步骤:启动所获取的主Activity,并将一替身Activity的启动参数发送给系统层,所述替身Activity为该脱壳容器中Manifest文件的Activity;系统层获取替身Activity的启动参数进行Activity管理;动态加载模块为该主Activity创建一新的ClassLoader对象,并将该ClassLoader对象绑定到系统层用于加载Activity类的加载器上;利用该ClassLoader对象调用加载类的函数完成代码加载;

所述核心脱壳模块用于获取该待脱壳应用程序的dex文件结构;根据该dex文件结构对该待脱壳应用程序进行脱壳。

进一步的,Activity的管理包括生命周期管理、栈管理或真实性的校验。

进一步的,绑定ClassLoader对象的方法包括以下步骤:通过系统函数getPackageInfoNoCheck()构建待脱壳应用程序的LoadeAPK对象;将构造的ClassLoader对象替换待脱壳应用程序的mClassLoader成员变量;通过反射获得CurrentThread对象,并获得其中的成员变量mPackages,将已创建的LoadeAPK对象加入到mPackages的Map中。

进一步的,所述动态加载模块加载资源路径的方法包括:创建一个AssetManager对象,通过反射的方式调用AssetManager中的addAssetPath函数,将待脱壳应用程序的资源加载到AssetManager中;根据该AssetManager创建待脱壳应用的Resources对象;将创建的Resources对象添加到脱壳容器的资源缓存表中。

进一步的,根据该dex文件结构对该待脱壳应用程序进行脱壳包括以下步骤:根据dex文件在内存中对应的gDvm.userDexFiles结构体的大小开辟一个新的空间,用于存储修复后的dex文件;通过gDvm.userDexFiles结构体获取当前的DexFile结构体,解析DexFile结构体,确定需要修复的结构体;修复各结构体,并对所有DexClassData结构体进行重组,在内存中形成所述修复后的dex文件;将修复后的dex文件从内存中Dump至相应的输出目录。

进一步的,所述动态加载模块完成资源路径及代码的加载后,脱壳容器调用该主Activity的OnCreate函数,在该函数中调用核心脱壳模块。

本发明与现有技术相比的有益效果是:现有的脱壳方式需要干预待脱壳应用程序的进程,因此需要获得待脱壳应用程序的root权限。而本发明利用动态加载的原理将该待脱壳应用程序的资源路径及代码加载到一预设脱壳容器中实现在应用层对应用程序的脱壳。本发明由于未进行跨进程操作,因此无需root权限,并且本发明也不用修改系统源码,能适用于普通用户的使用场景,实现方便,脱壳效率高。

附图说明

图1为本发明一种Android平台应用程序的脱壳方法的流程图。

图2为本发明代码加载的流程图。

图3为本发明对该待脱壳应用程序进行脱壳的流程图。

图4为本发明脱壳容器的结构示意图。

具体实施方式

为了使本发明的目的、技术方案和优点更加清楚,下面将结合附图对本发明作进一步地详细描述。

本发明中的步骤虽然用标号进行了排列,但并不用于限定步骤的先后次序,除非明确说明了步骤的次序或者某步骤的执行需要其他步骤作为基础,否则步骤的相对次序是可以调整的。

本发明拟实现对加固应用的脱壳,而脱壳核心是在于对dex文件结构的重构,在理解本发明之前需要了解下dex文件结构的相关信息。

首先Android平台的应用安装包都是以apk的形式存在的,apk其实就是一个ZIP的压缩包,解压后会得到一些资源文件、签名文件、配置文件和一个Android应用的可执行文件class.dex文件,class.dex文件的结构如表1所示。

表1

逻辑上,可以把 dex文件分成3个区,即文件头、索引区和数据区。索引区的 ids 后缀为 identifiers 的缩写,意思是某件东西的识别码。该区的数据多是指向数据区的指针。

dex 文件里的 header,除了描述.dex 文件的文件信息外,还有文件里其它各个区域的索引,其结构如下所示:

struct DexHeader { ubyte magic[8]; /* includes version number */ uint checksum; /* adler32 checksum */ ubyte signature[kSHA1DigestLen]; /* SHA-1 hash */ uint fileSize; /* length of entire file */ uint headerSize; /* offset to start of next section */ uint endianTag; uint linkSize; uint linkOff; uint mapOff; uint stringIdsSize; uint stringIdsOff; uint typeIdsSize; uint typeIdsOff; uint protoIdsSize; uint protoIdsOff; uint fieldIdsSize; uint fieldIdsOff; uint methodIdsSize; uint methodIdsOff; uint classDefsSize; uint classDefsOff; uint dataSize; uint dataOff; };

其中字体加粗的字段代表着dex文件的本身的信息,如magic魔术字段,dex文件中该字段固定为:dex.035;checksum为整个dex文件的校验值,以确保文件的完整性和防篡改。其他字段的都是成对出现的,它们代表的对应索引区的位置和大小:如sting_ids_off代表了字符串索引区的位置,string_ids_size代表着这索引区的大小等等。

Android系统中用DexFile的结构体来描述整个dex文件结构,DexHeader来描述dex文件的头部信息,用ClassDef结构来描述每一个类的信息,ClassDef结构体为脱壳过程中主要操作的结构体,ClassDef结构体中的class_data_off指向了一个DexClassData的结构,DexClassData结构描述了这个类中的具体信息,包括:静态成员变量和实例成员变量,静态方法和实例方法,其中的方法都是通过DexMethod的结构体来描述,DexMethod结构又包含了一个DexCode的结构体,用于描述该方法具体指令的相关信息。在脱壳过程中主要操作的就是DexClassData、DexMethod、DexCode这三层级的数据。

下面给出本发明的一些具体实施方式。

实施例1

结合图1所示,在一些实施例中,本发明公开的Android平台应用程序的脱壳方法,应用于一位于应用层的预设的脱壳容器中,可以理解的,该脱壳容器也是一种应用程序,具有自己的Manifest文件。本发明的脱壳方法包括以下步骤:

S01,获取外部输入的待脱壳应用程序的路径,将该待脱壳应用,拷贝到脱壳容器的文件目录中。

S02,解析待脱壳应用程序的Manifest文件,获取其主Activity及资源信息。

其主Activity包括用于对主页面进行描述的Activity的字符串,资源信息包括:图片、图标、XML文件和资源的路径。

S03,根据待脱壳应用程序的路径,将该待脱壳应用程序的代码及资源路径加载到脱壳容器的进程空间中。

S031,将待脱壳应用程序的资源路径添加到脱壳容器的系统资源管理类中。可以理解的,系统还会完成图片、图标、XML文件等资源的加载。

具体的,首先需要创建一个AssetManager对象,理论上可以通过调用AssetManager中的addAssetPath方法实现将一个apk文件的资源路径加载到Resources对象中。但是由于addAssetPath是隐藏api无法直接调用apk文件,因此,在创建AssetManager对象后还必须用反射调用其方法,将待脱壳应用程序的路径传给addAssetPath,以实现将资源路径加载到AssetManager中。由于应用程序一般使用Resource对象访问资源,因此还需要再通过AssetManager创建一个新的Resources对象,并将其添加到脱壳容器的资源缓存表中。

S032,代码加载。结合图2所示,代码加载包括以下步骤:

S0321,启动所获取的主Activity。

S0322,将一替身Activity的启动参数发送给系统层,替身Activity为该脱壳容器中Manifest文件的Activity,后文将该替身Activity记为StubActivity。

S0323,系统层获取StubActivity的启动参数来完成Activity的管理。

本发明以StubActivity作为主Activity的替身,以欺骗系统层用于管理Activity的ActivityManagerService类(下面简称AMS),从而实现对Activity的生命周期管理、栈管理或真实性的校验等工作。

S0324,脱壳容器为该主Activity创建一新的ClassLoader对象,并将该ClassLoader对象绑定到系统层加载Activity类的加载器上。

该ClassLoader的源dex路径就是S01拷贝后的路径。理论上,Android平台可以利用自身的ClassLoader对象加载应用程序的路径来实现代码加载,但是通过这种方式加载的应用程序的组件是没有生命周期的,也就是说通过这种方式是无法正常启动主Activity的。为了让加载的组件具有生命周期,因此需要用脱壳容器创建一个新的ClassLoader对象,并将此对象绑定到系统层用以加载Activity类的加载器上。

为了便于理解,现介绍ClassLoader对象的层级关系:ClassLoader对象在LoadeApk对象里,LoadeApk对象在CurrentThread对象的mPackages里,而系统层使用的是mPackages里的LoadeApk对象。

绑定ClassLoader对象的方法如下:通过系统函数getPackageInfoNoCheck()构建待脱壳应用程序的LoadeAPK对象;将构造的ClassLoader对象替换待脱壳应用程序的mClassLoader成员变量;通过反射获得CurrentThread对象,并获得其中的成员变量mPackages,将已创建的LoadeAPK对象加入到mPackages的Map中。

可以理解的,系统层利用该ClassLoader调用加载类的函数LoadClass完成代码加载。

现有的脱壳方式需要干预待脱壳应用程序的进程,因此需要获得待脱壳应用程序的root权限。而本发明利用动态加载的原理将该待脱壳应用程序的资源路径及代码加载到一预设脱壳容器中实现在应用层对应用程序的脱壳。本发明由于未进行跨进程操作,因此无需root权限,并且本发明也不用修改系统源码,能适用于普通用户的使用场景,实现方便,脱壳效率高。

S04,获取该待脱壳应用程序的dex文件结构。

获取待脱壳应用程序的dex文件在内存中对应的gDvm.userDexFiles结构体。

S05,根据该dex文件结构对该待脱壳应用程序进行脱壳。结合图3所示:

S051,根据gDvm.userDexFiles大小来开辟一个新的空间,用于存储修复后的Dex文件。

S052,通过gDvm.userDexFiles来获取当前的DexFile结构体,然后解析DexFile结构体获取其中的数据,根据该结构体中的头部数据,遍历整个DexFile文件,确定需要修复的结构体。

具体的遍历层级由DexClassData到DexMethod,再到具体的DexCode结构,确定需要修复的结构体,如判断出DexClassData中的class_data_off是一个远程地址,则确定其需要修复;如判断出DexMethod中的code_off是一个远程地址,则确定其需要修复;如判断出DexCode结构中insns的指令为空,则确定其需要修复。

S053,修复各结构体,对所有DexClassData结构体进行重组,在内存中形成一个新的dex文件。

修复各结构体,与S052对应,如DexClassData中的class_data_off是一个远程地址,则将该地址指向的值重新拷贝到新开辟的空间中;如DexMethod中的code_off是一个远程地址,则将远程指向的DexMethod的结构体拷贝到新开辟空间中的对应位置;如DexCode结构中insns的指令为空,则通过Method对象中的insns来将其中的指令进行还原。

对所有DexClassData结构体进行重组,即通过修复完成的DexClassData结构体,重新计算偏移,并填入DexFile对应偏移的结构中。

重新计算DexFile中的头部的数据,其中有的数据是固定不变的,如dex文件的魔术字段、头部大小、string_ids_off等,可以直接填入,有的数据如type_ids_off、proto_ids_off等数据需要重新计算偏移后填入,该头部数据修复完成后,就形成了一个新的Dex文件。

S054,将重组后的新Dex文件从内存中Dump出来以文件的形式写到对应的输出目录中,该文件即为脱壳后的文件。

实施例2

如图4所示,一种脱壳容器,用于在Android平台应用层中对应用程序进行脱壳,所述脱壳容器包括解析模块10、动态加载模块20、核心脱壳模块30,其中:

所述解析模块10用于获取外部输入的待脱壳应用程序的路径,将该待脱壳应用,拷贝到脱壳容器的文件目录中;并解析待脱壳应用程序的Manifest文件,获取其主Activity及资源信息。其主Activity包括用于对主页面进行描述的Activity的字符串,资源信息至少包括资源路径。

所述动态加载模块20用于根据待脱壳应用程序的路径,将该待脱壳应用程序的代码及资源路径加载到脱壳容器中创建主Activity的类。具体的:

1、资源路径加载:创建一个AssetManager对象,理论上可以通过调用AssetManager中的addAssetPath方法实现将一个apk文件的资源路径加载到Resources对象中。但是由于addAssetPath是隐藏api无法直接调用apk文件,因此,在创建AssetManager对象后还必须用反射调用其方法,将待脱壳应用程序的路径传给addAssetPath,以实现将资源路径加载到AssetManager中。由于应用程序一般使用Resource对象访问资源,因此还需要再通过AssetManager创建一个新的Resources对象,并将其添加到脱壳容器的资源缓存表中。

2、代码加载,包括以下内容:

(1)启动所获取的主Activity。

(2)将一替身Activity的启动参数发送给系统层,替身Activity为该脱壳容器中Manifest文件的Activity,后文将该替身Activity记为StubActivity。

(3)系统层获取StubActivity的启动参数来完成Activity的管理。

本发明以StubActivity作为主Activity的替身,以欺骗系统层用于管理Activity的ActivityManagerService类(下面简称AMS),从而实现对Activity的生命周期管理、栈管理或真实性的校验等工作。

(4)动态加载模块20为该主Activity创建一新的ClassLoader对象,并将该ClassLoader对象绑定到系统层加载Activity类的加载器上。通过动态代理的方式来实现Activity的启动。

具体的,动态加载模块20为该主Activity创建一新的ClassLoader对象,然后通过系统函数getPackageInfoNoCheck()构建待脱壳应用程序的LoadeAPK对象;将构造的ClassLoader对象替换待脱壳应用程序的mClassLoader成员变量;通过反射获得CurrentThread对象,并获得其中的成员变量mPackages,将已创建的LoadeAPK对象加入到mPackages的Map中。

可以理解的,系统层还利用该ClassLoader调用加载类的函数LoadClass完成代码加载。

现有的脱壳方式需要干预待脱壳应用程序的进程,因此需要获得待脱壳应用程序的root权限。而本发明利用动态加载的原理将该待脱壳应用程序的资源路径及代码加载到一预设脱壳容器中实现在应用层对应用程序的脱壳。本发明由于未进行跨进程操作,因此无需root权限,并且本发明也不用修改系统源码,能适用于普通用户的使用场景,实现方便,脱壳效率高。

当所述动态加载模块20完成资源路径及代码的加载后,脱壳容器调用该主Activity的OnCreate函数,在该函数中调用核心脱壳模块30。

所述核心脱壳模块30包括以下功能:

1、用于获取该待脱壳应用程序的dex文件结构,即获取待脱壳应用程序的dex文件在内存中对应的gDvm.userDexFiles结构体。

2、根据该dex文件结构对该待脱壳应用程序进行脱壳。具体的:

(1)根据gDvm.userDexFiles大小来开辟一个新的空间,用于存储修复后的Dex文件。

(2)通过gDvm.userDexFiles来获取当前的DexFile结构体,然后解析DexFile结构体获取其中的数据,根据该结构体中的头部数据,遍历整个DexFile文件确定需要修复的结构体。

(3)还原各结构体,对所有DexClassData结构体进行重组,在内存中形成一个新的Dex文件。

如DexClassData中的class_data_off是一个远程地址,则将该地址指向的值重新拷贝到新开辟的空间中;如DexMethod中的code_off是一个远程地址,则将远程指向的DexMethod的结构体拷贝到新开辟空间中的对应位置;如DexCode结构中insns的指令为空,则通过Method对象中的insns来将其中的指令进行还原。

对所有DexClassData结构体进行重组,即通过修复完成的DexClassData结构体,重新计算偏移,并填入DexFile对应偏移的结构中。

重新计算DexFile中的头部的数据,其中有的数据是固定不变的,如Dex文件的魔术字段、头部大小、string_ids_off等,可以直接填入,有的数据如type_ids_off、proto_ids_off等数据需要重新计算偏移后填入,该头部数据修复完成后,就形成了一个新的Dex文件。

(4)将重组后的新Dex文件从内存中Dump出来以文件的形式写到对应的输出目录中,该文件即为脱壳后的文件。

上述说明示出并描述了本发明的若干优选实施例,但如前所述,应当理解本发明 并非局限于本文所披露的形式,不应看作是对其他实施例的排除,而可用于各种其他组合、修改和环境,并能够在本文所述发明构想范围内,通过上述教导或相关领域的技术或知识 进行改动。 而本领域人员所进行的改动和变化不脱离本发明的精神和范围,则都应在本发明所附权利要求的保护范围内。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1