安卓逆向-从分析Dalvik字节码、Dalvik指令集到修改smali代码逻辑
字数 1954 2025-08-09 18:44:09

Android逆向工程:从Dalvik字节码到Smali代码修改

一、Dalvik虚拟机基础

1.1 Dalvik虚拟机概述

Dalvik是Android系统中用于运行应用程序的虚拟机,特点包括:

  • 基于寄存器架构(不同于JVM的栈架构)
  • 使用dex(Dalvik Executable)文件格式
  • 针对移动设备优化(内存占用小、启动快)

1.2 Dalvik字节码特点

  • 指令集精简,约200条指令
  • 使用16位寄存器(v0-v65535)
  • 支持宽指令(wide指令前缀)
  • 操作码为1字节(0x00-0xFF)

二、Dalvik指令集详解

2.1 基本指令分类

数据移动指令

  • move vA, vB - 将vB的值移动到vA
  • move/from16 vAA, vBBBB - 从大索引寄存器移动
  • move-wide - 移动64位数据
  • move-object - 移动对象引用

数据操作指令

  • const/4 vA, #+B - 4位常量
  • const/16 vAA, #+BBBB - 16位常量
  • const-string vAA, string@BBBB - 加载字符串

方法调用指令

  • invoke-virtual - 调用虚方法
  • invoke-super - 调用父类方法
  • invoke-direct - 调用直接方法
  • invoke-static - 调用静态方法
  • invoke-interface - 调用接口方法

控制流指令

  • if-eq vA, vB, +CCCC - 等于跳转
  • if-ne vA, vB, +CCCC - 不等于跳转
  • goto +AA - 无条件跳转
  • switch - 分支跳转表

2.2 寄存器使用约定

  • 参数寄存器:方法参数按顺序使用v0-vn
  • 返回值:使用v0或v0-v1(64位)
  • 局部变量:从参数寄存器后开始分配

三、Smali语法解析

3.1 Smali文件结构

.class <访问权限> <类名>
.super <父类>
.source <源文件名>

# 字段定义
.field <访问权限> <字段名>:<字段类型>

# 方法定义
.method <访问权限> <方法名>(<参数类型>)<返回类型>
    .registers <寄存器数量>
    .param <参数定义>
    .prologue
    # 方法体
.end method

3.2 数据类型表示

  • 基本类型:
    • V - void
    • Z - boolean
    • B - byte
    • S - short
    • C - char
    • I - int
    • J - long
    • F - float
    • D - double
  • 引用类型:
    • Lpackage/name/ObjectName; - 对象
    • [I - int数组
    • [[Ljava/lang/String; - String二维数组

四、逆向分析流程

4.1 工具链

  1. 反编译工具

    • apktool - 反编译apk到smali
    • dex2jar - dex转jar
    • jadx - 直接查看java代码
    • baksmali - dex转smali
  2. 分析工具

    • IDA Pro - 高级反汇编
    • JEB - 专业Android逆向工具
    • Bytecode Viewer - 多视图分析

4.2 分析步骤

  1. 使用apktool解包APK:

    apktool d target.apk -o output_dir
    
  2. 分析AndroidManifest.xml确定入口点

  3. 定位关键代码:

    • 搜索关键字符串
    • 跟踪Activity跳转
    • 分析网络请求相关类
  4. 阅读smali代码理解逻辑

五、Smali代码修改技术

5.1 常见修改场景

  1. 绕过验证

    • 修改条件跳转指令
    • 强制返回特定值
  2. 功能注入

    • 插入日志输出
    • 添加新方法调用
  3. 资源修改

    • 修改字符串资源
    • 替换图片资源

5.2 修改示例

示例1:修改返回值

原始代码:

.method public isVIP()Z
    .registers 2
    
    const/4 v0, 0x0
    
    return v0
.end method

修改后:

.method public isVIP()Z
    .registers 2
    
    const/4 v0, 0x1  # 修改为总是返回true
    
    return v0
.end method

示例2:绕过验证

原始代码:

if-eqz v0, :cond_0  # 如果v0==0跳转
invoke-static {v1}, Lcom/example/Check;->valid(Ljava/lang/String;)Z

:cond_0

修改为:

# 直接跳转到验证通过后的代码
goto :cond_0
nop  # 保持指令对齐

5.3 修改注意事项

  1. 保持寄存器数量一致(.registers)
  2. 注意指令对齐(nop填充)
  3. 修改后需要重新打包签名:
    apktool b output_dir -o modified.apk
    jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my.keystore modified.apk alias_name
    

六、高级逆向技巧

6.1 动态调试

  1. 使用adb forward转发调试端口:

    adb forward tcp:8700 jdwp:<pid>
    
  2. 使用jdb或IDEA进行调试

6.2 代码注入

  1. 使用Xposed框架进行运行时修改
  2. 使用Frida进行动态hook

6.3 混淆对抗

  1. 识别常见混淆模式:

    • 类名/方法名替换
    • 控制流平坦化
    • 字符串加密
  2. 反混淆技术:

    • 动态分析获取运行时信息
    • 模式识别恢复原始名称
    • 自定义脚本处理

七、实战案例

7.1 破解License验证

  1. 定位License检查方法
  2. 分析验证逻辑
  3. 修改关键跳转或返回值

7.2 解锁付费功能

  1. 查找功能开关方法
  2. 修改条件判断
  3. 绕过服务器验证

7.3 分析加密算法

  1. 定位加密/解密方法
  2. 提取密钥和算法
  3. 重建加密逻辑

八、法律与道德规范

  1. 仅对自有应用或授权应用进行逆向
  2. 不得用于非法目的
  3. 尊重知识产权
  4. 遵守相关法律法规

九、学习资源推荐

  1. 官方文档:

    • Dalvik字节码规范
    • Android开发者文档
  2. 工具资源:

    • Apktool官方Wiki
    • Smali/Baksmali项目
  3. 进阶书籍:

    • 《Android软件安全与逆向分析》
    • 《Android安全攻防权威指南》
Android逆向工程:从Dalvik字节码到Smali代码修改 一、Dalvik虚拟机基础 1.1 Dalvik虚拟机概述 Dalvik是Android系统中用于运行应用程序的虚拟机,特点包括: 基于寄存器架构(不同于JVM的栈架构) 使用dex(Dalvik Executable)文件格式 针对移动设备优化(内存占用小、启动快) 1.2 Dalvik字节码特点 指令集精简,约200条指令 使用16位寄存器(v0-v65535) 支持宽指令(wide指令前缀) 操作码为1字节(0x00-0xFF) 二、Dalvik指令集详解 2.1 基本指令分类 数据移动指令 move vA, vB - 将vB的值移动到vA move/from16 vAA, vBBBB - 从大索引寄存器移动 move-wide - 移动64位数据 move-object - 移动对象引用 数据操作指令 const/4 vA, #+B - 4位常量 const/16 vAA, #+BBBB - 16位常量 const-string vAA, string@BBBB - 加载字符串 方法调用指令 invoke-virtual - 调用虚方法 invoke-super - 调用父类方法 invoke-direct - 调用直接方法 invoke-static - 调用静态方法 invoke-interface - 调用接口方法 控制流指令 if-eq vA, vB, +CCCC - 等于跳转 if-ne vA, vB, +CCCC - 不等于跳转 goto +AA - 无条件跳转 switch - 分支跳转表 2.2 寄存器使用约定 参数寄存器:方法参数按顺序使用v0-vn 返回值:使用v0或v0-v1(64位) 局部变量:从参数寄存器后开始分配 三、Smali语法解析 3.1 Smali文件结构 3.2 数据类型表示 基本类型: V - void Z - boolean B - byte S - short C - char I - int J - long F - float D - double 引用类型: Lpackage/name/ObjectName; - 对象 [ I - int数组 [ [ Ljava/lang/String; - String二维数组 四、逆向分析流程 4.1 工具链 反编译工具 : apktool - 反编译apk到smali dex2jar - dex转jar jadx - 直接查看java代码 baksmali - dex转smali 分析工具 : IDA Pro - 高级反汇编 JEB - 专业Android逆向工具 Bytecode Viewer - 多视图分析 4.2 分析步骤 使用apktool解包APK: 分析AndroidManifest.xml确定入口点 定位关键代码: 搜索关键字符串 跟踪Activity跳转 分析网络请求相关类 阅读smali代码理解逻辑 五、Smali代码修改技术 5.1 常见修改场景 绕过验证 : 修改条件跳转指令 强制返回特定值 功能注入 : 插入日志输出 添加新方法调用 资源修改 : 修改字符串资源 替换图片资源 5.2 修改示例 示例1:修改返回值 原始代码: 修改后: 示例2:绕过验证 原始代码: 修改为: 5.3 修改注意事项 保持寄存器数量一致(.registers) 注意指令对齐(nop填充) 修改后需要重新打包签名: 六、高级逆向技巧 6.1 动态调试 使用adb forward转发调试端口: 使用jdb或IDEA进行调试 6.2 代码注入 使用Xposed框架进行运行时修改 使用Frida进行动态hook 6.3 混淆对抗 识别常见混淆模式: 类名/方法名替换 控制流平坦化 字符串加密 反混淆技术: 动态分析获取运行时信息 模式识别恢复原始名称 自定义脚本处理 七、实战案例 7.1 破解License验证 定位License检查方法 分析验证逻辑 修改关键跳转或返回值 7.2 解锁付费功能 查找功能开关方法 修改条件判断 绕过服务器验证 7.3 分析加密算法 定位加密/解密方法 提取密钥和算法 重建加密逻辑 八、法律与道德规范 仅对自有应用或授权应用进行逆向 不得用于非法目的 尊重知识产权 遵守相关法律法规 九、学习资源推荐 官方文档: Dalvik字节码规范 Android开发者文档 工具资源: Apktool官方Wiki Smali/Baksmali项目 进阶书籍: 《Android软件安全与逆向分析》 《Android安全攻防权威指南》