安卓应用(APK)逆向工程

原文参考链接:https://crifan.github.io/android_app_security_crack/website/

上述网址讲解的非常详细,这里只粗略的整理用到的比较多的工具以及一些安卓逆向工程的知识点。

全文中提到的各种工具都可以csdn下载https://download.csdn.net/download/wozaipermanent/11958306在中下载得到,但是现在csdn下载不能自己设置积分了,积分会动态改变,所以下文对于每一种工具都提供了一个下载网址,或者自行搜索下载。

1 APK文件

  • APK = android Application PacKage
  • APK文件:是安卓app的安装文件,其实就是一个zip或rar压缩包,把apk后缀改为zip,即可解压得到一堆安卓相关文件

1.1 APK内容结构

内容入口 含义解释
AndroidManifest.xml 二进制xml文件,提供设备运行应用程序所需的各种信息
classes.dex 以dex格式编译的应用程序代码
resources.arsc 包含预编译应用程序资源的二进制XML文件
res/ 此文件夹中包含未编译到resources.arsc文件中的资源
assets/ 此文件夹包含应用程序的原始资源,由AssetManager提供对这些资产文件的访问
META-INF/ 它包含MANIFEST.MF文件,该文件存储有关JAR内容的元数据。APK签名也存储在此文件夹中
lib/ 此文件夹包含已编译的代码,例如本地代码库

1.2 dex文件

  • dex = Dalvik Executable format

  • dex文件:逻辑类似于javaclass文件。

注:

  1. java的class文件内部是java的字节码(Java ByteCode)
  2. 安卓系统中,用**Dalvik虚拟机(DVM = Dalvik Virtual Machine)**去把java源代码编译为dex可执行文件(Dalvik Executable)

2 安卓加密技术

2.1 代码混淆

最常用的做法是,用ProGuard去实现代码混淆。

2.1.1 ProGuard的作用

  • 压缩 = Shrinking:移除未被使用的类、属性、方法等,并且会在优化动作执行之后再次执行(因为优化后可能会暴露一些未被使用的类和成员)
  • 优化 = Optimization: 优化字节码,并删除未使用的结构
  • 混淆 = Obfuscation: 将类名、属性名、方法名混淆为难以读懂的字母,比如a,b,c等,增大反编译难度

2.1.2 ProGuard的输出文件说明

  • dump.txt:说明APK中所有类文件的内部结构
  • mapping.txt:提供原始与混淆过的类、方法和字段名称之间的转换和对应关系
  • seeds.txt:列出未进行混淆的类和成员
  • usage.txt:列出从APK移除的代码

2.2 加固

市面上有很多公司和厂商提供免费或收费的加固方案。

3 安卓破解技术

3.1 反混淆

使用反编译工具只能看到混淆之后的代码结构,看不到混淆之前的原始代码。

  • 如果有mapping.txt文件:有机会反混淆,恢复和还原出原始代码。但一般只有安卓项目的开发者,在使用ProGuard时才会生成mapping.txt文件,实际上作为要破解的人,往往没有。
  • 如果有源文件和行号文件:有机会反混淆,恢复和还原出原始代码。许多APK开发者为了在崩溃时保存源文件类名、行号等信息会在APK混淆时添加规则(keepattributes SourceFile,LineNumberTable)保留源文件信息,实际上作为要破解的人,往往没有。

3.1.1 反混淆工具

  • JEB = JEB Decompiler:官网
  • Simplify(CalebFenton/simplify: Generic Android Deobfuscator):主页
  • jadx:主页

3.2 去壳脱壳

不是所有加固的安卓apk都可以成功脱壳的。

总结:

  • 没有加固的:直接用jadx即可导出源码

  • 部分加密不强的:可以脱壳

    • 老一代或免费的360加固保、爱加密、娜迦加固等
    • 用FDex2可以脱壳:可以hook导出dex,再dex转jar,jar转java源码
  • 腾讯乐固,新一代的360加固保等:没法脱壳(或许未来可以使用art+dex2oat相关机制去破解)

