发布信息

安卓应用反编译入门:从零开始探索APK结构与DEX文件解析

作者:软荐小编      2025-03-24 14:01:24     129

[i[id_32769990]_1143321454]

——题记

apk解包打包软件_文件打包解包软件_打包解压软件

一、初探

apk解包打包软件_打包解压软件_文件打包解包软件

事情是这样的。

有一个阅读软件,因为存在登录限制,所以只能试读部分页面,无法翻页到试读页面之外。它便在心中思考,是否能够对其进行反编译,看看能否绕过这个限制,接着就开始动手操作了。

在开始做这件事之前,笔者对安卓开发方面的知识是不具备的。对于 java ,也只是了解一点点。怀着试探的心态,就开始了相关的行动。

首先,要了解以下知识:

apk 本身是一个压缩包。使用解压工具将其解压后,其源码部分是由以 classes 打头的 dex 文件组成。

dex(Dalvik Executable)文件是 APK 的组成部分之一。它当中包含着应用程序的字节码。

安卓系统中,应用程序的 Java 源代码会被进行编译,生成字节码(也就是.class 文件)。接着,会使用工具把字节码转换为 dex 格式。

所以,第一步是要把 dex 反编译成 java 的 class。在这个过程中,需要用到第一个工具 dex-tools 并执行相关操作。

./d2j-dex2jar classes.dex

然后就得到了jar包文件,里面就是编译后的class。

由于 class 文件是字节码,直接读取和查看相对困难,所以接下来就需要运用第二个工具来对 class 进行反编译。因为笔者的技术水平存在限制,并且也不想花费过多的时间和精力在开发工具中重建整个项目,只是希望能够通过直接修改 class 的方式来完成这件事,因此便找到了 Luyten(类似的软件还有 JD-GUI)。

通过Luyten打开后,就看到了jar里面的代码。

文件打包解包软件_apk解包打包软件_打包解压软件

首先要定位代码的位置,这里不存在捷径。主要依靠 app 页面上的一些元素以及操作过程中的提示信息等,然后进行全局搜索,从而找到可能的文件。

这个过程较为顺利,没过多久就找到了所在的那个 class 文件。jar 包属于压缩包,只需将对应的 class 文件解压出来就行。

接下来要对这个文件进行修改。因为 class 文件属于字节码apk解包打包软件,若直接打开,它会呈现出下面这样的样子。

文件打包解包软件_打包解压软件_apk解包打包软件

在互联网时代是好的,即便处于寒冬,打工人之前留下的工具依然有很多。所以就用到了第三个工具,即 jclasslib bytecode viewer,用它来对 class 字节码进行修改。打开之后,代码呈现出这样的情况:

打包解压软件_文件打包解包软件_apk解包打包软件

这里需要强调的是,字节码是要交给机器去运行的。所以对于一般人而言,只能进行小范围的修改,比如修改参数、方法名称等。这种修改并不适合大范围进行,当然,大神除外。并且可以尝试修改后,重新将新的 class 文件替换到 jar 包中。

接下来准备再次进行打包测试,依旧使用 dex-tool,要执行的命令是:

./d2j-jar2dex classes.jar

生成了一个新的 dex 文件。随后,将原来 apk 中的 classes.dex 进行了替换。之后准备在模拟器上安装并进行尝试,然而结果却是失败的。

排查原因,由于改动较小,按理不应影响安装,所以怀疑是否是 dex-tool 打包的问题。接着把原来的 classes.dex 仅经过 dex->jar->dex 的过程,且不做任何修改,结果发现这样安装是没有问题的,这表明 dex-tool 打包不存在问题。

搜索后得知,apk 存在签名方面的问题,也就是文件发生变动后,就需要重新进行签名。另外,签名可以使用 jarsigner 或者 apksigner 这两种方式,其中 jarsigner 是 java 自带的,而 apksigner 是安卓 SDK 所具备的,并且需要下载 build-tools 来运行,所以首先采用了 jarsigner。

首先是生成密钥

keytool -genkey -alias abc.keystore -keyalg RSA -validity 20000 -keystore abc.keystore

接着对apk进行签名

jarsigner -verbose -keystore abc.keystore -signedjar reader-signed.apk reader.apk abc.keystore

签名过后会生成meta-INF文件夹,其中包括三个文件。

apk解包打包软件_文件打包解包软件_打包解压软件

再次再模拟器上安装,成了!修改的代码也生效了!️️️

我满心欢喜,准备在真机上进行安装。我还以为反编译很简单,逆向也很容易。然而,出事了,我的手机竟然安装不了。WTF!!!模拟器终究只是模拟器,在模拟器上能运行,在真机上却不一定行得通。

报错如下:

安装失败:无效的 APK,无法提取原生库,结果为-2

apk解包打包软件_文件打包解包软件_打包解压软件

二、求索

apk解包打包软件_打包解压软件_文件打包解包软件

于是进行了一番查询,发现原来是解压替换导致的问题。apk 虽是压缩包,但如果直接用解压工具进行压缩,可能会出现压缩算法不一致的情况,从而引发了这个问题,接着又进行了一番尝试。例如反复调整压缩方式等,但最终都以失败告终。看来,必须从根源上解决,也就是用专门的安卓打包工具重新进行打包。

于是又发现了apktool这个工具。

这工具也简单,主要是两个命令,解包:

