一种Android应用程序代码保护机制鉴别方法与流程

文档序号:12669729阅读:447来源:国知局
一种Android应用程序代码保护机制鉴别方法与流程

本发明属于网络空间安全技术领域,尤其涉及一种Android应用程序代码保护机制鉴别方法。



背景技术:

近年来,随着移动互联网的快速发展和应用,以Android为代表的智能移动端得以迅速普及应用。在这样的一个趋势下,涌现出一大批优秀的移动互联网公司,他们以APK应用程序为载体,向人们传达不同行业移动互联网思维和商业模式。然而,如果这些APK应用程序的源码遭到泄露,必然会给移动互联网公司带来巨大的经济损失。逆向工程能破开Android应用程序的外壳,借助Android逆向工程技术,分析者可以从一个APK应用程序包中解析出源码。随着APK应用程序防护技术的发展,很多公司采取了相应的技术手段,来防范通过逆向工程技术获取程序的源代码,比如采用代码混淆、代码加密、JNI调用等技术。一方面,很多公司用这些保护机制来保护自己的源代码;另一方面,很多网络攻击者开发的恶意代码为了逃避杀毒软件的查杀,采用上述保护机制对自己的代码进行保护,从而给恶意代码的检测和查杀造成了极大的困难。所以,判断源代码的保护机制,不管对于想保护自己源代码的公司,还是对于研究恶意代码检测技术的研究机构都具有重大意义。

Android逆向工程介绍:

逆向工程,顾名思义,就是通过现有的产品,通过一些手段进行逆向推演,最后还原出产品本来的架构和组成等。对于一个Android应用程序来说,我们可以通过最原始的APK包,利用一些工具,还原出APK的逻辑代码、系统架构、函数调用树、界面源码等。常见的工具有APKTool、dex2jar等。这也是我们在本发明方法中主要使用的工具。

Android逆向工程主要处理两部分内容:xml文件和dex文件,xml文件是APK的界面设计布局所使用的语言,dex文件存储的是java经过编译所生成的对应代码。对于xml文件的反编译,一般可以采用APKTool和AXMLPrinter2.jar工具。对于dex文件的反编译,一般可以采用APKTool和dex2jar工具。

dex2jar应用于反编译dex文件的过程可以分为两步:第一步,从一般的APK包中恢复出dex文件。APK包本质上是一个zip格式的压缩包,我们可以通过修改文件的后缀名并解压的方式,恢复出dex文件。第二步,从dex文件反编译出.class文件,可以使用dex2jar.ba在windows命令行下,输入dex2jar+反编译需要的dex文件名即可完成反编译。从jar文件恢复出Java源代码的技术相对较成熟,主要的工具包括jd-gui、Jodeclipse以及JadClipse。

通过APKTool工具我们可以将一个正常的APK包反编译成Smali程序语言代码,该程序语言可被Android系统里的Java虚拟机(Dalvik)所解析,该程序语言与Java程序语言有一定的相似性,因为其是由Java程序语言在打包时候经过转换得来的,有一定Java程序语言编程基础的人可以很轻松地阅读Smali程序语言。

Android系统代码保护机制介绍:

从代码被保护的客体来看,代码保护措施分为两种,分别是结构上的保护和语义上的保护。结构上的保护,如代码JNI接口调用等,让代码本身处于一种不可拿到的状态,分析者也就无法破获代码的具体内容了。语义上的保护,如代码混淆等,指的是代码的含义被人为进行了处理,并且这种处理是不可逆的,导致分析者即使拿到了代码,也无法阅读代码的具体内容,但是机器使用某些工具是可以解析的。需要注意的是,代码加密是一种结构上的保护,具体原因如下面详细解释。

1.对于代码结构的保护