3.2.1 如何判断是哪家加固方案

通过反编译工具后,从dex或jar包的目录结构,以及相关的文件(比如AndroidManifest.xml)的内容,往往可以看出是哪家的加密方案。

腾讯乐固加密后的目录

腾讯乐固legu加密加壳后的apk,用apktool反编译后,得到的jar包目录结构是:

  • com.tencent.bugly

  • com.tencent.bugly.legu

    • crashreport
    • proguard
  • com.tencent.StubShell

    • TxAppEntry

截图举例:

安卓应用(APK)逆向工程_第1张图片

安卓应用(APK)逆向工程_第2张图片

另外反编译出的AndroidManifest.xml内容:

<application android:allowBackup="true" android:icon="@drawable/app_logo" android:label="@string/app_name" android:name="com.tencent.StubShell.TxAppEntry" android:supportsRtl="true" android:theme="@style/AppTheme">
<meta-data android:name="TxAppEntry" android:value="com.huili.readingclub.MyApplication"/>

中有:

  • android:name="com.tencent.StubShell.TxAppEntry"

也是典型的腾讯乐固的内容。

360加固保加固的目录结构

360加固后的apk经过dex2jar反编译后的目录结构是:
安卓应用(APK)逆向工程_第3张图片
安卓应用(APK)逆向工程_第4张图片

  • com.qihoo.util
  • com.qihoo360.replugin
  • com.stub

这种结构就说明是360加固保加固的。

3.3 从apk破解出java源码

  • 没有加固的:用jadx从apk导出java源码
  • 加固了的:apk -> dex -> jar -> java,前提是后续的hook能够导出dex文件

3.3.1 AndroidManifest.xml

安卓中有个AndroidManifest.xml文件,是保存了相关项目的类,资源等配置信息。

而对于apk文件:

  • 直接改名为zip或rar后再解压:得到二进制的AndroidManifest.xml文件
  • 用apktool等工具去反编译:得到文本格式的AndroidManifest.xml

apktool下载:apktool下载官网

命令apktool d -f inputFile.apk -o outputFile

注:即使apk加固了,也可以用apktool反编译

比如,网上随便找了一个机器人塔防的apk(robotDefense.apk),用apktool对其进行反编译,得到AndroidManifest.xml文件信息如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.magicwach.rdefense">
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <application android:configChanges="keyboardHidden|orientation" android:icon="@drawable/icon" android:label="@string/app_name" android:launchMode="singleTask" android:multiprocess="false" android:sharedUserId="com.magicwach.rdefense_free" android:stateNotNeeded="true" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
        <activity android:label="@string/app_name" android:name=".TitleActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            intent-filter>
        activity>
        <activity android:label="@string/app_name" android:name=".GameActivity"/>
        <activity android:name=".RewardActivity"/>
        <activity android:name=".AchievementActivity"/>
        <activity android:name=".CreditsActivity"/>
        <activity android:name=".LevelSelectActivity"/>
        <activity android:name=".MixerSelectActivity"/>
        <activity android:name=".DebugActivity"/>
        <activity android:name=".OptionsActivity"/>
        <receiver android:name="com.xxx.yyy.MyBoolService">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            intent-filter>
        receiver>
        <receiver android:name="com.xxx.yyy.MyAlarmReceiver">
            <intent-filter>
                <action android:name="com.lz.myservicestart"/>
            intent-filter>
        receiver>
        <service android:enabled="true" android:name="com.xxx.yyy.MyService"/>
        <receiver android:name="com.xxx.yyy.NetWorkReceiver">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            intent-filter>
        receiver>
        <receiver android:name="com.xxx.yyy.CustomBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE"/>
            intent-filter>
        receiver>
    application>
    <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
manifest>

从xml文件中可以得到permission feature、component feature等特征信息。

3.3.2 一步:apk->java

