APK逆向分析入门-以某扫描软件为例
字数 1402 2025-08-22 12:23:00

APK逆向分析入门教程 - 以某扫描软件为例

1. 准备工作

1.1 所需工具

  • Jadx:用于反编译APK查看Java代码
  • MT管理器:文件管理器和APK分析工具
  • BlackDex:脱壳工具
  • NP管理器:用于DEX修复和APK签名
  • Frida:动态Hook工具
  • 文本编辑器:用于修改smali代码

2. 脱壳处理

2.1 识别加固

  1. 使用MT管理器查看APK,发现是BB加固
  2. 使用Jadx打开APK,确认是加固后的代码

2.2 脱壳步骤

  1. 使用BlackDex进行脱壳
  2. 从脱壳后的APK中找出和原有DEX相同的并删除
  3. 使用DEX编辑器查看脱壳后的内容
  4. 删除重复或无用的DEX文件
  5. 对保留的DEX进行修复(使用NP管理器)
  6. 重命名DEX为classes1.dex到classesS.dex
  7. 将修复后的DEX复制到原项目中(不要自动签名)

2.3 清理加固特征

  1. 在lib和assets目录下查找加固特征码并删除
  2. 使用NP管理器重新签名APK
  3. 使用MT管理器验证是否显示无加固

3. 修复入口

3.1 查找真实入口

  1. 查看com.SecShell.SecShell.H
  2. 找到appname行,这是真实入口

3.2 修改入口

  1. 将原入口替换为真实入口
  2. 检查AndroidManifest.xml中是否有android:appComponentFactory="com.SecShell.SecShell.AP"
  3. 如果有则删除该属性

4. 跳过启动界面

4.1 分析启动流程

  1. 使用Activity记录器观察应用启动情况
  2. 发现启动顺序:NewLaunchActivityMainActivity

4.2 修改启动项

  1. 直接修改AndroidManifest.xml中的启动项
  2. 将启动Activity从NewLaunchActivity改为MainActivity
  3. 这样可以跳过初始检查流程

5. 破解会员功能

5.1 分析翻译功能

  1. 发现翻译功能调用百度翻译API
  2. 应用先向自己的服务器发送请求验证权限
  3. 验证通过后才调用百度翻译API

5.2 关键函数分析

  1. isIssucc()函数决定是否允许翻译
    public boolean isIssucc() {
        return this.issucc;
    }
    
  2. 需要修改使其始终返回true

5.3 修改smali代码

原始smali代码:

.method public isIssucc()Z
    .registers 2
    .line 20
    iget-boolean v0, p0, Lcom/jtjsb/paitushizi/bean/TranslationBean;->issucc:Z
    return v0
.end method

修改后:

.method public isIssucc()Z
    .registers 2
    .line 20
    const v0, 0x1
    return v0
.end method

5.4 使用Frida Hook

function carhook3(){
    let TranslationBean = Java.use("com.jtjsb.paitushizi.bean.TranslationBean");
    TranslationBean["isIssucc"].implementation = function () {
        console.log('isIssucc is called');
        let ret = this.isIssucc();
        console.log('isIssucc ret value is ' + ret);
        return ret;
    };
};

6. 破解会员身份验证

6.1 分析会员验证

  1. 应用会检查免费次数或会员身份
  2. 关键函数:AppConfigs.getFreeTimes()DataBeanUtils.isVipExpired()

6.2 修改会员验证

  1. 修改isVipExpired()函数使其返回false
  2. 原始逻辑:
    if (vip == null) {
        return true;
    }
    
  3. 修改smali代码使函数返回false

6.3 修改点

  1. 修改vip==null的判断返回false
  2. 在return前给v0赋值0(即false)

7. 测试验证

  1. 安装修改后的APK
  2. 验证是否可以跳过启动界面
  3. 测试翻译功能是否无视字数限制
  4. 验证会员功能是否可用
  5. 确认免费次数用尽后仍可使用所有功能

8. 注意事项

  1. 修改DEX后不要自动签名
  2. 修改smali时要保持寄存器使用一致
  3. 修改前备份原始APK
  4. 测试时要覆盖各种边界条件
  5. 注意AndroidManifest.xml中的组件声明

通过以上步骤,可以完成对该扫描软件的逆向分析和功能修改,实现跳过启动界面和破解会员功能的目的。

APK逆向分析入门教程 - 以某扫描软件为例 1. 准备工作 1.1 所需工具 Jadx:用于反编译APK查看Java代码 MT管理器:文件管理器和APK分析工具 BlackDex:脱壳工具 NP管理器:用于DEX修复和APK签名 Frida:动态Hook工具 文本编辑器:用于修改smali代码 2. 脱壳处理 2.1 识别加固 使用MT管理器查看APK,发现是BB加固 使用Jadx打开APK,确认是加固后的代码 2.2 脱壳步骤 使用BlackDex进行脱壳 从脱壳后的APK中找出和原有DEX相同的并删除 使用DEX编辑器查看脱壳后的内容 删除重复或无用的DEX文件 对保留的DEX进行修复(使用NP管理器) 重命名DEX为classes1.dex到classesS.dex 将修复后的DEX复制到原项目中(不要自动签名) 2.3 清理加固特征 在lib和assets目录下查找加固特征码并删除 使用NP管理器重新签名APK 使用MT管理器验证是否显示无加固 3. 修复入口 3.1 查找真实入口 查看 com.SecShell.SecShell.H 类 找到 appname 行,这是真实入口 3.2 修改入口 将原入口替换为真实入口 检查AndroidManifest.xml中是否有 android:appComponentFactory="com.SecShell.SecShell.AP" 如果有则删除该属性 4. 跳过启动界面 4.1 分析启动流程 使用Activity记录器观察应用启动情况 发现启动顺序: NewLaunchActivity → MainActivity 4.2 修改启动项 直接修改AndroidManifest.xml中的启动项 将启动Activity从 NewLaunchActivity 改为 MainActivity 这样可以跳过初始检查流程 5. 破解会员功能 5.1 分析翻译功能 发现翻译功能调用百度翻译API 应用先向自己的服务器发送请求验证权限 验证通过后才调用百度翻译API 5.2 关键函数分析 isIssucc() 函数决定是否允许翻译 需要修改使其始终返回true 5.3 修改smali代码 原始smali代码: 修改后: 5.4 使用Frida Hook 6. 破解会员身份验证 6.1 分析会员验证 应用会检查免费次数或会员身份 关键函数: AppConfigs.getFreeTimes() 和 DataBeanUtils.isVipExpired() 6.2 修改会员验证 修改 isVipExpired() 函数使其返回false 原始逻辑: 修改smali代码使函数返回false 6.3 修改点 修改vip==null的判断返回false 在return前给v0赋值0(即false) 7. 测试验证 安装修改后的APK 验证是否可以跳过启动界面 测试翻译功能是否无视字数限制 验证会员功能是否可用 确认免费次数用尽后仍可使用所有功能 8. 注意事项 修改DEX后不要自动签名 修改smali时要保持寄存器使用一致 修改前备份原始APK 测试时要覆盖各种边界条件 注意AndroidManifest.xml中的组件声明 通过以上步骤,可以完成对该扫描软件的逆向分析和功能修改,实现跳过启动界面和破解会员功能的目的。