JNI技术:JNI技术已经成为Java开发平台的一部分,它允许Java代码和其他程序语言写的代码进行交互。JNI技术一开始是为了本地已编译语言,尤其是C和C++程序语言而设计的,但是它并不妨碍你使用其他程序语言,只要JNI调用约定支持就可以了。一般来说,APK程序运行在Android系统的应用程序层,先将APK程序打包成的jar文件解析成dex文件,然后交由Java虚拟机(Dalvik)进一步执行。对于C程序语言编译的so文件,Java虚拟机(Dalvik)是不能够直接执行的,它可以将这个文件递交给自己的上一层去执行。很多开发者将应用程序的核心代码编译成so文件,再由JNI去调用。这样做的原因是相对于jar文件,so文件的反编译难度会有所增加。

代码加密技术:这是利用Java虚拟机类装载机制实现加密解密,类装载机制指的是:在执行Java程序的时候,Java虚拟机会将*.class类文件加载到内存中,并形成一个Class的对象。代码加密首先将代码用密钥加密,然后发布出去,当该代码的应用程序在执行的过程中,需要调用ClassLoader的loadClass方法时,开发者提前重写了loadClass方法,使其变成解密器,利用密钥进行解密,完成代码的顺利执行。上面提到,代码加密是一种结构保护措施,因为解密的密钥往往被嵌入在APK包内。

2.对于代码语义的保护

代码混淆技术:相对来说成本较低、效果较好的当属代码混淆技术。代码混淆是将计算机程序语言的代码,转换成一种功能上的等价,但是其形式人类难于阅读和理解的行为。代码混淆可以用于程序源代码,也可以用于程序编译成的中间代码。具体做法有:

将代码中的各种元素,如变量、函数、类的名字改写成无意义的名字。比如改写成单个字母,或是简短的无意义字母组合,甚至改写成“__”这样的符号等,使得代码阅读者无法根据名字猜测其用途。

重写代码中的部分逻辑,将其变成功能上的等价,但是更难理解的形式。比如将for循环改写成while循环,将循环改写成递归,精简中间变量等。

打乱代码的格式,比如删除空格,将多行代码挤到一行中,或者将一行代码断成多行等。

在Android的开发平台工具中,内嵌了一个代码混淆工具ProGuard。ProGuard是一个压缩、优化和混淆Java字节码文件的免费工具,它可以删除无用的类、字段、方法和属性。可以删除没用的注释,最大限度地优化字节码文件。它还可以使用简短的无意义的名称来重命名已经存在的类、字段、方法和属性。Android系统开发者常常用其混淆最终的代码,以增加项目被反编译的难度。



技术实现要素:

针对现有技术的上述状况,本发明提供一种Android应用程序代码保护机制鉴别方法,能有效识别出代码是否有保护机制,以及采用的是何种保护机制,并以人们易懂的形式输出鉴别结果。

本发明Android应用程序代码保护机制鉴别方法,包括以下步骤:

步骤一、载入APK包,按照路径读取APK包文件;

步骤二、对APK包进行初步的逆向工程反编译,判断获取APK包的安装包名称、版本,如果成功则进入步骤三,不成功则加入手工辨识标签后,进入步骤六;

步骤三、进入反编译器,对APK包进行深入的反编译操作,如果反编译成功,得到APK源代码,则进入步骤四;如果反编译不成功则进入APK解析器,通过包解析操作得到源代码,如果成功则进入步骤四,不成功则加入手工辨识标签后进入步骤六;

步骤四、对APK源代码进行分析,判断代码是否经过混淆及是否存在结构保护,得到分析结果集后进入步骤五;

步骤五、对结果集进行归类整理,将结果集用人类能理解的语言描述、输出;

步骤六、提取具有手工辨识标签的APK包,进行手工辨识,最终得到结果集。

优选地,步骤二及步骤三调用程序APKTools进行APK包的反编译,利用Process类封装反编译APK包的进程,然后调用该进程进行APKTools程序执行,一旦APKTools程序执行完毕,则判断APK包已经反编译完毕。

优选地,步骤四判断代码是否经过混淆的步骤如下:如果APK源代码的变量名、类名符合正则表达式,则判断代码经过混淆;如果APK源代码的变量名、类名不符合正则表达式,则调用驼峰命名法检测其是否符合规则命名法,如果符合规则命名法则判断代码经过混淆,如果不符合规则命名法则打上人工检测的标识,后续进行人工判断。

