61

Android APP安全攻防

 7 years ago
source link: http://www.10tiao.com/html/473/201806/2651474885/1.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

 背景


在移动互联网时代,APP破解已经成为产业链。APP主要有3大威胁,盗版、数据篡改和山寨。盗版是以反编译为前提通过修改某些资源文件或者是代码文件,之后重新打包二次分发。数据篡改是通过人为地使用某些专业工具来修改正版APP内存中的数据,比如把一个收费的APP变成一个免费的APP。山寨主要是通过相似度来混淆用户。

 

安全对一些涉及到直接的金钱交易或个人隐私相关的应用的重要性是不言而喻的。Android系统由于其开源的属性,市场上针对开源代码定制的ROM参差不齐,在系统层面的安全防范和易损性都不一样,Android应用市场对app的审核相对iOS来说也比较宽泛,为很多漏洞提供了可乘之机。市场上一些主流的app虽然多少都做了一些安全防范,但由于大部分app不涉及资金安全,所以对安全的重视程度不够;但是数据是我们的核心壁垒,如果我们的数据安全无法得到保证,那么我们的竞争力就无从谈起。

 

APP安全,很重要


APP攻防整体方案


01

Android基本介绍


  1. APP工程目录结构

图1 APP工程结构


  • src目录:放置所有java源代码

  • genR.javaBuildConfig.java (生成的文件)

  • assets: 用于存放需要打包到apk的静态文件,支持文件的子目录。没有资源ID

  • bin: 输出文件夹,apk就在这个文件夹内

  • jni: Android工程加入NDK支持的时候,有NDK生成,用于放置make filenativec/c++)代码

  • obj: jni生成的中间结果

  • proguard:当工程enable proguard时自动生成

  • res:资源文件夹

  • AndroidMenifest.xmlAndroid apk清单,四大组件和权限声明(以及测试组件)等都需要在此文件中声明

  • proguard-project.txt:proguard混淆规则

  • Project.properties: 定义Android工程的sdk版本,以及依赖的外部lib,是否开启proguard混淆等


2. APP打包过程

图2 APP打包(来源:网络)


如上图,Maven简单的APK打包过程

  • aapt,如果pom依赖中有apklib,将会先解压,与原文件一起产生aidl r等文件。

  • aidl, javac,编译,和传统maven编译一样,需要解决依赖,包冲突等还有scope

  • proguard,混淆,发布包需要,会把所有依赖的jar包放一起处理,形成混淆后的单一jar

  • Dex,混淆后的jar包,处理成delvik认识的classes.dex

  • lint工具优化删除无用的资源。

  • apkbuilder,APK,将把所有资源文件,和dex,打包成为apk

  • maven插件支持,将替换相应的资源文件和配置项,最后再次调用aapt打包。

  • jarsignerzipalign工具对apk进行签名,压缩对齐优化后发布。


3. APP反编译后产出

图3 APP反编译结果


如上图,对apk进行反编译后的产出,下面只列出破解过程相关的文件或者文件夹,其他无关紧要的可以忽略:

  • assets:资源文件。一些apk做了反apktool保护的会再资源文件入手,例如修改文件格式等,会导致回编译打包失败;

  • libso文件,apk引擎层(c层逻辑/数据)文件存放处。(破解重点)

  • res:资源文件。

  • smalismali文件存放apk上层(java层逻辑/数据)存放处。不同的apk可能不一样,如果apk有多个dex文件,那么反编译出来后就会有对应的多个smali文件。(破解重点)

  • AndroidManifest文件:manifest文件。如果需要增删权限,需要修改此文件。


02

环境搭建



1. 基础环境安装

1安装JDKJDK java程序所依赖的虚拟运行环境,而android开发是使用JDK 来编译的,因此JDK 也是必需的环境平台。官网下载地址为: http://www.oracle.com/technetwork/java/javase/downloads/index.html。下载完成后点击安装安装,安装完后需配置环境变量JAVA_HOME路径,指向SDK 的安装目录所在可执行文件的目录,并将%JAVA_HOME%添加到Path 中。


2安装AndroidSDK从官网上下载完SDK 后,笔者SDK 的安装目录在E 盘,所以将目录sdk\platform-tools 和目录sdk\tools 同时添加到系统的环境变量Path 中,同时,通过打开SDK Manager.exe 可以配置android 的版本及更新。


3安装Android NDK从官网下载NDK,然后配置环境变量ANDROID_NDK 即可,可以自己创建jni工程测试下。


2. 编译和编译打包工具:

1ApkTool用于APK的反编译与编译;反编译与编译的最核心的工具便是ApkTool 的工具集合了。借助不同版本的apktool.jar包对目标apk包进行反编译,同时支持对反编译后的文件夹进行回编译重新生成apk 包:

Apktool 直接下载解压就能够通过命令调用。


图3 apktool反编译


2baksmali.jarsmali.jarBaksmali.jar可以直接将apk包中的dex文件直接转成smali文件;而smali.jar可以将smali文件转成相应的dex包。

破解APK我们一般采用apktool来进行反编译和编译打包,但是如果APK做了反apktool保护,那么直接用apktool反编译就会报错。如果出现这种情况,那么就可以采用bak.smali.jarsmali.jar这种方式来进行APK的反编译和编译。

 

3. Smali层工具集:

1JD-GUI、Dex2jar:一般是配套使用,dex2jar用来将classes.dex文件解析成jar包,解析完后用jd-gui 可以直接查看反编译后的dex转成java代码。dex2jar工具的官方下载地址为https://code.google.com/p/dex2jar/,jd-gui工具的官方下载地址为http://jd.benow.ca/。

图4 jd-gui查看jar对应的java代码


2Eclipse用于反编译后smali代码的快速分析;反编译之后的smali文件可以将整个工程导入后eclipse来进行快速的代码分析。Eclipse下载比较简单,直接到官网下载即可。


3Android killer是一款可视化的安卓应用逆向工具,集Apk反编译、Apk打包、Apk签名,编码互转,ADB通信(应用安装-卸载-运行-设备文件管理)等特色功能于一身,大大简化了安卓应用/游戏修改过程中各类繁琐工作。缺点:对于大的APP,使用起来会比较卡顿,影响效率;


图5 Android killer


4. So层工具集:

(1)IDA:支持对so文件进行静态分析和动态调试;Android NDK开发本质上是通过gcc编译器在pc机上交叉编译得到的arm或者mips架构的经过优化的动态链接库文件。与linux标准的so文件是同源的。Ida内置了arm的反汇编器因此可以对NDK开发的so文件一键反汇编和反编译:


  • 静态分析:将so文件直接打开,可以切换不同视图进行代码分析;部分代码可以直接将汇编代码反编译得到C代码;

  • 动态分析:通过IDA对so下断点,attach到进程的方式对so进行动态分析调试;


(2)WinHex:是一款so二进制修改工具,支持直接图形化查找要修改的偏移量,直接修改二进制值保存;

图6 Android killer


(3)010 Editor:是一款so分析工具,可以直观得到整个so的整体架构,支持指定template对so进行分析修改。

btw,可以通过010Editor实现简单的so IDA混淆;

图7 010 Editor


03

APK破解


Android APP反编译的整体流程图如下图所示:

图8 破解整体流程

基础知识:

dex文件:Dex是一个类似Jar的存储了多有Java编译字节码的归档文件。因为Android系统(4.4以下)使用Dalvik虚拟机,所以需要把使用Java Compiler编译之后的class文件转换成Dalvik能够执行的class文件。这里需要强调的是,Dex和Jar一样是一个归档文件,里面仍然是Java代码对应的字节码文件。ODEX是安卓上的应用程序apk中提取出来的可运行文件,即将APK中的classes.dex文件通过dex优化过程将其优化生成一个·odex文件单独存放,常见于framework的system app目录下,如SystemUI.apk, SystemUI.odex。

smali文件:Smali是Dalvik虚拟机的寄存器语言,它与Java的关系,简单理解就是汇编之于C;

so库:动态链接库,一般存放核心逻辑。从APP安全角度来讲可以解决APP核心数据安全问题;ARM汇编:汇编语言;


整个流程中,从APP破解角度来说,主要涉及到哪些工作呢?

  1. 如何反编译和编译打包?

  2. 如何进行Smali机器码分析修改?

  3. 如何进行ARM汇编分析修改?

下面会逐一介绍。


1. 反编译和编译打包

Android APP反编译和编译打包使用章节2.2.2提到的工具进行操作即可,这里讲2个过程中可能会遇到的问题。


1Dex加固

如果apk中使用了dex加固技术,那么对apk反编译之后,我们会发现,没有相应的smali文件生成。目前apk dex加固方式有3种,分别是dex隐藏到asset文件夹中、dex文件末尾做加密、dex隐藏到so中,具体apk采用哪种形式需要具体去分析;目前最常用的第三种方法;那么我们重点讲一下如何解决第三种?

我们终点看下dex加在到内存中的主要流程图,抽样如下,有兴趣的同学可以一步一步跟进查看源代码,可以参考/dalvik/dexopt/OptMain.cpp


图9 dex加载校验流程


