简单的APK结构和Dalvik字节码

简单的APK结构

应用打包的核心文件——APK(Android Package)

APK 文件是Android操作系统中的应用程序包,它包含了应用的所有资源、代码和必要的配置文件。可以把APK看作一个容器,其中集成了Android应用的所有组成部分。

实际上,APK 文件是以 ZIP 格式进行压缩打包的,只要在电脑上将apk后缀改为zip即可解压。

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
项目根目录/                     # 整个项目的根目录
├── .gradle/ # Gradle构建工具的缓存文件,自动生成,无需手动修改
├── .idea/ # Android Studio的配置文件目录,包含项目设置等,自动生成
├── app/ # 应用的核心模块,主要开发工作在此目录进行
│ ├── src/ # 源代码和资源的主目录
│ │ ├── main/ # 主代码和资源目录(正式环境)
│ │ │ ├── java/(或kotlin/) # 源代码目录,按包名组织
│ │ │ │ └── com/example/myapp/ # 应用的包名目录(示例)
│ │ │ │ ├── MainActivity.java(或.kt) # 应用入口Activity,定义界面逻辑
│ │ │ │ └── utils/ # 工具类目录(如网络、数据处理工具)
│ │ │ ├── res/ # 资源目录,按类型分类
│ │ │ │ ├── drawable/ # 可绘制资源(图片、形状、选择器等)
│ │ │ │ │ ├── ic_logo.png # 应用图标图片资源
│ │ │ │ │ └── shape_round.xml # 圆角形状资源
│ │ │ │ ├── layout/ # 布局文件目录,定义UI结构
│ │ │ │ │ └── activity_main.xml # MainActivity对应的布局文件
│ │ │ │ ├── mipmap/ # 应用图标目录(适配不同屏幕密度)
│ │ │ │ │ └── ic_launcher.png # 应用桌面图标
│ │ │ │ ├── values/ # 配置资源目录
│ │ │ │ │ ├── strings.xml # 字符串资源(集中管理文本,避免硬编码)
│ │ │ │ │ ├── colors.xml # 颜色资源(定义应用配色)
│ │ │ │ │ └── dimens.xml # 尺寸资源(统一管理控件大小)
│ │ │ │ ├── raw/ # 原始文件目录(音频、视频等)
│ │ │ │ └── xml/ # 自定义XML资源(如菜单、网络配置)
│ │ │ └── AndroidManifest.xml # 应用清单文件,声明组件、权限、配置等
│ │ ├── androidTest/ # 仪器化测试目录(需在设备/模拟器上运行)
│ │ │ └── java/(或kotlin/) # 测试代码,如UI交互测试
│ │ └── test/ # 单元测试目录(在本地JVM运行)
│ │ └── java/(或kotlin/) # 测试代码,如逻辑单元测试
│ ├── build.gradle # 模块级构建脚本,配置依赖、编译选项等
│ └── proguard-rules.pro # 代码混淆规则(发布时减小APK体积并保护代码)
├── build/ # 编译生成的中间文件和APK,自动管理
├── gradle/ # Gradle包装器配置,自动下载指定版本Gradle
├── gradlew # Linux/Mac系统的Gradle命令行脚本
├── gradlew.bat # Windows系统的Gradle命令行脚本
├── build.gradle(Project) # 项目级构建脚本,配置全局插件和仓库
├── settings.gradle # 声明项目包含的模块(默认包含:app)
└── local.properties # 记录本地Android SDK路径,自动生成

主要部分

APK 文件通常包括以下几个主要部分

  1. AndroidManifest.xml
  2. classes.dex
  3. resources.arsc
  4. assets/
  5. lib/
  6. res/
  7. META-INF/