优选地,步骤四判断代码是否经过混淆的分析入口为:根据配置清单将APK源代码的类名转换为路径,找到内部有代码的文件夹,然后再进行是否经过混淆的检测。

优选地,步骤四判断代码是否经过混淆时,若在APK包的资源文件夹lib下检索到jar包或者so文件,则判断APK源代码引用了第三方的支持库文件,将对应的路径排除,不进行是否经过混淆的判断。

优选地,步骤四判断代码是否存在结构保护时,若在APK包的资源文件夹lib中存在.so文件,则判断APK源代码使用了JNI技术。

与现有技术相比,本发明具有如下优点及有益效果:

1、对APK包进行初步和深入两个层次的逆向工程反编译,通过初步反编译获取到APK包的安装包名称、版本等关键信息,通过深度反编译获取到APK包的源代码,得到源代码后利用代码逻辑保护检测器和代码结构保护检测器分别对代码进行分析,最终将分析后的结果集进行归类整理,使得原本只有计算机可以懂的结果集用人类可以理解的语言描述,例如报表等方式输出,极大方便了源程序开发者对自己所开发程序的管理,也方便了研究恶意代码检测技术的研究机构对相关恶意代码的监管。

2、对于分析过程中无法用机器自动化进行逆向工程和反编译的APK包,本发明方法能自动加上手工辨识标签。待分析完毕后提取具有手工辨识标签的APK,进行手工辨识后得到结果。

3、本发明等反编译结束后,才进行下一步检测,即判断代码是否经过混淆或存在结构保护,保证了整个鉴别过程的可靠性。

4、判断代码是否经过混淆时,并不直接从解析的Smali目录开始逐层地进行判断,而是根据配置清单将APK源代码的类名转换为路径,找到内部有代码的文件夹后再进行是否混淆的检测,极大地提供了算法的效率。

5、善用正反馈,充分借助代码的历史检测结果来辅助分析当前的检测结果,将历史检测结果与当前检测结果进行比对,最终得出较为科学的分析结果集,以免误判。

附图说明

图1是本发明实施例提供的一种Android应用程序代码保护机制鉴别方法的流程图。

图2是本发明实施例提供的鉴别结果报表结构图。

具体实施方式

下面结合实施例和附图对本发明作进一步详细的描述,但本发明的具体实施方式不限于此。

实施例

本发明Android应用程序代码保护机制鉴别方法首先载入APK文件安装包,对APK包进行逐一反编译,再对反编译以后的文件进行扫描,查看其是否经过代码混淆和代码加密等措施。如图1所示,具体来说包括以下步骤:

步骤一、载入APK包,按照路径读取APK包文件。可通过路径加载器完成APK包的载入,路径加载器可利用Java语言自带的文件操作框进行编写实现。

步骤二、对APK包进行初步的逆向工程反编译,判断获取APK的安装包名称、版本等关键信息。如果成功则进入步骤三,不成功则加入手工辨识标签后,进入步骤六。初步逆向工程反编译的核心工具是APKTool。APKTool的解析原理是通过将一个APK包文件转换成ZIP压缩文件,按照事先定义好的解析规则,解析AndroidMainfest.xml,将classes.dex文件解析成Smali程序语言文件。在本步骤中,主要是从AndroidMainfest.xml中的packagename字段中解析安装包名称,从versionname与versioncode中解析APK的版本信息。

步骤三、进入反编译器,对APK包进行深入的反编译操作,如果反编译成功,得到APK源代码,则进入步骤四,不成功则进入APK包解析器。APK包解析器会对APK包进行解析操作,尝试通过包解析操作得到源代码,如果成功则进入步骤四,不成功则加入手工辨识标签后进入步骤六。

反编译器有许多预先定义的规则,正常的APK包可以被这些规则所解析。一旦APK包被保护,就会破坏这些规则,如采取加密、XML主配文件保护等手段,反编译就无法顺利执行,从而导致APKTool抛出异常。抛出异常后进入步骤六。通过反编译器获取源码的过程中,如果失败,我们就能知道其针对于APK安装包进行过防止反编译保护,即经过结构类保护。这些结果会被记录下来,提供给结果集分析器。

步骤四、对APK的源代码进行分析。利用代码逻辑保护检测器和代码结构保护检测器分别对源代码进行分析,判断源代码是否经过混淆及是否存在结构保护,得到分析结果集后进行步骤五操作。

APK包能否解析是APK包经过保护与否的一项重要标志,但是无法判断APK包内部的代码是否经过混淆保护。本发明方法采用代码混淆检测器,对解析出来的代码进行混淆检测,判段其是否经过代码混淆。代码混淆检测器会逐级检测已经解析的代码是否经过混淆。对计算机无法解析的代码,会给它打上手工解析标识。

经过APKTool反编译的APK包会生成和原来文件名一样的一个文件夹,内部放置了AndroidMainfest.xml、res等文件,代码放置在Smali文件夹下。

此外,如果在lib的文件夹及子文件夹中含有非第三方的so文件,那么就可以判断其进行了JNI调用。

在整个源代码的解析与混淆检测过程中,需要克服以下技术难题,现在一一进行分析与阐述:

如何判断代码是否已经反编译结束

步骤二及步骤三所述反编译在执行的过程中,如何判断出这个APK是否已经反编译结束,是至关重要的一步,因为只有等反编译结束后(不论成功与否),才能进行下一步检测。这里不能是一个简单的if-else判断,因为我们调用的另外一个程序APKTools来反编译APK,这个程序独立于主程序,无法在一个独立的程序中加入Flag判断其是否已经对一个APK执行反编译结束。如果进行循环检测,一方面,可能出现检测效率问题,另一方面,因为对于一个APK文件反编译后目录的结构是不确定的,也就是说,找不到循环结束的条件。在这里,将用到Java的Process类,这个类是一个抽象类(该类所有的方法均是抽象的),封装了一个进程(即一个执行程序)。Process类提供了执行进程输入、执行进程输出、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。我们利用Process类封装反编译APK包的进程,然后调用该进程进行程序执行,一旦APKTools程序执行完毕,那么该应用程序的进程就会被系统自动置空,也就能依据此,判断一个APK已经反编译完毕。

如何判断代码经过混淆

经过混淆的代码,通常变量名、类名是由一些难以理解的字符串进行拼接而成的,所以往往是没有意义且杂乱的。通过大量的手工实验我们发现通过Proguard混淆后的变量名和类名,一般都用a、b、c、d等1到3个字符组成,正则表达式为^[a-z]{1,2,3}$。此时Java语言中的正则表达式,为我们提供了很好的现成调用方法。正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。一方面,通过正则表达式,我们能判断一个类的类名,以及其内部变量,是否符合Proguard的混淆规则。另一方面,有极少一部分APK不是经过Proguard进行代码混淆的,那么这些APK内部类名就可能是一些其它的特殊符号。正则表达式会在上述判断不符合的情况下,进一步判断一个类的类名是否符合类名的拼写规则,目前业内通用的类名拼写方法是驼峰命名法,即对于一个单词,首字母大写,其余字母小写。如登录界面的拼写方法是LoginActivity,这种每个单词的首字母都大写的我们叫做大驼峰命名法,正则表达式为^([A-Z][a-z]+)$,对于类似于getAttribute这样的机构,我们叫做小驼峰命名法,正则表达式为^[a-z]+([A-Z][a-z]+)$。大驼峰命名的名字常见于类名等命名规则中,小驼峰命名则常常出现在方法名称中。如果变量名、类名不符合^[a-z]{1,2,3}$正则表达式,我们调用驼峰命名法检测其是否符合规则命名法,如果不符合规则命名法,其代码很可能经过特殊符号的混淆,我们会为其打上人工检测的标识。为什么我们要首先检测是否满足^[a-z]{1,2,3}$表达式呢?首先,大多数经过混淆的代码类名、变量名,都符合上述的命名规则,符合该规则能迅速判断一个类名经过混淆。其次,从执行效率方面,首先判断命名规则若满足^[a-z]{1,2,3}$表达式,肯定是经过混淆的,若不满足^[a-z]{1,2,3}$表达式,则不一定没有经过混淆,还要经过驼峰命名法进行检测,如果驼峰命名法检测结果为假,也不一定是经过混淆,其还需要人工去判断。如果最先进行驼峰命名法检测,那么不论检测结果真与假都需要进行下一次的判断,才能确定其是否经过混淆。

