APK逆向分析破解

背景介绍

很多同学都对移动应用的安全扫描不明所以,不安全的应用会出现什么样的问题呢?举例来说,对于未进行保护的Android应用,有很多方法和思路对其进行逆向分析和攻击。使用一些基本的方法,就可以打破对应用安全非常重要的机密性和完整性,实现获取其内部代码、数据,修改其代码逻辑和机制等操作。今天小编就要介绍一些基本的应用逆向和分析方法,至于接下去的事儿,就不多说啦!准备好充充电了吗!


一、 环境搭建

    1.1 安装JDK

JDK是java程序所依赖的虚拟运行环境,而android开发是使用JDK来编译的,因此JDK也是android的必需环境平台。SDK的官网下载地址为http://www.oracle.com/technetwork/java/javase/downloads/index.html,打开页面,目前最新版本为JDK 8,如图2-1所示:

图2-1

点击DOWNLOAD按钮,进入如图2-2的页面,可以根据自己的操作系统平台来选择下载所需的JDK:

图2-2

笔者的系统为Win7平台32位系统,选择Windows x86下载,下载完成后点击安装安装,安装完后需配置环境变量JAVA_HOME为E:\jdk1.7.0_10\bin的路径,指向SDK的安装目录所在可执行文件的目录,并将%JAVA_HOME%添加到Path中,如图2-3所示:

图2-3

为了进一步验证JDK是否安装成功,我们可以在命令行窗口输入java –version的命令,如果出现图2-4中的所示信息,则表示安装成功:

图2-4

1.2 安装Android SDK

Android SDK是供开发android应用的开发人员使用的,其提供了可调试APK包的模拟器及监控手机日志等工具和平台。官网的最新下载地址为http://developer.android.com/sdk/index.html从官网上下载完SDK后,笔者SDK的安装目录在E盘,所以将目录E:\ androidsdk\sdk\platform-tools和目录E:\ androidsdk\sdk\tools同时添加到系统的环境变量Path中,方法与2.1章节中所述的相似。添加完后在cmd命令窗口测试emulator –version检查是否安装成功,如果成功,则会出现图2-5的画面:

图2-5

同时通过打开SDK Manager.exe可以配置android的版本及更新,该过程会自动联网获取数据,如图2-6所示:

图2-6

1.3 安装Android NDK

Android NDK是基于Android下编译与调试so动态库的工具包。许多Android应用利用so包将关键的代码隐藏在里面,一方面简化了上层Java代码的技术实现难度,一方面增强了核心技术的保护。NDK的官网下载地址为https://developer.android.com/tools/sdk/ndk/index.html。下载完后解压,然后配置环境变量ANDROID_NDK即可。NDK目录下有两个基本例子,一个是hello-jni,一个是two-libs,我们可以直接编译hello-jni的例子生成libhello-jni.so包,将它放在android的libs/armeabi目录下,我们就可以用eclipse工具打开HelloJni工程,发现通过JNI的接口是属于native方法调用,如图2-7所示:

图2-7

该样例在Activity初始化时通过调用so包中的stringFromJNI函数获取字符串并将其内容显示到界面上。为了将打包成 apk文件,可以直接选择eclipse的export功能,在弹出的对话框中选择Export Android Application选项,如图2-8所示:

图2-8

点击Next下一步,然后选择HelloJni工程,再点击Next下一步,发现需要Keystore,即安全钥匙和证书,我们可以自己创建一个或者使用一个己经存在的证书,如图2-9:

图2-9

接着输入密码便可以成功生成Hellojni.apk包了,接下来我们试试是否可以运行,我们发现界面上出现一行字符Hello from JNI!,说明android在调用JNI接口读取了so包中的字符串并显示到屏幕上,如图2-10所示:

 

图2-10

1.4 安装Apktool、Jd-gui、Dex2jar

编译与反编译的最核心的工具便是ApkTool的工具集合了,apktool会借助sdk的版本jar包对己经己经编译好的apk包进行反编译,同时对反编译后的文件夹进行回编译重新生成apk包。

Apktool直接下载解压就能够通过命令调用。官方下载地址为https://code.google.com/p/android-apktool/

由于apktool工具的参数比较多,使用起来不太方便,为此封装两条批命令文件分别到decodeapk.bat和encodeapk.bat中,具体命令如下所示:

java -jar "%~dp0\apktool152.jar" d %1   %2 %4 %5 %6 %7 %8 %9

java -jar "%~dp0\apktool152.jar" b %1   Update.zip %4 %5 %6 %7 %8 %9

d参数表示解码反编译,%1表示需要解析的apk包的全路径;b参数表示编码回编译,%1表示反编译apk包后的文件夹全路径。其中apktool152表示使用的是1.52的工具版本,这里最好使用最新版本,否则可能出现编译错误。

