如何利用Android反编译定位问题

October 02, 2020

安卓代码反编译并不仅仅只用来做攻击或“参考”别人的代码内容,我们还可以用反编译来帮助我们分析和定位遇到的编译问题。

安卓apk编译的配置很多。如果项目庞大,构建的依赖也会错综复杂,这时候,遇到了奇怪的编译问题,有时候反编译一下构建出来的apk,反而可以更快定位出问题所在。

如何反编译

这里推荐一个叫做jadx的反编译工具,可以在github的release页面直接下载。

运行只需要点击bin目录下对应的文件执行就可以了。Mac点击jadx-gui可以启动gui界面。

image-20201011165212525

image-20201011165258863

然后根据指引,找到apk,即可执行反编译。

gui操作的一些特性可以在这篇文章里看到。

可以定位什么问题?

开发安卓的同学,应该经常会遇到一些构建的困惑:为什么明明构建成功了,但是却提示我classNotFound;为什么本地debug构建是可以的,但是构建release版本就不行了;明明配置了progurd,但是怎么好像没有生效一样,等等这些跟构建相关的问题。经常处理方式就是clean一下project,有一定概率可以解决这些问题。

拿我最近遇到的一个问题举例:

整个项目构建运行是正常的,我在给其中一个子module写测试用例,用android studio运行单个测试用例也是正常的,但是跑整个module的测试用例检查覆盖率的时候总是提示我有个类找不到。

image-20201011170402762

刚开始,我一直怀疑是构建有问题,clean了多次都不行,各种清除缓存试了个遍,因为我一直觉得整体运行都没有问题,单个运行肯定可以才对呀。

最后,甚至直接运行git clean -xdf来清理目录下非git索引的所有其他文件。相当于在新目录clone了一遍,再运行,发现还是报错。

于是,我开始想是不是真的构建配置有问题了。

仔细分析看了一下这个缺少的类是一个跟视频相关的类,按理说我写的webview单元测试应该不依赖这些代码。但是一直构建不过,就尝试依赖一下视频相关的module。发现确实可以构建通过了。看来确实是缺少了这个类的依赖,并不是AS的bug。整个项目有很多module,而且依赖关系也比较复杂,根据gradle的配置来推断哪里依赖导致的比较难搞。于是就开始尝试使用反编译来看下到底是哪个里依赖了这个类。

反编译构建出来的apk之后,cmd+shift+f直接搜索缺失的类。可以找到有一些地方确实有使用,比如类XXFilterBase。然后再在AS里面双击shift看这个类属于哪个包。再根据gradle命令./gradlew :app:dependencies分析webview和这个包的依赖关系。一下就很清楚了。整个依赖路径是:project(':webview')->project(':moduleA')->'com.xxx.videoModuleB',最后的videoModuleB里使用了类VideoFilterBase。'videoModuleB'是通过maven库依赖的。这个问题是因为videoModuleB没有在库里声明依赖关系,导致单独构建的时候会存在缺少某个类的情况。。

可以看出来,整个过程中,构建本来是一个黑盒操作,但是能够反编译之后,直接看到构建结果,可以直接推断问题出现在哪里。而不是不停地重复尝试构建,能够极大提高定位问题的速度。

本文首发于 一粟(https://www.zeyio.com),欢迎转载,但是必须保留本文的署名和链接。

本文永久链接:https://www.zeyio.com/202010/android-decompile-for-debug/