文件 注释
assets目录 存放APK的静态资源文件,比如视频,音频,图片等(不一定有但常见)
lib目录 armeabi-v7a基本通用所有Android设备,arm64-v8a只是用与64为的Android设备,x86常用于Android模拟器,其目录下的.so文件时c或者c++编译的动态链接库文件(不一定有但常见)
META-INF目录 保存应用的签名信息,签名信息可以验证APK文件的额完整性,相当于APK的身份验证(验证文件是否又被修改)
res目录 res目录存放资源文件,包括图片,字符串等,APK的 脸蛋由它的layout文件设计
AndroidManifest.xml文件 APK的应用清单信息,他描述了应用的名字,版本,权限,引用的库文件等信息
classes.dex文件 classes.dex是java原码编译后生成的java字节码文件,APK运行的主要逻辑
reaources.arsc文件 resources.arsc是编译后的二进制资源文件,它是一个映射表,映射着资源和id,通过R文件中的id就可以找到对应的资源

1.AndroidManifest.xml(关键核心)

AndroidManifest.xml 是每个Android应用不可或缺的配置文件,它包含了应用的关键信息。可以把它看作是应用的“蓝图”或“说明书”,它向系统声明了应用的基本属性、组件以及权限等。AndroidManifest.xml中包括以下重要部分:

  • 应用的包名(package):每个Android应用都有一个唯一的包名,通过包名来区分不同的应用。
  • 应用的组件(Activities, Services, Broadcast Receivers, Content Providers):声明应用包含哪些组件,以及这些组件的属性和功能。
  • 权限声明:列出应用所需的权限,如访问网络、读取存储、使用相机等。
  • 应用主题和图标:定义应用的UI样式、图标等。
  • 最小SDK版本和目标SDK版本:确定应用能在什么版本的Android系统上运行。

详细解析Manifest中的关键字段

  • <manifest>:包含整个应用的包信息及权限定义。
    • package: 定义了应用的包名,通常为反向域名格式,如com.example.app
    • android:versionCode: 定义应用的版本号。
    • android:versionName: 定义应用的版本名称。
  • <application>:包含应用的核心配置,如主题、图标等。
    • android:icon: 定义应用的图标。
    • android:label: 定义应用的名称。
    • android:theme: 应用的UI主题。
  • <activity> :声明应用的各个界面(Activity),以及这些Activity的属性和行为。
    • android:name: Activity的类名。
    • android:label: Activity的标签。
    • android:theme: Activity特有的UI主题。
  • <uses-permission>:声明应用所需要的权限,如访问网络、发送短信等。
  • <intent-filter>:定义组件的功能和响应的事件,如Activity的启动方式或Broadcast Receiver接收的广播类型。

2. classes.dex

classes.dex 文件包含了应用程序的可执行代码。它是应用的Dalvik字节码文件,也是Android应用在运行时通过 Dalvik虚拟机ART(Android Runtime) 解释执行的核心文件。每个Android应用中,所有的Java源代码都经过编译后形成一个或多个DEX(Dalvik Executable)文件,这些文件包含了应用的业务逻辑和代码实现。
在Android 5.0(Lollipop)之后,Google引入了 ART(Android Runtime) 代替了传统的Dalvik虚拟机,ART的执行方式比Dalvik更高效,支持Ahead-of-Time(AOT)编译和即时编译(JIT)策略。
这部分比较难可以拓展阅读一下,相关文档:

3. resources.arsc

resources.arsc 文件包含了应用程序的所有编译后的资源映射信息。这个文件并不存储实际的资源内容(如图片或字符串),而是存储资源与资源ID的映射关系。例如,它会保存应用中的字符串、颜色、尺寸、样式等信息以及这些资源的ID。通过这个文件,Android系统能够在应用运行时快速访问和加载所需的资源。

4. assets/

assets/ 目录包含了应用程序的原始资源文件,这些资源不经过编译,直接以原始形式存储。通常,开发者可以在该目录中存放字体文件、音频文件、HTML文件等,应用在运行时通过API来读取这些资源。例如,游戏可能会将所有的地图文件或纹理图像存放在此目录中。通过AssetManager API,应用可以访问这些文件。

