Apk 反编译前期了解

Enmmm,预计阅读时间:8 分钟

LZ-Says:学习之路,似乎枯燥乏味,唯有耐着性子,独自前行,当光明笼罩的那一刻,一切,也仿佛明亮了许多。

前言

前段日子,工作之中涉及到了 Apk 的逆向,到现在也是一知半解,今天重新回顾一番,希望在此基础上再次得到理解。

一、前期内容了解

反编译 Apk,并不是直接拿过来 Apk,改名,解压缩或者使用某些工具直接反编译。

徒有其表,并不是自己的东西。So,在反编译之前,我们需要掌握什么技能点呢?

1. Dalvik 虚拟机

Dalvik 是 Google 公司自己设计用于 Android 平台的虚拟机。

它支持转换为 .dex (即 Dalvik Executable)格式的 Java 程序的运行,而 .dex 格式则是专门为 Dalvik 设计的一种压缩格式,适用于适合内存以及处理器速度有限的操作系统。

而目前的 Dalvik 经过一系列的优化,已经支持在有限的内存中同时运行多个虚拟机的实例。

下面来张图,简单查看下:

在 Java 程序中,Java 类会被编译成一个或多个 .class 文件,然后打包到 jar 文件中,接着 Java 虚拟机会从对应的 class 文件以及 jar 文件中获取对应的字节码文件。

Android 应用目前大多数还是使用 Java 语言进行开发,虽然都是需要编译成 class 文件,但是 Android 还是会通过 Dex 工具将所有的 class 文件转化成一个 Dex 文件,而 Dalvik 虚拟机则从此文件中读取对应的指令以及所需要的数据。

dex 文件除了减少了整体文件大小以及 I/O 操作次数,相对应的也提高了类的查找速度。

Dalvik 虚拟机使用的指令是基于寄存器,而 Java 虚拟机则使用的指令集是基于堆栈的。(Dalvik 基于寄存器,而 JVM 基于栈。)

所以说,每一个 Android 应用在底层都会对应一个独立的 Dalvik 虚拟机实例,并使其代码在虚拟机的解释器下得以执行。

而这里,简述下 Dalvik 和 Java 运行环境的区别:

  • Dalvik 主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能;
  • Dalvik 负责进程隔离和线程管理,每一个 Android 应用在底层都会对应一个独立的 Dalvik 虚拟机实例,其代码在虚拟机的解释下得以执行;
  • 不同于 Java 虚拟机运行 java 字节码,Dalvik 虚拟机运行的是其专有的文件格式 Dex;
  • 文件格式可以减少整体文件尺寸,提高 I/O 操作的类查找速度;
  • odex 是为了在运行过程中进一步提高性能,对 Dex 文件的进一步优化;
  • 所有的 Android 应用的线程都对应一个 Linux 线程,虚拟机因而可以更多的依赖操作系统的线程调度和管理机制
  • 有一个特殊的虚拟机进程 Zygote,他是虚拟机实例的孵化器。它在系统启动的时候就会产生,它会完成虚拟机的初始化,库的加载,预制类库和初始化的操作。如果系统需要一个新的虚拟机实例,它会迅速复制自身,以最快的数据提供给系统。对于一些只读的系统库,所有虚拟机实例都和 Zygote 共享一块内存区域;
  • Dalvik 是由 Dan Bornstein 编写的,名字来源于他的祖先曾经居住过名叫 Dalvík 的小渔村,村子位于冰岛 Eyjafjörður。

而在 Dalvik 字节码中,包含俩种类型,分别为:

  • 基本类型
  • 引用类型

我们常说的对象和数组便是引用类型,下面附上关于 Dalvik 字节码的基本类型图:

了解这个的目的,便是方便我们今后阅读 Smail 文件。