前提: apk没有被加固。用jadx等工具打开看到的进而导出的代码和目录结构都是qihoo奇虎、360、tencent腾讯乐固legu等字样的就说明是被加固了的,这样导出的代码也只是加固后的代码,不是app自已业务逻辑的java代码。

思路: 用jadx等工具,直接从apk转换出java源代码

准备: 下载jadx,从首页下载最新版本,如jadx-1.0.0.zip,解压;或使用如下安装命令:

git clone https://github.com/skylot/jadx.git
cd jadx
./gradlew dist

详细步骤:

用jadx-gui打开没有加固的apk文件:

安卓应用(APK)逆向工程_第5张图片

可以看到源码,想要导出全部源码,则可以去文件->全部保存文件->另存为Gradle项目即可导出全部代码。

3.3.3 三步:app->dex->jar->java

前提: apk虽然被加固,但(后续)用FDex2等工具能够导出我们要的dex文件

  • 这种加固方式往往是旧版本的360加固等
  • 如果导不出dex文件则无法继续导出jar再导出java代码,说明加固方案往往是新版本的360加固保、腾讯乐固等。

思路:

  1. 从运行中的安卓app导出dex文件
  • 事先安装安卓的apk到已root的安卓真机或安卓模拟器
  • 在安卓中已经安装了Xposed等Hook框架中
  • 再去Xposed中安装FDex2/DumpDex等插件,用于后续导出dex文件
  • 运行安卓app,自动导出我们要的dex文件
  • 从安卓(真机/模拟器)中拷贝出刚才导出的(往往是多个)dex文件
  1. 用dex2jar等工具从dex文件中导出jar文件
  2. 用反编译器(jadx/CFR/Procyon/JD-GUI)把jar转换出java源代码

详细步骤:

1. app导出dex

准备:

  • 已root了的安卓4.4+的真机或模拟器,此处用的是夜神模拟器 = Nox App Player

安卓应用(APK)逆向工程_第6张图片

Android 5.1.1,夜神模拟器已自带root

  • Hook框架:用于后续安装插件去导出dex文件,此处选用Xposed框架

安卓应用(APK)逆向工程_第7张图片

  • 下载好FDex2的apk,下载地址:百度网盘 提取码:3e3t。

安卓应用(APK)逆向工程_第8张图片

详细步骤:

  • 安装要破解的apk

安卓应用(APK)逆向工程_第9张图片

  • 安装和激活FDex2,去Xposed里面勾选激活FDex2

安卓应用(APK)逆向工程_第10张图片

激活FDex2,Xposed模块列表会更新,重启之后生效。

  • FDex2中设置要处理的app,会提示设置成功

安卓应用(APK)逆向工程_第11张图片

  • 运行要破解的app

安卓应用(APK)逆向工程_第12张图片

此处内部FDex2已经去导出app的所有文件对应的目录

  • 拷贝出以导出的dex文件,根据之前设置时提示的输出路径去找dex文件(和其他相关项目文件),并拷贝出来即可。

没有看到我们要导出的dex文件:

  1. 有时候没有看到导出文件,则可以重新多试几次即可。
  2. 有些app,打破沉寂的文件中,没有我们希望的(多个dex文件中的某个)包含了app业务逻辑的dex文件。说明该app采用了更加高级的加固,无法导出我们要的dex文件。

2. dex转换出jar

思路:已经从前面的app导出dex文件,然后用dex2jar等工具从dex转换出jar文件。

准备: 从下载网址:官网:https://tools.kali.org/reverse-engineering/dex2jar,下载最新版本的dex2jar并解压

用法:

  • 从dex中转换出jar:

    • Windows:d2j-dex2jar.bat -f classes.dex;Linux:d2j-dex2jar.sh -f classes.dex
  • 从apk中转换出jar:

    • Windows:d2j-dex2jar.bat -f test.apk;Linux:d2j-dex2jar.sh -f test.apk