如上图,在Androiddvm下,apk中的dex文件运行时是通过libdvm.so中的dvmDexFileOpenPartial函数来加载,那么不管apksodex文件做了什么加固,apk最后通过libdvm.so加载到内存中的必须是一个完整的dex文件,因此我们可以基于此函数进行断点dump,那么得到的就是完整的dex文件;


图10 dvnDexFileOpenPartial函数


2. Smali机器码分析修改

smali代码中包含了app java层中所有代码逻辑和数据,我们可以通过分析smali代码得到appjava层的逻辑和数据;目前分析修改smali代码的工具包括有dex2jar+jd-guiEclipseandroidkiller等,我们可以通过这些工具来进行smali 代码分析修改,我们在smali代码注入主要会遇到2个问题,如何快速定位和高效注入。


(1)smali关键代码定位

  • 顺序查看法:从application入口开始,逐行往下分析;

  • 代码注入法:手动修改apk中的代码,加入Log输出,配合Logcat查看日志输出;

  • 特征查看法:根据特定空间的value值在string.xml中查找对应的value或者id,全局搜索对应的value或者id引用地方进行定位;

  • 名字猜测法:apk反编译后,如果不混淆,那么我们可以根据smali中的文件名或者函数名进行猜测定位;


(2)高效smali代码注入

在修改Java 反编译后的smali 机器码之前,我们目前还缺少一个可以调试修改效果和定位功能关键点的工具。在调试中打印日志是一个非常有效的方法,通过在smali 代码中插入smali 日志功能,便于分析apk 包中的运行逻辑以及功能与代码的对应位置。


  • 新建一个工程,写一个简单的测试类命名为任意名称,如HelloSmali.java,生成原始apk文件;

  • apktool 反编译获得HelloSmali.java 对应的smali 文件。

      

这样从java 明文到smali 代码的生成,完全构造了一个日志类的smali 机器码。只需要在smali 的任意位置调用我们创建的smali 文件中相应的输出代码即可;举个栗子,如下图,标红处就是日志输出调用。


图11 dvnDexFileOpenPartial函数


3. ARM汇编分析修改

APK反编译后我们可以得到相应的so文件,so 中基本存放了apk最核心的数据和逻辑。那么在抓取so数据我们主要需要解决2个问题,如何绕过so签名校验和如何抓取数据,以下我们会分别讲解解决这2个问题的思路。


(1)so签名绕过

目前APK为了防反编译后的核心数据安全,会在so层做多处的签名校验。如果没有绕过so的签名校验,我们破解之后打的新包会crash或者核心功能无法正常运行的。对于so层的签名校验绕过,主要有3种方法:


  • 静态分析:通过ida工具进行静态分析,基于signature关键字进行查找定位,然后篡改逻辑跳转实现签名绕过目的。

  • Android Framework签名模块破解:so去获取apk的签名是从系统签名模块获取相应的签名数据,因此基于操作系统Framework模块的getPackageInfo函数做破解,让其返回指定的签名内容来绕过签名校验。


图12 getPackageInfo函数破解


  • 签名Hookhook系统签名函数,让其返回指定签名内容来绕过签名校验,原理类似第二种方法;


(2)so数据抓取

apk为了保护其核心数据,会将主要逻辑放入到so中,会大大增加数据被他人抓取的难度。目前从so中进行数据抓取主要有3种方式:静态调试dump(依赖ida pro)、so注入、so hook,而且so hook也分为导入表、导出表、inline hook三种;比较常用的是inline hook推荐Cydia Hook框架来做相应的数据抓取;下图是inline hook的简单原理:


图13 hook原理


04

APP防护




1. APP防护要点

为了保障我们Android APP的数据安全,有哪些措施是我们可以做的呢?总结了下,主要有以下这些点:

  • 添加apktool保护:不让轻易可以进行反编译和编译打包;

  • Dex加固:保护dex文件,但是使用此策略可能会影响apk启动效率;

  • 核心逻辑和数据尽量放入so:可以加大破解难度;

  • 签名校验:保护核心函数逻辑和数据;

  • 反动态调试:不能轻易使用ida工具进行调试;

  • 反hook:不能直接对so进行hook;

  • 服务端联动:同个IP或者同个deviceID出去的请求有qps限制和总量请求限制;

  • 其他。


  总结和未来展望


APP安全很重要!破解相关的技术需要不断的学习和沉淀,才能持续为产品线保驾护航。路漫漫其修远兮,吾将上下而求索。



作者介绍

吴彬杰

百度地图测试开发高级工程师,聚焦安卓APP安全,为百度地图等产品保驾护航。





About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK