当前位置: 首页 > news >正文

关于 smali:3. Smali 与 APK 结构理解

一、APK 解包工具:apktool, jadx, dex2jar

当我们拿到一个 APK 文件进行逆向时,通常的目标是:

  • 分析 Java 层源码(逻辑、加密、通信等)

  • 修改资源或 Smali 代码实现功能修改

  • 尝试定位加固方式、脱壳、定位敏感函数

而实现这些目标,需要用到不同的工具来解析 APK 的不同部分。

1.1 工具 1:apktool —— 解包 & 重打包 + Smali 分析

功能:

  • 反编译 APK 为 Smali 代码

  • 提取 AndroidManifest.xml 和资源文件(res、assets)

  • 支持修改后再 重新打包 APK

输出内容:

myapp/
├── AndroidManifest.xml       ← 已反编译的清晰 XML
├── smali/                    ← Smali 代码目录
├── res/                      ← layout、drawable 等资源
├── assets/                   ← 加密配置、脚本文件等
└── original/                 ← META-INF 等签名信息

使用方式:

apktool d myapp.apk -o myapp
apktool b myapp -o newapp.apk

优点:

  • 结构清晰,可修改资源文件和 Smali

  • 支持重打包,非常适合二次修改

  • 可搭配签名工具重新签名

缺点:

  • 无法恢复 Java 源码(Smali 是汇编级中间代码)

1.2 工具 2:jadx —— Java 源码查看神器(GUI + CLI)

功能:

  • 将 DEX 文件反编译为 Java 源码

  • 提供 GUI 界面浏览、搜索类、方法、字符串

  • 也可以命令行导出所有 Java 代码

使用方式:

GUI 方式(推荐):

jadx-gui myapp.apk
  • 可搜索类名、字符串、方法名

  • 可定位到 Java 层代码逻辑

  • 可导出为整个项目 .java 文件

CLI 导出:

jadx -d output_dir myapp.apk

优点:

  • Java 源码级别还原,阅读体验好

  • 快速定位加密函数、网络通信、关键逻辑

  • 可搜索代码片段、敏感 API 使用等

缺点:

  • 不是 100% 恢复原代码,变量名、结构可能会乱

  • 不能直接用于修改和重打包

1.3 工具 3:dex2jar + jd-gui —— 老牌 Java 源码还原工具链

功能:

  • 将 DEX 文件转换为 .jar

  • 用 Java 反编译工具查看 .jar 的 Java 源码

使用方式:

dex2jar myapp.apk -o myapp.jar

然后用 jd-gui 打开生成的 JAR 文件查看源码。

优点:

  • 最早的 Java 源码查看方式之一

  • jd-gui 查看变量、函数较直观

缺点:

  • dex2jar 在处理多 dex / 新版 APK 时容易出错

  • jd-gui 不如 jadx-gui 强大(不能搜索,UI 老旧)

1.4 工具之间的配合策略

目标使用工具说明
阅读 Java 代码jadx-gui推荐第一步,快速理解逻辑
修改资源或代码apktool提取 smali/res/,修改再打包
深度分析/自动脚本apktool + fridaSmali Hook、定位类名
压缩包分析(手动)unzip APK解压 apk 查看 META-INF / assets 手工分析
生成 .jar 查看dex2jar + jd-gui不推荐主力使用,适合老项目

1.5 推荐的完整工作流

  • apktool d myapp.apk → 拿到 Smali + 资源 + Manifest

  • jadx-gui myapp.apk → 找 Java 关键函数、参数、逻辑

  • 分析混淆/加密 → 对照 Smali 和 Java 定位加壳/关键代码

  • 修改 Smali 或资源 → 用 apktool 修改后 b 打包

  • 重新签名 APK(使用 apksignerjarsigner

1.6 实战举例

实战目的使用方式
找到某个 API Token 的加载逻辑jadx 搜索字符串 → 定位 Java 函数
修改登录校验apktool 找到 Smali → 修改跳过检查
Hook 某个函数jadx 找类名函数名 → Frida 脚本注入
脱壳分析加固apktool 查看 Manifest + Smali → 判断加固方案
恢复加密算法实现jadx 找 Java 加密逻辑 → Smali 跟踪字段流

二、APK 编译 / 反编译流程(反编译到 smali,修改后重新打包)

2.1 整体流程概览

要做的是:

原始 APK → [反编译] → Smali 代码 & 资源文件 → [修改] → [重新打包] → 签名 → 安装运行测试

用的核心工具是:

  • apktool负责 APK → Smali & 资源 的反编译、再打包

  • keytool / apksignerAPK 签名

  • 模拟器或真机:测试打包后的 APK

2.2 反编译 APK 到 Smali

工具:apktool

命令:

apktool d your_app.apk -o your_app_src

反编译结果目录结构:

your_app_src/
├── AndroidManifest.xml   ← Android 应用的配置文件(反编译后的 XML)
├── smali/                ← 主 dex 的 Smali 代码
├── smali_classes2/       ← 第二个 dex(如有)
├── res/                  ← 应用 UI 资源
├── assets/               ← 各种配置、脚本、加密数据
├── unknown/              ← 非标准结构
└── original/             ← 原始 META-INF 信息等

2.3 修改 Smali 或资源

可以修改的内容包括:

内容路径示例
Java逻辑smali/修改跳过登录校验
字符串res/values/strings.xml修改 App 名
布局res/layout/改按钮显示
ManifestAndroidManifest.xml增加权限等

示例:跳过登录逻辑

找到如下 Smali 函数:

.method public isLogin()Z.locals 1const/4 v0, 0x1    # 改成返回 truereturn v0
.end method

2.4 重新打包 APK

命令:

apktool b your_app_src -o new_app.apk

这将把修改过的 Smali + 资源重新打包成一个新的 APK。

2.5 给 APK 签名(非常关键)

Android 不允许安装未签名 APK,必须使用 debug 签名或你自己的 keystore。

1)使用 debug 签名快速签名:

# 如果你用的是 Android SDK,自带 debug.keystore
apksigner sign --ks ~/.android/debug.keystore --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android --out signed_new_app.apk new_app.apk

2)自己生成签名:

# 生成签名(仅需一次)
keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myalias

签名命令:

apksigner sign --ks my-release-key.jks --out signed.apk new_app.apk

2.6 安装并测试 APK

adb install -r signed.apk

或者将 APK 拖进模拟器中测试(如雷电、夜神、Pixel)。

2.7 常见问题

问题解决方式
安装失败:未签名一定要使用 apksigner 签名
打包失败:资源异常检查 res/ 文件是否手动修改破坏结构
安装后闪退使用 logcat 查看崩溃日志
找不到类路径检查是否为 smali_classes2 或其他目录

2.8 补充技巧:快速调试 Smali 改动

  • 给函数添加日志:
const-string v0, "TAG"
const-string v1, "Login function called!"
invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
  • 替换函数返回值(绕过登录):
const/4 v0, 0x1
return v0
  • 强制跳转 Activity(改 Intent)

2.9 小结 

  • apktool 反编译 APK 为 Smali + 资源

  • 修改 Smali 或资源文件以实现绕过或定制

  • 使用 apktool b 打包、apksigner 签名

  • 安装并调试新 APK,结合 logcat 分析


三、Manifest 与资源文件分析

3.1 AndroidManifest.xml 分析详解

APK 中的 AndroidManifest.xml 是核心配置文件,控制应用的权限、组件、入口点等信息。通过 apktool 反编译后,它会变成可读的 XML,路径如下:

your_app/
├── AndroidManifest.xml

Manifest 的主要组成部分

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.app"android:versionCode="10"android:versionName="1.0.0"><!-- 权限声明 --><uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.READ_SMS"/><!-- 特性声明 --><uses-feature android:name="android.hardware.camera" android:required="false"/><!-- 应用声明 --><applicationandroid:label="@string/app_name"android:icon="@mipmap/ic_launcher"android:allowBackup="true"><!-- 主入口 Activity --><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity><!-- 其他组件 --><activity android:name=".LoginActivity"/><service android:name=".MyService"/><receiver android:name=".AlarmReceiver"/><provider android:name="androidx.core.content.FileProvider"android:authorities="com.example.app.fileprovider"android:exported="false"/></application>
</manifest>

Manifest 可分析的关键点

项目作用用途
package应用包名定位主类、资源路径
<uses-permission>声明权限判断敏感操作(如读短信、网络、相机)
<application>应用入口看启动配置、资源入口
<activity>声明 Activity找到界面跳转逻辑入口
<service>后台服务检查是否有后台恶意逻辑
<receiver>广播监听是否监听短信、系统事件等
<provider>文件或数据库访问接口判断是否有导出风险点

示例:如何通过 Manifest 快速定位入口类?

<activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter>
</activity>

主界面是 .MainActivity,真实路径是:

smali/com/example/app/MainActivity.smali

3.2 res 目录资源文件分析

资源文件主要用于界面布局、文字、图片等。路径:

your_app/
├── res/
│   ├── layout/           # XML 界面布局
│   ├── values/           # 字符串、颜色、样式等
│   ├── drawable*/        # 图片资源
│   ├── mipmap*/          # 启动图标等

layout 目录(布局 XML)

<!-- res/layout/activity_login.xml -->
<LinearLayout ... ><TextView android:text="@string/login_title"/><EditText android:id="@+id/username"/><EditText android:id="@+id/password"/><Button android:onClick="doLogin"/>
</LinearLayout>
  • 可以帮助你快速识别按钮/控件绑定的方法名

  • 比如 onClick="doLogin"LoginActivity.smali 里找 doLogin 方法

values 目录(字符串/样式)

<!-- res/values/strings.xml -->
<resources><string name="app_name">极验验证器</string><string name="login_title">请输入账号密码</string>
</resources>
  • 用于分析文本提示、隐藏字符串等

  • Java/Smali 中引用方式:@string/app_nameR.string.app_name

drawable/mipmap(图标/图片资源)

  • drawable 通常为按钮背景、状态图标

  • mipmap 是 APP 图标ic_launcher.png

可用工具查看其中是否嵌入敏感信息,比如二维码、恶意图标伪装等。

3.3 资源 ID 映射机制(R.java 与 Smali 的关系)

  • Java 中:R.layout.activity_login

  • 编译后:0x7f0a0010(整数资源 ID)

  • 在 Smali 中的使用方式:

const v0, 0x7f0a0010
invoke-virtual {p0, v0}, Lcom/example/app/MainActivity;->setContentView(I)V

可以通过 jadx-gui 打开 APK 找到 R.java 对应的映射关系来反查 ID。

实战分析思路总结

场景Manifest 线索res 线索后续操作
找主界面<intent-filter>MainActivitylayout XML 中 onClick 函数进入 smali 分析函数
判断功能权限uses-permission 中包含 READ_SMSRECORD_AUDIO检查是否监听短信/语音等
监听短信广播<receiver>SmsReceiver分析是否有钓鱼或信息拦截
定位文件导出风险点<provider android:exported="true">判断是否有任意文件读取风险点
找图形验证码组件layout 中 ImageView、Buttonlayout/activity_login.xml分析点击事件和图像加载逻辑

3.4 小结:Manifest + 资源分析的意义

  •  快速定位关键组件入口(Activity/Service/Receiver)

  •  判断敏感权限申请与组件导出(安全评估)

  •  配合布局文件找 UI 操作对应方法(逆向入口)

  •  结合 Smali 对照分析逻辑代码


四、Dex 文件格式基础(了解 Smali 背后是 Dalvik bytecode)

什么是 DEX 文件?

  • DEX 是 Android 平台用于执行的二进制格式的字节码文件,由 Java 编译而来。

  • 一个 APK 中可能有一个或多个 DEX 文件(比如 classes.dex, classes2.dex 等)。

  • 它是 Dalvik 虚拟机(早期 Android)ART(Android Runtime) 执行的对象。

4.1 DEX 文件的整体结构

一个 DEX 文件的结构如下图:

+--------------------+
| Header             |  # dex 文件头部
+--------------------+
| String IDs         |  # 所有字符串索引表
+--------------------+
| Type IDs           |  # 所有类型(类)索引表
+--------------------+
| Proto IDs          |  # 所有方法签名(参数/返回类型)
+--------------------+
| Field IDs          |  # 所有字段(类成员变量)
+--------------------+
| Method IDs         |  # 所有方法的签名
+--------------------+
| Class Definitions  |  # 每个类的结构体定义
+--------------------+
| Data Section       |  # 所有字节码、常量、注解等原始数据
+--------------------+

所有这些部分都以**“索引+引用+数据”**的方式来组织,这就解释了为什么在 Smali 里经常看到 .field, .method, .proto, .string, .type 等信息。

4.2 关键字段详细说明

