APK是AndroidPackage的缩写,即Android安装包(apk),能够经过将APK文件直接传到Android模拟器或手机中执行便可安装。APK的本质是一个zip的压缩包,用压缩软件打开后就能够看到里面的文件以及结构。java
APK的文件组成:android
AndroidManifest.xml:清单文件,主要包含四大组件注册信息,应用权限,和元数据等信息,此文件列出了应用的名称、版本、访问权限和引用的库文件。安全
classes.dex:Dalvid虚拟机上运行的字节码文件,咱们在将java代码编译成class字节码文件后,经过android SDK提供的工具将class转换成dex字节码,dex文件可能有多个。数据结构
META—INF: 包含 CERT.SF 和 CERT.RSA 签名文件,以及 MANIFEST.MF 清单文件。CERT.SF、MANIFEST.MF是对资源作的SHA1 hash处理,CERT.RSA包含有公钥证书和签名。app
res:包含未编译到 resources.arsc 中的资源例如:布局xml、图片、动画等。函数
resources.arsc 打包工具会提取此 XML 内容,将其编译为二进制文件形式,并将相应内容进行归档。此内容包括语言字符串和样式,以及未直接包含在 resources.arsc 文件中的内容(例如布局文件和图片)的路径。工具
lib/:包含特定于处理器软件层的编译代码。此目录包含每种平台类型的子目录,如 armeabi、armeabi-v7a、arm64-v8a、x8六、x86_64 和 mips布局
由上图可知,APK打包的流程主要有以下几个步骤:学习
工具aapt优化
输入
过程
输出
总结
这个主要是在aidl接口文件,经过SDK提供的AIDL工具生成相应的java文件,供程序调用,没有用到aidl的工程,并不会有这个过程
工具
输入
输出
总结:
工具
输入
过程
输出
android应用须要签名才能在设备上安装。
使用JDK自带签名工具的jarsigner:
对齐使用的是android-idk/tools目录下的zipalign工具,主要工做是将apk包中全部的资源文件起始偏移为4字节的整数倍,这样经过内存映射访问apk时的速度会更快。
通过这几步的编译,输出的apk文件,最终是一个具备特定文件格式的静态文件。若是拿到该文件,分析文件格式和逆向,最终是能够分析一个破解apk的业务和流程,这就必然对apk产生安全问题。
Android 支持如下三种应用签名方案:
从一开始,APK 签名就是Android 的一个有机部分。该方案基于签名的JAR。 可是v1方案存在如下一些不足:
签名不保护APK的某些部分,例如ZIP元数据。
APK验证程序须要处理大量不可信(还没有通过验证)的数据结构,而后会舍弃不受签名保护的数据,这会致使至关大的受攻击面。
APK 验证程序必须解压全部已压缩的条目,而这须要花费更多时间和内存。
因为这些不足致使apk签名后能够进行许多修改,能够移动甚至从新压缩文件,致使一些安全事件的发生。为了解决这些问题, google在Android 7.0之后引入了V2签名方案Android 7.0 中引入了APK 签名方案v2, Android 9以后引入v3(v2+)。
APK v2签名方案是一种全文件签名方案,该方案可以:
使用APK签名方案v2进行签名时,会在APK文件中插入一个APK签名分块,该分块位于“ZIP中央目录”部分以前并紧邻该部分。在“APK 签名分块”内,v2签名和签名者身份信息会存储在APK签名方案v2分块中。
搭载Android 7.0 及更高版本的设备支持APK 签名方案v2(v2方案)及更高版本的方案(在Android P(Android 9) 中,v2方案已更新为v3方案,以便在签名分块中包含其余信息,但在其余方面保持相同的工做方式)。该方案会对APK的内容进行哈希处理和签名,而后将生成的“APK签名分块”插入到APK中。
在验证期间,v2+方案会将APK文件视为Blob,并对整个文件进行签名检查。对APK进行的任何修改(包括对ZIP元数据进行的修改)都会使APK签名做废。这种形式的APK验证不只速度要快得多,并且可以发现更多种未经受权的修改。新的签名格式向后兼容,所以,使用这种新格式签名的APK 可在更低版本的Android设备上进行安装(会直接忽略添加到APK 的额外数据),但前提是这些APK 还带有v1签名。
验证程序会对照存储在“APK签名分块”中的v2+签名对APK的全文件哈希进行验证。该哈希涵盖除“APK签名分块”(其中包含v2+签名)以外的全部内容。在“APK签名分块”之外对APK进行的任何修改都会使APK的v2+签名做废。v2+签名被删除的APK也会被拒绝,由于v1签名指明相应APK带有v2签名,因此Android 7.0及更高版本会拒绝使用v1签名验证APK。
APK反编译,就是把编译后的APK文件经过逆向工程手段获取到原始代码和资源的一个过程。因为APK文件是一个具备固定文件格式的静态文件,并且可以解析和执行的,因此理论上能够对一个APK文件进行逆向的分析进行反编译、破解。若是一个APK没有进行安全方面的防御措施,是能够经过很简单的几步给破解掉。
apktool+dex2jar+JD-GUI
使用如下命令:./dex2jar.sh classes.dex
经过JD-GUI打开classes_dex2jar.jar能够看到大部分源。
经过apktool直接反编译app.apk便可看到资源文件 ./apktool d app.apk -f -o ./app3
反编译后AndroidMenifest.xml:
反编译后layout:
反编译后color文件:
至此,一个apk中全部的资源文件、代码文件所有被反编译出来,因此做为一个app开发者,为了数据、业务的安全,必需要对app进行安全处理,防止对用户形成信息、财产方面的损失,如下是几个对apk进行安全加固的处理方法。
对于apk安全加固主要分为两个方面的安全防御:
混淆代码并非让代码没法被反编译,而是将代码中的类、方法、变量等信息进行重命名,把它们改为一些毫无心义的名字。由于对于咱们而言可能CellPhone类的call()方法意味着不少信息,而A类的a()方法则没有任何意义,可是对于计算机而言,它们都是平等的,计算机不会试图去理解CellPhone是什么意思,它只会按照设定好的逻辑来去执行这些代码。因此说混淆代码能够在不影响程序正常运行的前提下让破解者对代码逻辑的理解难度加大,从而大大提高了程序的安全性。
APK必须被签名才可以安装到手机中,没有被签名的apk是没法安装到设备中的。可是签名在反编译以后是获取不到的,因此只能用本身的签名文件去签名,可是在已经安装了应用设备中在安装一个签名不一致的应用会致使安装失败。
利用该原理,能够在程序启动的时候获取应用签名,而后和正确的签名值作比对,若是不符合就直接退出程序。
既然是在程序的入口进行签名比对,就能够反编译找到程序入口处相关的代码,进行处理删除或者把签名信息改为本身的签名值,从新打包便可解决这个问题。
- 加密的源apk
- 本身的壳apk,负责解密apk,并动态加载apk的工做
- 加密工具,负责将源apk进行加密和壳dex合并成新的dex
复制代码
反调试检测是为了应对如今不少破解者使用IDA进行动态方式调试so文件,从而获取重要的信息,知道IDA进行so动态调试是基于进程的注入技术,而后使用Linux中的ptrace机制,进行调试目标进程的附加操做。ptrace机制有一个特色,若是一个进程被调试了,在它进程的status文件中有一个字段TracerPid会记录调试者的进程id值,如图所示:
查看文件:/proc/[myPid]/status,在第六行,有一个TracerPid字段,就是记录了调试者的进程id。那么就能够这么作来达到反调试的功效了:轮询遍历本身进程的status文件,而后读取TracerPid字段值,若是发现它大于0,就表明着本身的应用在被人调试,因此就立马退出程序。原理知道了,代码实现也很简单,这里用pthread建立一个线程,而后进行轮询操做: 使用pthreadcreate建立一个线程,线程启动以后执行threadfunction函数:
看看thread_funcation函数:
Dex-Java2C:将Java代码翻译为C代码,并实施Native层的代码混淆保护。
So文件加壳:对SO文件进行总体加壳保护,防止IDA Pro等工具逆向分析。
内存加密:防止内存数据被篡改或Dump,好比Dump解密后的Java代码。
自身虚拟化保护:专业版采用代码虚拟化技术对自身代码进行保护,防止逆向分析。
对于apk安全方面的技术,层出不穷,安全攻防拉锯技术不断改进不断提高。
apk的编译是把咱们写的代码、资源、库文件打包成能够在Android设备上运行的过程,而为了代码、数据、业务安全诉求须要对apk进行安全防御工做。
安全攻防是魔高一尺、道高一丈,特别是金融类app须要高度重视的工做,在此与你们一块儿学习和分享。
Thanks!
焦亚克, 民生科技有限公司用户体验技术部开发工程师。