不过直接回编译后的apk包是不能直接运行的,因为Android系统在安装的时候会校验签名,因此需要进行重新签名后才能正常运行。重新签名的工具使用的是signapk.jar包,signapk是一个包含在Android平台源码包中的工具,使用时的具体命令如下所示:

java -jar   signapk.jar testkey.x509.pem testkey.pk8 update.zip update_signed.zip

dex2jar是用来将classes.dex文件(见3.1章节)解析成java代码,便于分析可读,解析完后用jd-gui可以直接查看反编译后的java代码,dex2jar工具的官方下载地址为https://code.google.com/p/dex2jar/,jd-gui工具的官方下载地址为http://jd.benow.ca/,通过jd-gui可以查看到反编译后的java源码,如图2-11所示:

图2-11

1.5 安装IDA

IDA是一个非常强大的交互式反汇编的工具,它能够提供交叉引用,图示,注释等多种便捷的功能便于代码分析。IDA是一个收费工具,它的官网获取地址是https://www.hex-rays.com/products/ida/。IDA能够直接载入so包进行反编译分析,打开IDA工具会出现如图2-12的对话框,其中New表示新打开一个需要反编译的文件,Go表示是不打开直接进入IDA的主界面,Previous表示载入上次打开过的文件,下面是打开过的历史记录文件的列表,可以直接双击打开以前分析过的文件:

图2-12

我们选择2.3章节中NDK配置完后的一个hello-jni样例中的libhello.so包进行分析,选择ELF for ARM方式,其他选项以默认项为准,处理器为80x86 的方式,选中分析调试信息,如图2-13所示:

图2-13

然后点击OK按钮,进入分析的主界面,如果载入的so包比较大的话,可能分析的时间会很长,在界面上方有一个彩色分割条,等待分割条的颜色稳定后,反编译分析处理便完成了。IDA的整个主界面分为Function window,Graph overview,Output window,IDA View,Hex View,Imports,Export六个主要的分析子窗口,如图2-14所示:

图2-14

Function window主要罗列反编译后的so包中的所有函数接口,包含对外的JNI接口,也包含一些内部调用的接口,从图2-14中我们可以看到有一个Java 的JNI函数接口;Graph overview提供分析后的函数之间的关系图示,通过其中的流程图能够清晰地描述被分析文件的函数之前的调用关系,同时点击图示可以使直接定位到对应的代码;IDA View是分析反汇编的主要窗口,是对Graph overview的具体代码的展现的子窗口,so包反汇编后的代码属于ARM汇编;Hex View是直接描述原文件的十六进制代码,当点击IDA View中的一条语句时,Hex View会自动对应到该语句的十六进制代码(图2-15),一般so包会出现16字节和32字节两种长度的十六进制编码;Output window是描述处理文件或调试文件等的输出信息的窗口;Imports和Export分别描述文件的导入与导出的函数接口名信息,一般Export在so包中会出现大量的JNI接口,因为JNI接口是导出给上层调用的开放接口。

图2-15

1.6 安装WinHex

WinHex是用来修改十六进制文件内容的一个工具,在修改二进制文件方面,它的功能算是非常齐全的。WinHex也是一个收费的软件,其官方地址是http://www.x-ways.net/winhex/index-m.html。用其打开2.5章节中所述的so包,如图2-16所示:

图2-16

在主界面Offset是表示的是文件偏移地址,以十六进制描述,在右侧每行有16个字节的十六进制编码。如果需要定位十六进制编码,可以通过Search菜单进行搜索,可以直接在主界面对十六进制编码进行修改,修改完后,对应的编码会变成蓝色。


1.7 安装Eclipse

Eclipse下载比较简单,可以到官网http://www.eclipse.org/downloads/下载java EE版本,笔者安装的版本如图2-17所示:

图2-17

接下来将android SDK配置到eclipse下编译开发apk程序,打开eclipse的菜单Help-Install New Software,如图2-18所示:

图2-18

进入到安装插件界面,点击Add,Name自己命名,Location输入链接地址https://dl-ssl.google.com/android/eclipse/,如图2-19:

图2-19

接下来就是点击下一步等待安装完,重启eclipse即可,为了验证下是否安装成功可以打开New菜单,发现多了Android工程,则表明己经安装完成。但是别忘了还要配置SDK的地址,这个在菜单window里的preferences,这里由于篇幅就不再详细介绍了。

 

二、  APK逆向及结构介绍

     2.1  apk逆向

在前面章节中,我们己经准备好了Apk逆向的基本工具,接下来我们可以用它们对APK包进行逆向分析了,为了简单地阐述这个过程,我们以NDK包中的HelloJni.apk作为示例,我们加入判断解压路径是否存在,如果存在则删除解压路径的批处理代码,将其一块封装到2.4章节所述的decodeapk.bat中,具体代码如下:

@echo off

set str=%1