而 Dalvik 字节码引用类型又包含如下:

  • 对象类型: 例如,L 代表 Java 类型中任何类,而在 Java 代码中引用格式如下: package.name.ObjectName. 而在 Dalvik 中引用格式如下: Lpakeage/name/ObjectName L 代表引用的是 Java 类的类型,而后面则为类的全限定名(包路径),例如 Java 中的 String 对应 Dalvik 中描述应为:Ljava/lang/String
  • 数组类型: [ 代表所有基本类型的数组。[ 后面跟随着是基本类型描述符。 每一个一维数组前面都会有一个 [ ,例如 Java 中的 int [] 对应的描述便是 [I,则对应的二维数组 int [][] 对应的则为 [[I 。

关于 Dalvik 字节码详情,LZ 搞了份 pdf 版本,下面附上链接~

链接: https://pan.baidu.com/s/14I63tafdQRcBkSm6UO1qaQ 密码:2w7h

https://download.csdn.net/download/u012400885/10528023

科普时间:

寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,存器有累加器(ACC)。

而寄存器有俩种不同的命名方式,如下图所示:

而在实际当中,一般来讲,P(0) 代表当前指针。

Enmmm,还有个比较坑的事儿,谷歌Baba在 5.0 后彻底移除了 Dalvik 层,由此替代的是 ART,如下图:

2. Apk 构建流程

构建流程涉及许多将项目转换成 Android 应用 APK 的工具和流程。构建流程非常灵活,因此了解它的一些底层工作原理会很有帮助。

如上图所示,典型 Android 应用模块的构建流程通常依循下列步骤:

  1. 编译器将源代码转换成 Dex(Dalvik Executable) 文件(其中包括运行在 Android 设备上的字节码),将所有其他内容转换成已编译资源;
  2. Apk 打包器将 Dex文件和已编译资源合并成单个 Apk 。不过,必须先签名 Apk ,才能将应用安装并部署到 Android 设备上;
  3. Apk 打包器使用调试或发布密钥库来签名 Apk :
  • 如果构建的是调试版本的应用(即专用于测试和分析的应用),打包器会使用调试密钥库签署应用。Android Studio 自动使用调试密钥库配置新项目;
  • 如果构建的是打算向外发布的发布版本应用,打包器会使用发布密钥库签署应用。
  • 在生成最终 Apk 之前,打包器会使用 zipalign 工具对应用进行优化,减少其在设备上运行时的内存占用。

而下方也附上一张实际打包的简图:

二、反编译前工具准备

反编译前期,需要我们准备一系列的工具,有了这些工具,我们才能更好的进行我们的反编译操作。

那么下面,LZ 简单介绍几个基础所需要的工具:

首先,可以去查看 LZ 前段时间编写的部分博文:

破解APK修改资源文件

修改包名以及玩个淫思奇巧

Enmmm,当然还有一篇是 LZ 之前遇坑记录,如下:

记录Android Killer反编译时遇到的异常

这里再次总结一波:

2.1 比较好用工具以及描述

  • ApkTool 作用: 反编译出 Apk 中的资源文件, 例如 AndroidManifest.xml 和 res 资源文件,或者回包形成新的 Apk;
  • Dex2jar 作用:反编译出 Apk 中的 class;
  • JD-GUI / JAD 作用:反编译 class 为 java 源文件;
  • Android 逆向助手 2.2 下载链接: https://pan.baidu.com/s/1TJ1Q5hdwSfzvf6cilFOMkw 密码:ipu9
  • ApkToolBox 作用如下 :

点我下载链接: https://pan.baidu.com/s/16jE9Bu2pm_lRmdFZry0soQ 密码:mac4

  • 吾爱破解工具集
  • onekey-decompile-apk-1.0.1 作用:一步到位反编译apk工具;

PS:

反编译工具还是 JAD 最强, JD-GUI 只是方便反编译/查看整个 Jar 而已, 反编译出来的代码不全,

因此需要 JD-GUI + JAD。

欢迎各位老铁关注~不定期发布~见证你我的成长路~!!!

觉得不错,动动小手,转发让更多人看到,3Q,比心~

原文发布于微信公众号 - 贺利权(hlq_struggle)

原文发表时间:2018-07-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券