说明和提示:

  • apk改名zip解压得到的classes.dex去转换一般无法得到有效的jar,虽然有时候转换过程没有报错,但是其中可能没有包括业务逻辑的代码,不是我们需要的jar
  • 多个dex转换jar期间会报错,如果报错,会吧错误信息导出到名为xxx-error.zip的压缩包中

3. jar转换出java

选择合适的反编译器,如jadx或JD-GUI等,打开上一步从dex转换得到的jar文件。

jadx网址: https://github.com/skylot/jadx

详见 4.3 反编译器内容

4 常见安卓破解工具

4.1 从app导出dex

下面整理关于从运行中的安卓app导出dex文件的一些hook工具。

4.1.1 导出dex文件的文件名

利用FDex2等工具,从运行的app导出dex文件时,看到很多文件名都类似于:com.huili.readingclub8825612.dex

这些hook工具生成的dex代码中,对应的命名规则应该是:

packageName + fileSize.dex

所以上面的文件名对应:

  • packageNamecom.huili.readingclub
  • fileSize8825612,即dex文件本身的大小

4.1.2 FDex2

用来从运行中的安卓app中导出dex文件的工具。下载地址:百度网盘 提取码:3e3t。

4.1.3 DumpDex

用来从运行中的安卓app中导出dex文件的工具。下载地址:https://github.com/WrBug/dumpDex/releases

4.1.4 drizzleDumper

  • 功能:一款基于内存搜索的Android脱壳工具,可以从运行中的安卓app中,利用ptrace机制,导出dex文件
  • github主页: https://github.com/DrizzleRisk/drizzleDumper
  • 机制和原理:root设备之后,通过ptrace附加需要脱壳的apk进程,然后在脱壳的apk进程的内存中进行dex文件的特征搜索,当搜索到dex文件时,进行dex文件的内存dump
  • 使用步骤:
    • 将\armeabi下的drizzleDumper push进手机
    • 进入shell,赋给可执行权限
    • 运行drizzleDumper[包名][等待时间,默认为0]
    • 运行需要脱壳的程序
$ adb push F:\drizzleDumper /data/local/tmp
$ chmod 755 drizzleDumper
$ ./drizzleDumper xyz.sysorem.crakme

4.2 dex转jar

4.2.1 dex2jar

下载网址:官网:https://tools.kali.org/reverse-engineering/dex2jar、github: https://github.com/pxb1988/dex2jar

功能: 用于处理安卓的dex文件和java的class文件的一系列的工具

  • 核心和常用功能:从dex文件导出jar
  • 一系列的功能:
    • dex-reader/writer:读写dex(Dalvik Executable)文件,具有和ASM类似的轻量级API接口
    • d2j-dex2jar:把dex文件转换为class文件
    • smali/baksmali:反汇编dex转换出smali文件,从smali文件中汇编出dex文件

用法:

  • 从dex中转换出jar:

    • Windows:d2j-dex2jar.bat -f classes.dex;Linux:d2j-dex2jar.sh -f classes.dex
  • 从apk中转换出jar:

    • Windows:d2j-dex2jar.bat -f test.apk;Linux:d2j-dex2jar.sh -f test.apk

4.2.2 Enjarify

网址: https://github.com/Storyyeller/enjarify

功能:把安卓的Dalvik字节码转化为Java字节码,和dex2jar类似

特点:google官方开源、用python3编写、比dex2jar更新且更好

用法

  • python -o -m enjarify.main yourapp.apk

  • enjarify yourapp.apk
    enjarify classes2.dex
    enjarify yourapp.apk -o yourapp.jar
    

与dex2jar比较

  • dex2jar:

    • 比较旧
    • 大部分情况转换没问题
    • 但是有时候(模糊特征时、边缘情况时)转换会报错,甚至不报错但生成的是错误的结果
  • Enjarify

    • 最新设计的工具
    • 支持绝大多数情况(包括有些dex2jar会出错的情况),且额外支持:
      • Unicode的类名
      • 用作多种类型的常量
      • 隐式转换
      • 正常执行流程中的异常处理
      • 引用了非常多的常量的类
      • 名字非常长的方法
      • 捕获函数后的异常处理
      • 错误类型的静态初始变量