java -jar apktool_2.9.0.jar d -f reader.apk -o DIR

重新打包:

java -jar apktool_2.9.0.jar b ./DIR

解包后的文件源码对应的是 smali 文件格式。Smali 文件与 DEX 文件相关,它包含了 Dalvik 虚拟机指令集的人类可读形式,是一种低级的汇编语言,用于表示和编辑安卓应用程序的字节码指令,长这个样子。

文件打包解包软件_apk解包打包软件_打包解压软件

每个字符都能认识,然而当它们连在一起时,就不太容易看懂了。接着进行了一番探索,最终找到了对应的位置,并且尝试进行修改以及重新打包。

仍然先在模拟上安装,成功!

满怀期待地在真机上安装,又失败了,而且这次是一个新的错误:

动用 BAIDU 搜索了很久,了解到最新安卓上的一些规范。这些规范大致包括两个方面:一是 apk 要对齐,即让 APK 包内未压缩的数据有序排列对齐,以此减少 APP 运行时的内存消耗;二是用 jarsigner 和 apksigner 会涉及到对齐前后顺序的问题。于是分别进行了 zipalign 对齐、jarsigner 签名以及 apksigner 签名的操作,并且将各种排列组合都尝试了一遍,然而最终都没有结果!

首先回归错误提示本身。从字面意思去理解apk解包打包软件,存在不该被压缩的资源文件却被压缩了的情况。由此猜测,在解包的时候可能会引发问题。接着查看 apktool 是否有其他参数,最终发现了其中的端倪。

apktool 在解包时存在很多参数,其中有两个参数可能与当前的问题存在关联。

不进行反编译资源的操作,要让 resources.arsc 保持原来的样子。

-s,不反编译代码,即不处理dex文件。

有些豁然开朗了,于是先把-r参数加上,运行:

java -jar apktool_2.9.0.jar d -f reader.apk -r -o DIR

重新打包、对齐、签名,安装失败,报错又变成了

INSTALL_FAILED_INVALID_APK: Failed to extract native libraries, res=-2

这表明错误已回归至最后的打包环节。接着查看打包的参数,果然有新的发现。其中有一个参数“-nc”,它的作用是禁止对资源文件进行处理。所以加上这个参数,也就是运行:

java -jar apktool_2.9.0.jar b -nc ./DIR

重新打包、对齐、签名。

模拟器上安装成功!

真机上安装成功!

测试修改的,也起作用了!

大功告成!️️️

apk解包打包软件_文件打包解包软件_打包解压软件

三、结语

apk解包打包软件_打包解压软件_文件打包解包软件

尝试了很多次,也走过一些弯路。对于安卓开发者而言,或许能很快定位并解决问题,但我作为新手,想知道仅借助网络能否解决所有问题,在这过程中,搜索引擎、技术博客、论坛以及 GPT 都发挥了很大作用。

最后简单总结一下,用到的工具和流程。

从 apk 中把 dex 解压出来,接着将其转换为 jar,从而得到 classes-dex2jar.jar 包文件。

./d2j-dex2jar classes.dex

使用 Luyten 来查看 classes-dex2jar.jar 以分析源码,并且搜索可能存在的位置。

将 classes-dex2jar.jar 中的 class 文件进行单独解压,这些 class 文件是需要修改的

使用 jclass bytecode viewer 来对相应的字节进行修改。

将 classes-dex2jar.jar 里的 class 文件进行替换。

6)使用dex-tool重新转为classes.dex

使用./d2j-dex2jar 工具以及 classes-dex2jar.jar 文件。

7)使用apktool解包

java -jar apktool_2.9.0.jar d -f reader.apk -r -s -o DIR

由于直接修改 smali 文件存在困难,所以在加上 -s 之后,能够不进行反编译源码,进而保留 classes.dex。这样一来,就可以利用步骤 6)中所得到的 classes.dex 进行替换,降低了修改 smali 的难度。如果是直接修改 smali,那么就无需添加 -s 。

8)重新打包

java -jar apktool_2.9.0.jar b -nc ./DIR

使用 Android SDK build-tools 里的那个对齐工具来对 apk 进行对齐。

检查对齐

./zipalign -c -v 4 reader.apk

执行对齐

使用 zipalign 命令,带有 -p、-f、-v 4 这些参数,对 reader.apk 进行操作,生成 reader-aligned.apk

使用 Android SDK build-tools 中的 apksigner 工具进行签名,这种方式比 jarsigner 签名更为安全,并且安装速度也更快。

生成密钥

keytool -genkeypair -alias my-alias -keyalg RSA -keysize 2048 -validity 10000 -keystore my-keystore.jks

签名

使用 apksigner 进行签名操作,签名时使用的密钥库为 my-keystore.jks,并且指定了密钥的相关信息。alias my-alias reader-aligned.apk

首先,存在一个小问题,即第三方平台中的 apk 可能被篡改。其次,笔者在这个过程中发现了此问题。再者,相同的版本号,在 apkPure 网站上下载的 apk 与在应用市场安装的 apk 不是同一个,且内部存在差异。

可以通过安装 sai 工具从手机上把 apk 文件提取出来,sai 还支持安装包含依赖项的复合 app,如 xapk、apks 等。在本例中,app 内部包含多个 apk,所以每一个都需要进行解包、打包、对齐、签名这些步骤,以确保签名一致。

参考资料:

相关内容 查看全部