段名说明对应 Smali
Header包含 magic、版本、校验和等信息与 Smali 无直接关系
String IDs所有字符串常量,如类名、方法名、字段名.method, .field 中用到的字符串
Type IDs所有类型(如 Ljava/lang/String;所有类/参数类型
Proto IDs方法的签名(参数类型+返回值)方法声明部分 .method public test(II)V
Field IDs类字段:所属类 + 名称 + 类型.field public name:Ljava/lang/String;
Method IDs方法签名(所属类 + 名称 + 签名).method public test(I)V
Class Defs每个类的信息:字段、方法、超类等每个 .smali 文件
Data Section字节码、注解、数组、调试信息.locals, 指令等都是来自这里

4.3 从 Java 到 DEX 到 Smali 的关系图

// Java代码
public int sum(int a, int b) {return a + b;
}

编译成 DEX(字节码):

[method_id] sum (II)I
[proto_id]  params: int, int → return: int
[code_item] add-int v0, p1, p2

反编译成 Smali:

.method public sum(II)I.locals 1add-int v0, p1, p2return v0
.end method

可以看到:

DEX 字节码结构Smali 表现说明
method_id.method方法定义
proto_id(II)I参数签名
code_item指令块add-int / return
field_id.field成员变量
string_id方法名、字段名、类名被引用的字符串

4.4 DEX 中的字节码与 Smali 指令对应

Smali 指令DEX 字节码行为说明
const v0, 1加载常量立即数加载
move v0, p1寄存器移动值拷贝
add-int v0, v1, v2两数相加算术操作
return v0方法返回指定值返回
invoke-virtual {p0}, Lxxx;->method()V虚方法调用方法跳转
iget v0, p0, Lxxx;->field:I获取成员字段对象字段读取
sput v0, Lxxx;->staticField:I写静态字段静态变量写入

4.5 为什么需要理解DEX 格式?

  • 更深入理解 Smali 指令意义(知道它来源于哪段 DEX 字节码)

  • 定位问题更方便(某个类 Smali 错误,找其 DEX 结构)

  • 参与二进制级分析(脱离 Smali,直接 patch DEX)

  • 配合 tools(baksmali、dexdump、dex2jar)分析数据段、方法偏移等

4.6 小结

内容意义
DEX 是 Dalvik/ART 的执行格式所有 Smali 指令来源
每个类在 DEX 中有一个 ClassDefSmali 对应一个 class
所有调用/变量/类/方法 都是“索引+引用”机制提高执行效率和体积压缩
DEX 格式理解有助于进阶分析DEX Patch、反调试、脱壳等

相关文章:

  • 构建智慧校园门户:技术架构与实践指南
  • 银发团扎堆本地游,“微度假”模式如何盘活银发旅游市场?
  • Autodesk Maya 2025.3新特性
  • halcon高斯滤波
  • AI如何颠覆财务预测?——用Python打造自动化智能分析系统
  • JSONP跨域原理全解析
  • vue2使用el-tree实现两棵树间节点的拖拽复制
  • 计算机网络实验课(三)——直接使用数据构造以太网帧,打包并发送|使用SharpPcap库函数构造以太网帧,并发送出去
  • 【Webtrees 手册】第 8章 - 网站管理员指南
  • 在 Unity 中,Start 方法直接设置 RectTransform 的位置,时出现问题,与预计位置不匹配。
  • LightGBM的python实现及参数优化
  • 从十进制到二进制:深入理解定点数与浮点数表示
  • Python学习(2) ----- Python的类型
  • 多模态大语言模型arxiv论文略读(九十五)
  • Python正则表达式:30秒精通文本处理
  • Java中数组(一维/二维)与字符串操作(String/StringBuilder/StringBuffer)详解
  • mysql中的索引怎么用?
  • 高压单端探头,如何实现大比例的衰减?
  • 在thinkphp5.0中。单表使用 model clone 时就会有问题。 需要使用 alias(), 否则会报错。
  • 网络协议:[0-RTT 认证 ]
  • 做网站要注册那些商标/网站建设黄页视频
  • 做平面设计赚钱靠谱的网站有哪些/快速排名工具免费
  • 国内高清视频素材网站/厦门网站seo哪家好
  • 网站建设实训的认识/网站如何优化流程
  • 花乡科技园区网站建设/网络建站优化科技
  • 建设路21号官方网站/企业营销策划是做什么的