5. lib/

lib/ 目录包含了本地库文件,通常是通过 JNI(Java Native Interface) 与C/C++编写的本地代码。这些库文件可以针对不同的硬件架构(如arm、x86等)进行编译,因此lib/目录下通常会为每个架构创建相应的子目录。这个目录中存放的本地库可以通过Java代码调用JNI接口实现与系统底层的交互。

不同架构的手机拥有不同的操汇编代码

1
2
3
4
5
6
7
8
9
10
11
├─arm64-v8a
│ libcyberpeace.so

├─armeabi-v7a
│ libcyberpeace.so

├─x86
│ libcyberpeace.so

└─x86_64
libcyberpeace.so

6. res/

res/ 目录包含了Android应用所需的所有资源文件。与 assets/ 目录不同,res/ 目录中的资源文件是经过编译的,按照不同类型的资源进行组织,例如:

  • **drawable/**:存放图像资源(如PNG、JPEG等格式的图片)。

  • **layout/**:存放XML格式的布局文件,定义界面的结构。

  • values/

    :存放各种配置文件,定义应用的常量、颜色、字符串等资源。例如:

    • strings.xml:存储应用的文本字符串。
    • colors.xml:存储应用使用的颜色资源。
    • styles.xml:存储样式资源。

values/目录下,除了strings.xmlcolors.xml等常见资源文件,还会有像dimens.xml(尺寸定义文件)和attrs.xml(自定义属性)等资源文件。

可以在文件夹目录中找到也可以在jadx里面查看。

7.META-INF/

META-INF/ 目录与Java的JAR文件类似,用于存放APK文件的元数据,如签名文件、校验信息等。此目录主要包括以下文件:

  • MANIFEST.MF:存放APK的清单文件,包含关于APK文件本身的信息。
  • CERT.RSA:包含APK文件的数字签名。
  • CERT.SF:存放APK文件的签名摘要。
    这些文件确保了APK的完整性和安全性,保证APK文件没有被篡改,且来自合法的开发者。

Dalvik字节码

Dalvik 字节码是安卓系统早期(Android 4.4 及之前)为Dalvik 虚拟机(DVM) 设计的中间代码,是安卓应用程序的核心执行载体。它由 Java 源代码编译生成的.class文件,通过安卓 SDK 中的dx工具进一步转换而来,最终存储在 APK 文件的classes.dex(或多 DEX 文件)中。

与 Java 字节码的核心区别:

  • 设计目标:Dalvik 字节码针对移动设备的有限内存和低功耗处理器优化,采用更紧凑的指令集和寄存器架构(Java 字节码是栈式架构),执行效率更高。
  • 存储形式:Java 字节码以.class文件单独存储,而 Dalvik 字节码将所有.class文件合并为单一的.dex文件,减少冗余并提高加载效率。
  • 运行环境:Java 字节码运行在 JVM(Java 虚拟机),而 Dalvik 字节码运行在 DVM;后期安卓引入 ART 虚拟机(Android Runtime)后,.dex文件会被预编译为本地机器码(.oat文件),但 Dalvik 字节码仍是逆向分析的基础。

逆向破解中作用:

  • 逆向入口:APK 核心逻辑载体,是提取、分析应用功能的起点(通过 dex2jar 等工具解析)。
  • 静态分析基础:指令直接对应应用逻辑(如条件判断、方法调用),可定位关键函数(验证、付费等)、追踪数据流向。
  • 动态调试对象:支持断点调试,可观察寄存器值、单步执行,实时修改指令绕过验证。
  • 破解核心:可反编译为 Smali(汇编形式)修改指令(如反转条件、删除关键调用),重编译后替换原 dex,实现功能篡改。
  • 对抗保护:即使被混淆 / 加壳,仍可通过指令特征、动态捕获解密后字节码突破。
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2025 唐小唐
  • 访问人数: | 浏览次数: