本文不是讲解传统源码的阅读, 而是『别人的APK源码』该怎么阅读。
此前,由于工作的原因,反编译竞品SDK,通过逆向的手段修复其源码并编译运行。
前端之下,本无秘密。相对于前端源码,Android APK源码并不是那么容易获取。由于Android这样一个开发的系统和使用java编写应用使得源码的获取成为现实。本文不过多介绍如果脱壳dex,或者动态调试apk,着重聊一下如何阅读jadx APK/DEX/JAR之后的『源码』。
什么是反编译?Executable->Human Readable
:机器可执行转变为程序员可读。后面通过APK打包过程分析打包产物
和从打包产物到可读产物
。
注:apk反编译生成的一般为Smali或java decompiled(后简称jd)代码。
原官网较为完整的打包过程:
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 应用模块的构建流程
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加壳之后不能反编译。
$ apktool b foo.jar.out
# builds foo.jar.out folder into foo.jar.out/dist/foo.jar file
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
背景故事很有趣。
网络抓包分析工具
1.思路:
2.修复java代码过程(不同工具反编译字节码得到java文件不相同)
匿名内部类闭包、自引用(this)、匿名类嵌套匿名类(超难解)、引用父类成员或方法与当前所在类同名
运行时类型丢失、泛型类型被擦除、资源和字符串常量化等
局部变量声明丢失
反编译失败型(比较少,往往是第一个入口类)
位置错落型
太多不一一列举,感兴趣的可以试着反编译看一下。
上面介绍的主要是一些jd方面的技术。jd之后的代码可以简单理解混淆后的代码,因为JVM的代码优化和逆向的语法问题使得代码不能完全运行,只要修复还是可以还原的(针对非大型项目)。代码量太多(超过5W行)只能慢慢阅读逆向代码了。阅读代码代码时需要注意this指针,同包下不需要导入的特性,可以快速定位类和方法。
矿物盐所含钙、镁、钾、锌、溴化物等,功效:柔肌肤,治疗风湿性关节炎、腰椎病、颈椎病,大骨节等,可缓解筋挛,胃痛,腹痛,坐骨神经痛!钙:平衡体内细胞矿物质的份量,缓解痉挛组织细胞的作用; 镁:由抗敏感功能,对皮肤敏感患者特别有效,促进细胞活动功能,加快组织细胞恢复; 钾:平衡水份,协助细胞再生,增强新陈代谢;锌:加速组织受损细胞伤口愈合;溴化物:有治疗、舒缓、消毒的作用,可松弛神经缓解疼痛。矿物...
在工作中遇到了这样的需求,我也是百度的,然后现在整合一下 算是笔记了(删除了没必要的引入,复制到额时候如果还有爆红 记得删除)1,依赖 <!--mqtt依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-integration</artif
网格(二) 这里我们学习的关于网格部分是以上一章内容为基础的,这里给出链接: http://blog.csdn.net/chenwu_843402773/article/details/8238314 在D3DX库中,Microsoft提供很多与网格相关的接口、结构和函数。这里我们主要学习X文件的相关操作和渐进网格。 1. XFile
https://www.cnblogs.com/keedor/p/4463988.html很多时候我们都用到ROC和AUC来评判一个二值分类器的优劣,其实AUC跟ROC息息相关,AUC就是ROC曲线下部分的面积,所以需要首先知道什么是ROC,ROC怎么得来的。然后我们要知道一般分类器会有个准确率ACC,那么既然有了ACC,为什么还要有ROC呢,ACC和ROC的区别又在哪儿,这是我喜欢的一种既生...
# Pair_2测试与优化 211606316李震 21160305胡彤一、预估与实际PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)Planning计划600900• Estimate• 估计这个任务需要多少时间600900Development开发600800• Analy...
输入一个不多于5位的正整数,要求:1 求它是几位数;2 分别输出每一位数字;3 按逆序输出各位数字。例如原数为321,应输出123。我编了这样的一个程序,但是我想应该会有更加简单的,能不能帮我做下,大家共同进步,让我学会多种方法去做同一道题,谢谢!#include#includevoid main(){long int num;int a,b,c,d,e,place;printf("please ...
Android app集成bugly之后就收到了android.os.DeadObjectException,解决方式是在manifest中设置application的硬件加速为false:android:hardwareAccelerated="false"异常原因:deadObjectException异常,说明应用的service已经停止;要么是从操作系统中丧生,要么从应用程序中
主要介绍图像频域的概念以及低通滤波以及高通滤波的相关概念
话不多花,依然是这么干练,直接创建一个相同的名称的类,代码复制过去就行了请注意cron那里,我的Scheduled注解的写法是package com.edgedo.aop;import com.edgedo.utils.HttpUtil;import com.edgedo.utils.YmlUtils;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj
目录promise简介赋值取值promise简介存在于头文件 future 中,相当于一个在并行环境中的数据存储箱,各线程可以通过这一箱子传递某种类型的数据举个例子如果我们要定义一个装int类型的箱子std::promise<int> boxOfInt赋值如果我们要往箱子里放东西,比如放一个10boxOfInt.set_value(10)箱子同时只能放一个东西,如果还想多放(多次赋值),就会报错,terminate called after throwing an i
这一段时间都在现有的项目上开发,开发的前提是要弄清楚业务逻辑。业务逻辑蕴藏在项目的各个代码片断中,所以从代码中去分析出业务逻辑,是一个程序员成长的必经之路。我很佩服我们头,他在不看代码的情况下,就靠分析程序运行时的输入和输出,就能够知道那段代码是什么意思。这是值得我们学习的。实际上程序的输入和输出就是为了业务处理,要弄清楚代码的逻辑,从分析输入和输出开始。但是话分两头说,分析代码的输入和输出也不简
数据结构是我们软件开发中最基础的部分了,它体现着我们编程的内功。大多数人在正儿八经学习数据结构的时候估计是在大学计算机课上,而在实际项目开发中,反而感觉到用得不多。其实也不是真的用得少,只不过我们在使用的时候被很多高级语言和框架组件封装好了,真正需要自己去实现的地方比较少而已。但别人封装好了不代表我们就可以不关注了,数据结构作为程序员的内功心法,是非常值得我们多花时间去研究的,我这就翻开书复习复习:本文就先从大家最经常使用的「 数组 」和「 链表 」聊起。不过在聊数组和链表之前,咱们先看一下数据的逻