4.2.3 Dedexer

下载地址: https://sourceforge.net/projects/dedexer/files/

作用: 把dex转换为类似于汇编的格式,从dex文件创建类似于Jasmin的源代码

用法:

  • java -jar ddx.jar -o -D -d <destination directory> <source>
    java -jar ddx1.5.jar -o -D -d c:\dex\gen c:\dex\classes.dex
    

4.3 反编译器

此处主要讨论java反编译器,更主要的是和安卓相关的java的反编译器,其中尤其涉及到dex转出jar包后的,如何从jar包反编译出java源代码的相关反编译器。

作用: 从jar包转换出java源代码,用于在GUI图形界面工具中查看java代码;命令行工具中直接导出整个项目所有的java代码文件

常用反编译器:

  • JD-GUI(网上目前提到最多的): https://github.com/java-decompiler/jd-gui/releases
    • 有些文件会转换出错
    • 代码逻辑不够清晰
  • jadx(个人觉得比较好用的)
    • 代码转换不仅不会出错,关键是代码逻辑更加清晰和易懂
    • 可以直接用jadx打开未加固的apk,打开(用FDex2从加固了的apk导出的)dex文件并查看和导出java源代码
  • Procyon: https://bitbucket.org/mstrobel/procyon/downloads/
    • 基于Procyon的GUI工具:Luyten
    • 代码转换不出错
    • 查看代码:用基于Procyon的Luyten去查看代码;导出代码:用procyon从jar反编译转换出java源代码

4.4 其他破解类工具

4.4.1 apktool

  • apktool:一个用来逆向工程第三方的二进制的安卓app工具。

    • 输入:apk文件

    • 输出:各种安卓资源文件

    • 安装: https://ibotpeaches.github.io/Apktool/install/

    • 用法:apktool d -f inputFile.apk -o outputFile

  • 利用上述命令可以得到项目目录文件:

    • 最基本的:AndroidManifest.xml
    • 得不到dex文件
    • 可得到:和app业务逻辑相关代码的smali文件,想要得到最终的java源码的话,需要再去找smali转java的工具才可以
  • 用apktool转换apk得到smali源码是有前提的:apk没有加固。加固了的apk反编译后只能看到被加固的目录结构,看不到app业务逻辑代码和结构,如下图:
    安卓应用(APK)逆向工程_第13张图片

4.4.2 IDA

  • 下载: https://www.hex-rays.com/products/ida/support/download.shtml ,注:IDA Pro是商业收费软件,请支持和购买正版
  • 功能: 逆向工程利器,支持Android的静态分析与动态调试,动态调试so文件

4.4.3 安卓XML破解

AXMLPrinter2

下载: https://code.google.com/archive/p/android4me/downloads

作用: 将安卓二进制的AXML转换成可读的xml文件

提示: 最佳更新都是2008年,看起来是很老旧的工具

用法:

java -jar AXMLPrinter2.jar xxx.xml output.xml
java -jar AXMLPrinter2.jar AndroidManifest.xml > main.xml

4.5 其他辅助类工具

4.5.1 安卓调试器

AndBug

  • 主页: https://github.com/swdunlop/AndBug
  • 作用:在没有源代码的情况下,调试Android上的java程序
  • 功能:支持断点、call stack查看、查看class、method等信息

Android-OpenDebug

  • 主页: https://github.com/iSECPartners/Android-OpenDebug
  • 功能:是一个Cydia Substrace插件,所以前提是要安装Cydia Substrace;可以使得任何一个安卓程序可以被调试

4.5.2 二进制编辑器

这部分详见文档开头第一个参考链接,下面只罗列一些工具名称

  • 010ditor
  • EverEdit

4.5.3 其他工具略叙

下面介绍的工具详见文档开头第一个参考链接,下面只罗列这些工具的名称

  • ClassyShark
  • APK Analyzer
  • Fino
  • Introspy-Android
  • redexer
  • SmaliViewer

4.6 其他综合类工具

这部分详见文档开头第一个参考链接

  • ByteCode Viewer
  • Android Decompiler
  • decompile-apk
  • Android-Crack-Tool For Mac
  • Android逆向助手
  • AndroidKiller
  • Androguard
  • AFE

4.7 其他相关工具

4.7.1 安卓Hook框架

Xposed框架

Xposed框架是用于安装相关插件FDex2,配合破解安卓,导出运行时app的dex文件。

Cydia Substrace

主页: http://www.cydiasubstrate.com

功能: 和Xposed类似的框架,用来安装各种插件,实现各种功能,比如可以安装绕过ssl检测的插件,用来破解ssl pinning

特点: hook底层方法非常方便,对so中的方法hook操作非常便捷

frida

官网:https://www.frida.re

简介:

  • 一款基于python+JavaScript的hook框架
  • 可运行在Android/IOS/Linux/Win/OSX等各平台
  • 主要使用动态二进制插桩(DBI)技术
    • 将外部代码注入到现有的正在运行的二进制文件中,从而让它执行额外操作
      • 访问进程内存
      • 在应用程序运行时覆盖函数
      • 从导入的类调用函数
      • 在堆上查找对象实例并使用
      • Hook、跟踪和拦截函数等

5 安卓模拟器

5.1 夜神安卓模拟器

使用夜神安卓模拟器,来配合破解安卓:

  • 可以在夜神模拟器的Xposed中安装FDex2,用来从运行期间的安卓app导出dex文件
  • 同时夜神自带的文件管理器可以方便的导出dex文件到PC端

5.2 文件浏览器

想要把安卓中(导出的dex等)文件拷贝(导)出来,一般需要借助于好用的安卓浏览器。

5.2.1 夜神模拟器中自带文件浏览器

ES文件浏览器: 功能很强,比较流行的安卓的文件浏览器。

5.2.2 MT管理器

  • MT = MT Manager = MT Manager for Android:安卓中的一个文件管理器,常被简称为MT2

特点:

  • ⽀持在VirtualXposed中使⽤MT
  • 除了普通⽂件管理功能外,还⽀持APK反编译相关功能

应用简介

MT管理器是⼀款强⼤的⽂件管理⼯具和APK逆向修改神器。

  • 如果你喜欢它的双窗⼝操作⻛格,可以单纯地把它当成⽂件管理器使⽤。
  • 如果你对修改APK有深厚的兴趣,那么你可以⽤它做许许多多的事。比如:汉化应⽤、替换资源、修改布局、修改逻辑代码、资源混淆、去除签名校验等,主要取决于你如何使⽤。

主要功能:

  • ⽂件复制、移动、创建软链接、重命名、删除、创建⽂件(夹),⽂件批量操作。获取 Root 权限后可访问系统⽬录,挂载⽂件系统为读写,修改⽂件权限和所有者。
  • 像 WinRAR 那样打开 ZIP 格式⽂件,可以对 ZIP 内的⽂件进⾏删除、重命名、移动,添加/替换外部⽂件到 ZIP中,⽆需解压后再重新打包,同时⽀持单独解压 ZIP 内的部分⽂件。
  • ⾃带强⼤的⽂本编辑器,可以流畅编辑⼤⽂本⽂件,⽀持设置是否显示⾏号、开关⾃动换⾏、双指缩放字体大小、⾃动识别编码、代码语法⾼亮、⾃动缩进、正则搜索替换。
  • 拥有图⽚查看、⾳乐播放、字体预览、执⾏脚本、⽂本对⽐等功能,在侧拉栏中可⽅便地查看存储设备、FTP连接、书签、后台、⼯具等。
  • APK 编辑功能,主要有 DEX 编辑,ARSC 编辑,XML 编辑,APK 签名、APK 优化、APK 共存、去除签名校验、RES 资源混淆、RES 反资源混淆、翻译模式等。

你可能感兴趣的:(APK逆向)