一文看懂混淆代码——Java Decompiled过程和代码阅读
本文不是讲解传统源码的阅读, 而是『别人的APK源码』该怎么阅读。
项目背景
此前,由于工作的原因,反编译竞品SDK,通过逆向的手段修复其源码并编译运行。
前端之下,本无秘密。相对于前端源码,Android APK源码并不是那么容易获取。由于Android这样一个开发的系统和使用java编写应用使得源码的获取成为现实。本文不过多介绍如果脱壳dex,或者动态调试apk,着重聊一下如何阅读jadx APK/DEX/JAR之后的『源码』。
反编译概念
什么是反编译?Executable->Human Readable
:机器可执行转变为程序员可读。后面通过APK打包过程分析打包产物
和从打包产物到可读产物
。
注:apk反编译生成的一般为Smali或java decompiled(后简称jd)代码。
Android源码的打包过程
原官网较为完整的打包过程:
APK打包流程
打包资源文件,生成R.java文件
通过aapt打包res资源文件,生成R.java、resources.arsc和res文件(二进制 & 非二进制如res/raw和pic保持原样)处理aidl文件,生成相应的Java文件
编译项目源代码,生成class文件
通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件,生成的class文件位于工程中的bin/classes目录下。转换所有的class文件,生成classes.dex文件
dx工具生成可供Android系统Dalvik虚拟机执行的classes.dex文件,该工具位于android-sdk/platform-tools 目录下。
任何第三方的libraries和.class文件都会被转换成.dex文件。
dx工具的主要工作是将Java字节码转成成Dalvik字节码、压缩常量池、消除冗余信息等。打包生成APK文件
通过apkbuilder工具,将aapt生成的resources.arsc和res文件、assets文件和classes.dex一起打包生成apk对APK文件进行签名
一旦APK文件生成,它必须被签名才能被安装在设备上。
通过Jarsigner工具,对上面的apk进行debug或release签名
在开发过程中,主要用到的就是两种签名的keystore。一种是用于调试的debug.keystore,它主要用于调试,在Eclipse或者Android
Studio中直接run以后跑在手机上的就是使用的debug.keystore。另一种就是用于发布正式版本的keystore。对签名后的APK文件进行对齐处理
通过zipalign工具,将签名后的apk进行对齐处理。
对齐的主要过程是将APK包中所有的资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问apk文件时的速度会更快。对齐的作用就是减少运行时内存的使用。
考虑到Gradle作为主要构建工具,官方后来缩减版(可以看谷歌的变化之快):
典型 Android 应用模块的构建流程
构建过程中的产物
- resources.arsc 二进制
- .class
debug/release javac -g字节码是否可调试 - .jar
- .dex 相比jar结构更紧凑
- AAR 可执行文件dex和资源文件的集合记录文件
反编译的过程和工具
APK文件结构(通过解压缩查看)
Apks are nothing more than a zip file containing resources and assembled java code
$ unzip testapp.apk
Archive: testapp.apk
inflating: AndroidManifest.xml
inflating: classes.dex
extracting: res/drawable-hdpi/ic_launcher.png
inflating: res/xml/literals.xml
inflating: res/xml/references.xml
extracting: resources.arsc
无法查看目录中资源文件
查看 AndroidManifest.xml、resource.arsc编译后的二进制文件,后面讲解怎么查看APK、dex和反编译后端资源文件。
AAR文件结构
注意:lib中jar文件依然存在,在APK打包时候会合入.dex中。
以下,介绍一些java decompiled
的工具。
Apktool
apktool工具官网的介绍 :
editing or viewing a compiled file is next to impossible. That is where Apktool >comes into play.
由于apktool实在太常用,甚至有许多人以为是官网给出的打包工具。
$ apktool d testapp.apk//apk 、jar I: Using Apktool 2.0.0 on testapp.apk I: Loading resource table... I: Decoding AndroidManifest.xml with resources... I: Loading resource table from file: 1.apk I: Regular manifest package... I: Decoding file-resources... I: Decoding values */* XMLs... I: Baksmaling classes.dex... I: Copying assets and libs... $
很多APK通过apktool的bug加壳之后不能反编译。
- 通过分析和修改smali文件,再通过apktool重新打包、签名之后生成apk从而达到修改的目的。
$ apktool b foo.jar.out # builds foo.jar.out folder into foo.jar.out/dist/foo.jar file
- Framework Files 厂商定制
- Smali Debugging 调试
SmaliDebugging has been marked as deprecated in 2.0.3, and removed in 2.1. Please check SmaliIdea for a debugger.
dex2jar
功能:将 dex 文件还原成为 jar 文件;d2j-dex2jar.sh dex文件名
,
将 dex 文件还原成为 smali 文件;d2j-dex2smali.bat dex文件名
功能:查看 dex 文件还原成为 jar 文件代码;将 jar 文件中所有的 class 文件转换成为 java 文件
2015 年开始就停止了维护
jadx
功能:可直接浏览 Apk、dex、jar
带全局搜索功能,很好用,通过保存全部可以获得所以反编译的java代码。
enjarify
Google 出品
环境:Python3
可直接将 apk 文件还原成为 jar 文件,也可以和 dex2jar 一样,直接操作某个dex
ClassyShark
Google 出品
功能:可直接浏览 Apk,支持对.dex, .aar, .so,.apk, .jar, .class等文件的操作,查看统计、依赖等
优点:轻量
感兴趣请阅读以下参考
http://www.jianshu.com/p/8e8b88ea2197
https://github.com/borisf/classyshark-user-guide
背景故事很有趣。
网络抓包分析工具
7反编译思路和总结
1.思路:
- 反编译获取魔蝎Android全部代码->调试和重构增强可读性->断点调试JS分析前端控制逻辑->获取全部抓取策略和细节
- 代码可调试 尝试调试JAR包
- 通过抓取分析具体流程 控制逻辑很复杂,前端为核心
2.修复java代码过程(不同工具反编译字节码得到java文件不相同)
-
匿名内部类闭包、自引用(this)、匿名类嵌套匿名类(超难解)、引用父类成员或方法与当前所在类同名
image.png -
运行时类型丢失、泛型类型被擦除、资源和字符串常量化等
image.png -
局部变量声明丢失
image.png -
反编译失败型(比较少,往往是第一个入口类)
image.png -
位置错落型
image.png
太多不一一列举,感兴趣的可以试着反编译看一下。
上面介绍的主要是一些jd方面的技术。jd之后的代码可以简单理解混淆后的代码,因为JVM的代码优化和逆向的语法问题使得代码不能完全运行,只要修复还是可以还原的(针对非大型项目)。代码量太多(超过5W行)只能慢慢阅读逆向代码了。阅读代码代码时需要注意this指针,同包下不需要导入的特性,可以快速定位类和方法。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
倒计时按钮—获取手机验证码按钮
HTML: <input type="button" value="获取验证码"> CSS: 1 input[type=button] { 2 width: 150px; 3 height: 30px; 4 background-color: #ff3000; 5 border: 0; 6 border-radius: 15px; 7 color: #fff; 8 } 9 10 input[type=button].on { 11 background-color: #eee; 12 color: #ccc; 13 cursor: not-allowed; 14 } JavaScript: 1 $("input[type='button']").click(btnCheck); 2 3 /** 4 * [btnCheck 按钮倒计时常用于获取手机短信验证码] 5 */ 6 function btnCheck() { 7 8 $(this).addClass("on"); 9 10 var time = 5; 11 12 $(this).attr("disabled", tr...
- 下一篇
java源码-ArrayDeque
开篇 Deque 接口继承自 Queue接口,但 Deque 支持同时从两端添加或移除元素,因此又被成为双端队列。鉴于此,Deque 接口的实现可以被当作 FIFO队列使用,也可以当作LIFO队列(栈)来使用。官方也是推荐使用 Deque 的实现来替代 Stack。 ArrayDeque 是 Deque 接口的一种具体实现,是依赖于可变数组来实现的。ArrayDeque 没有容量限制,可根据需求自动进行扩容。ArrayDeque不支持值为 null 的元素。 ArrayDeque类图 ArrayDeque类图 ArrayDeque的类变量和构造函数 ArrayDeque的类变量当中数组elements用来保存队列元素,head指针指向第一个存储元素,tail指向最后一个元素的下一个位置。 ArrayDeque的calculateSize的逻辑非常巧妙,用于计算大于numElements的最小的2*n次方的值。 public class ArrayDeque<E> extends AbstractCollection<E> implements Deque...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS关闭SELinux安全模块
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- 2048小游戏-低调大师作品
- SpringBoot2更换Tomcat为Jetty,小型站点的福音