rd /q /s    %str:~0,-4%

set PATH=%CD%;%PATH%;

java -jar "%~dp0\apktool152.jar" d %1   %2 %4 %5 %6 %7 %8 %9

 

Echo Decode Complete

我们将helloJni.apk包复制到apktool所在的路径,然后在命令行输入decodeapk.bat HelloJni.apk命令并执行,如图3-1所示:

图3-1

从上图中我们可以看到apktool工具对apk包进行反编译处理,将其中的资源文件以及smali机器码解压出来(smali代码在后面的3.2章节中会详细阐释)当没有错误并且出现Decode Complete时说明反编译成功,反编译完后会在当前目录下生成一个同名文件夹helloJni。

接下来我们在2.4章节所述的encodeapk.bat中合并重签名命令,使得回编译后生成包可以直接安装运行,具体代码如下:

@echo off

 

del /a /f /s /q %1_rebuild.apk

set PATH=%CD%;%PATH%;

java -jar "%~dp0\apktool152.jar" b %1   Update.zip %4 %5 %6 %7 %8 %9

 

Echo Auto-sign Created By Dave Da illest 1

Echo Update.zip is now being signed and will be   renamed to update_signed.zip

 

java -jar signapk.jar testkey.x509.pem   testkey.pk8 update.zip update_signed.zip

del /a /f /s /q Update.zip

rename update_signed.zip %1_rebuild.apk

 

Echo Encode Complete

最后在命令行输入encodeapk.bat HelloJni命令,HelloJni即为反编译后生成的目录名,执行完后会将该目录下的资源文件及代码文件重新打包签名生成HelloJni_rebuild.apk,当没有错误并且出现Encode Complete时说明回编译成功,如图3-2所示:

图3-2

为了区分反编译后的apk的运行效果,我们稍微对smali代码进行一下修改,我们打开smali/com/example/hellojini文件夹,找到HelloJni.smali,在第12行有一句const-string v0, "hello-jni"代码,然后我们定位到第51行之前,即setText(Ljava/lang/CharSequence;)V语句之前,我们如法炮制地加入const-string v1, "Hello from APK"一句机器码,然后再回编译生成apk包,我们发现界面显示发生了明显的变化,这个结果十分令人欣喜,说明我们己经成功地反编译了Apk包并且还修改了其中的代码逻辑,这样我们完全可以灵活自如地在Apk的smali机器码中加入任何想要的逻辑了,如图3-3所示:

 

图3-3

2.2  apk结构介绍

   2.2.1 整体结构

由于apk包本质上是一种zip压缩包,用任意一种rar软件,可以对其中的内容进行查看。经较反编译后与反编译前的目录结构可以发现,反编译后的目录没有META-INF文件夹,却多了一个smali文件夹,同时classes.dex文件也不见了,apktool.yml是apktool工具生成的一个日志文件。其实classes.dex正是java代码编译后的字节流文件,apktool工具将classes.dex反编译生成了对应的smali机器码,并且还原了其中的目录结构,使得java代码从机器码的层面上一览无余,而META-INF中含有apk包的签名信息,经过反编译后签名信息失效了,所以META-INF文件夹也就不见了,同时apktool工具按照配置文件将对应的资源解压出来放到res文件夹内,lib文件夹中含有被调用的so包等C++库,如图3-4所示:

图3-4

不过我们直接查看smali代码比较吃力,因为所对应的文件内容全是一行行的机器码,为此我们准备的jd-gui工具和dex2jar可以派上用场了,我们将classes.dex文件解压出来,放到dex2jar工具所在目录下,执行如图3-5所示的命令:

图3-5

如果没有错误生成,则在当前目录不会出现error字样的文件,然后用jd-gui工具打开生成的classes_dex2jar.jar文件,会发现原来的smali代码目录结构对应其中的package包的路径,同时每一个java文件对应着一个同名的smali文件,如图3-6所示:

图3-6

通过这种方式极大地减轻了代码阅读的难度,不过jd-gui解析出来的代码在循环和跳转上有时是不准确的,但是不影响整个代码结构的阅读,我们回编译后的apk包也可以通过这种方式来验证修改的apk包是否存在语法错误。从图3-8中我们发现还有一个R类,这个是对应工程res文件夹下的每一个资源的id值,这些资源包括字符串,图片,色彩,样式等。


如果你看的意犹未尽,如果你想随时随地充实自己,请扫描以下二维码,关注我们的公众账号,可以获取更多技术类干货,还有精彩活动与你分享~


大咖招募
欢迎App研发/测试方面的大牛来投稿,开设专栏。我们提供丰厚的稿酬,预约个人专访,帮助建立个人技术品牌!
立即投稿

我要评论

字数不能超过140字,谢谢!
提交

评论({{allComments.length}})

{{comment.create_time.substr(0,16)}}

显示所有评论
复制成功!