混淆检测入口的判断

如果直接从解析的Smali目录开始逐层地进行判断,那么就会出现效率问题,一个混淆后的代码,可能出现在第一个子目录,也有可能出现在最后一个子目录。如果都从第一个子目录开始找起,难免会造成效率低下。因为有的子目录可能级联好几个子目录,每个子目录中可能都没有混淆,而且,并不是每个子目录中都有代码,很多情况下,目录中层层嵌套着其余的目录。目录递归也会对效率造成相应的影响。

我们发现不管代码如何混淆,它的入口函数是不会进行混淆的。实际上,由于Activity入口函数属于Android四大组件之一,要在配置清单文件中进行相应的配置,Activity入口函数一旦经过混淆,那么在配置清单中就无法找到相应的Acitivity函数名称,Android程序就会出错。基于此,我们可以从配置清单入手,将类名转换为路径,找到内部有代码的文件夹,然后再进行混淆检测。

src下的包结构是以“.”作为分隔符的,我们可以将其中的“.”替换为文件路径分隔符“/”,用以表示路径。值得一提的是,在有的APK中,类并不是全名,往往是类似于“.LoginActivity”这类的名称,我们可以通过获取包名的方式,将APK包名和类名进行拼接,就能得到目录级联下的实际文件位置。而APK包名在配置文件中也可以直接找到。

lib包检测

一方面,有很多应用程序,代码本身其实没有进行过代码混淆,但是调用了第三方的代码,导致代码混淆。这样的代码我们也可以在APK包的资源文件夹lib下进行检索,如果包含常用的第三方jar包,或者so文件,那么就可以知道这些应用程序引用了第三方的支持库文件,将对应的路径排除即可。常用的第三方库文件有地图应用、广告应用等,如libBaiduMapSDK_v3_5_0_1.so就是百度地图的核心类库。在检测其代码是否经过混淆的时候,我们可以将com.baidu.*目录下的所有文件排除在外,不进行混淆检测。

另外一方面,如果APK应用本身使用了JNI技术调用自身存储的C/C++代码,那么在APK包的资源文件夹lib中,必然存在着.so文件,这可以作为我们分析判断一个APK有没有经过代码保护措施的重要依据。

善用正反馈

尽管本发明方法设计了完备的检测方案,但是仍然可能出现误报的情况,如何提高检测的准确率以降低误报率,也是本发明方法研究的重点。对此,本发明方法加入了正反馈功能,即借助历史的检测结果来辅助分析现有的检测结果。将先前的检测结果,通过报表的形式导入到待检测APK源代码的当前判断结果中进行比对,最终得出较为科学的分析结果集。比如说,一个APK早期版本,发现其经过代码混淆,到了后面的版本,发现其没有经过代码混淆,那么很可能结果是有问题的,需要加上人工标识,后面再进行排查以得出正确的结果。

步骤五、对结果集进行归类整理,将原本只有计算机可以懂的结果集用人类可以理解的语言描述,如报表等方式输出结果,呈现给用户。这里我们选择用jexcelapi工具生成excel报表的形式并呈现给用户,如图2所示。用户可以在报表上看到包名、版本、是否经过保护措施、经过何种保护措施以及判断理由等信息。

步骤六、步骤二与步骤三中,对于计算机分析无效的代码,本发明方法会自动加上手工辨识标签。步骤六提取具有手工辨识标签的APK包,进行手工辨识,最终得到结果集。

以上所述仅为本发明的较佳实施例之一而已,并不用于限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。

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