Android应用逆向工程技术入门参考手册

22次阅读
没有评论

Android应用逆向工程技术参考手册

Android应用逆向工程技术入门参考手册

⚠️ 法律与道德警告 本文档仅用于技术研究和学习目的。修改、反编译或分发受版权保护的应用程序可能违反《计算机软件保护条例》和相关法律法规。未经授权修改应用程序可能构成侵权。请仅在您拥有合法权限的应用上进行测试。


一、基础概念与工具

1.1 Smali语法基础

# 常用指令
const/4 v0, 0x1 # 将常量1赋值给寄存器v0 (4位)
const v0, 0x1 # 将常量1赋值给寄存器v0 (32位)
const-wide v0, 0x... # 赋值64位长整型
return v0 # 返回v0的值
return-void # 无返回值返回
invoke-virtual {v0}, L类名;->方法名()V # 调用实例方法

1.2 核心破解思路

  • 赋值法:修改返回值使条件永远为真/假
  • 跳转法:修改条件跳转逻辑
  • 删除法:移除调用代码或Activity
  • 替换法:替换关键字符串或资源

二、弹窗与广告去除

2.1 通用弹窗移除

# 定位弹窗显示代码
invoke-virtual {v0}, Landroid/app/AlertDialog;->show()V

# 破解方法:直接删除show()调用或在其前添加return-void
.method public showDialog()V
.registers 1
return-void # 直接返回,不执行弹窗
.end method

2.2 启动页广告跳过

方法一:直接返回

# 搜索"跳过"相关方法
.method public onCreate(Landroid/os/Bundle;)V
.registers 2
return-void # 结束广告Activity
.end method

方法二:修改启动Activity

<!-- AndroidManifest.xml中修改主入口 -->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

2.3 布局隐藏法

<!-- 在XML中隐藏广告视图 -->
android:visibility="gone" <!-- 完全隐藏 -->
android:width="0dp" <!-- 宽度设为0 -->
android:height="0dp" <!-- 高度设为0 -->

2.4 广告Activity移除

<!-- 在AndroidManifest.xml中删除以下广告Activity -->

<!-- 腾讯广告 -->
<activity android:name="com.qq.e.ads.ADActivity"/>

<!-- 百度广告 -->
<activity android:name="com.baidu.ads.ADActivity"/>

<!-- 谷歌广告 -->
<activity android:name="com.google.android.gms.ads.AdActivity"/>
<!-- 或 -->
<activity android:name="com.google.ads.ADActivity"/>

<!-- 支付宝H5支付 -->
<activity android:name="com.alipay.sdk.app.H5PayActivity"/>

三、会员与权限破解

3.1 通用会员破解(赋值法)

# 搜索方法名:isVip, getIsVip, isLogin, isPremium, isSubscribe, isBuy

# 标准破解模式
.method public isVip()Z
.registers 1
const/4 v0, 0x1 # 0x1 = true (会员)
return v0
.end method

# 去广告赋值
.method public isAdFree()Z
.registers 1
const/4 v0, 0x0 # 0x0 = false (无广告)
return v0
.end method

3.2 布尔值破解原理

# z代表布尔类型 (Z = boolean)
.field private isFlag:Z

# 0x1 = true, 0x0 = false
const/4 v0, 0x1 # 赋值为真
const/4 v0, 0x0 # 赋值为假

3.3 高级赋值示例

# 赋值会员到期时间
const-string v0, "2099-01-01"

# 赋值超长会员期限
const-wide v0, 0x1e0cb12f93dd60L # 269999年

# 赋值天数
const v0, 0x3bb2b0b # 700天

四、登录与验证绕过

4.1 登录状态破解

# 搜索方法名:isLogin, getEnable

.method public isLogin()Z
.registers 1
const/4 v0, 0x1 # 强制返回已登录
return v0
.end method

4.2 反跳转破解法

# 原代码:如果v3等于0则跳转到cond_45
if-eqz v3, :cond_45

# 破解后:如果v3不等于0则跳转(逻辑反转)
if-nez v3, :cond_45

# 或直接删除条件判断,改为无条件跳转
goto :cond_45

4.3 分支破解法

# 在验证分支顶部强制赋值
.method public checkLicense()V
.registers 2
const/4 v0, 0x1 # 强制成功
# 后续所有分支都会认为验证通过
...
.end method

五、签名验证绕过

5.1 通用签名绕过

# 搜索关键词:sign, signature, checkSign, verify, getPackageManager

# 修改getSignature方法
.method public getSignatures()Ljava/lang/String;
.registers 1
const-string v0, "testkey" # 返回测试签名
return-object v0
.end method

# 或直接返回验证成功
.method public checkSignature()I
.registers 1
const v0, 0x0 # 0 = VALID
return v0
.end method

5.2 华为签名特殊处理

# 在闪退的代码处添加
.registers 1
const v0, 0x0
return v0

六、游戏内购破解(高风险警告)

⚠️ 此部分内容涉及支付系统欺诈,仅供技术研究,严禁用于非法用途!

6.1 通用游戏支付破解

# 搜索方法名:onPayNotify, purchased, onBillingFinish

# Yodo1 SDK通用破解
# 定位到:Lcom/yodo1/android/sdk/helper/Yodo1PayHelper;->purchased(...)
# 在方法内插入:
const p1, 0x1 # 强制支付成功

6.2 各平台支付方法名

平台 关键方法名 破解策略
4399 notifydelivergoods 赋值为真
VIVO onReceiveServerCommand / paySuccessCallback 复制成功代码到失败分支
OPPO onCallCarrierPay / onSuccess 替换onFailure
腾讯 midaSpayCallback / onPayNotify 删除跳转,修改switch分支
咪咕 onResult / onChinaBillingResult 强制成功
联通 onPayResult / pyaResult 修改返回值
电信 paySuccess 覆盖失败代码
360 onFinished / onActivityResult 修改支付结果

6.3 支付关键词搜索

成功:succeed, success, VALID, paySuccess
失败:fail, failed, INVALID, payFailed
取消:cancel, payCancel

七、正则表达式批量修改

7.1 SharedPreferences布尔值破解

# 搜索模式
ip"\s*.*\s*invoke-interface \{.*\}, Landroid/content/SharedPreferences;->getBoolean\(Ljava/lang/String;Z\)Z\s*move-result (.*)

# 替换为
$0 \n const $1, 0x1

八、资源替换技巧

8.1 水印去除

  1. 提取APK中的图片资源
  2. 使用透明PNG图片替换水印文件
  3. 保持文件名和路径一致
  4. 重新打包

8.2 强制下载软件破解

# 搜索指定软件包名,替换为已安装应用包名(如QQ)
# 原代码:
const-string v0, "com.target.app"

# 破解后:
const-string v0, "com.tencent.mobileqq"

九、常见关键词速查表

9.1 会员/付费相关

isvip, getisvip, ispremium, issubscribe, isbuy, hasbought
getenable, islogin, isunlimit, showvip

9.2 广告相关

show_ad, showdialog, mdialog, adactivity
//ad, /ad/, adview, adlayout

9.3 游戏数值相关

gold, coin, money, cash, gem, diamond
health, life, hp, mp, attack, defence

9.4 支付相关

purchase, billing, pay, order, trade
notifydelivergoods, onpaynotify, onbillingfinish

十、安全加固对抗

10.1 加固识别与修复

常见加固方案:

  • 360加固
  • 腾讯乐固
  • 百度加固
  • 网易易盾

修复教程参考https://bbs.binmt.cc/thread-35986-1-1.html

10.2 签名校验定位

// Java层校验特征
getPackageManager()
getPackageInfo()
getSignatures()
verify()
checkSign()
signatures

十一、完整破解流程示例

案例:去广告+解锁VIP

# 1. 定位VIP检查
.method public isVip()Z
.registers 1
const/4 v0, 0x1 # 强制VIP
return v0
.end method

# 2. 定位广告显示
.method public showAd()V
.registers 1
return-void # 直接返回不显示
.end method

# 3. 修改AndroidManifest.xml
# 删除广告Activity声明

# 4. 绕过签名验证
.method public checkSignature()I
.registers 1
const v0, 0x0 # 返回验证成功
return v0
.end method

十二、重要提醒

  1. 备份原始APK:所有修改前务必做好备份
  2. 逐步测试:每次只修改一处,便于定位问题
  3. 权限清理:删除不必要的短信、支付权限
  4. 法律风险:商业软件破解可能面临法律诉讼
  5. 道德约束:尊重开发者劳动成果

技术无罪,但使用需负责。请将此知识用于正当目的!

十三、必备工具链推荐

13.1 核心工具

# 反编译/回编译
apktool d app.apk # 反编译
apktool b app -o new.apk # 回编译

# 签名工具
apksigner sign --ks keystore.jks new.apk

# 字节码编辑器
jadx-gui # Java代码查看
MT管理器 # 手机端Smali编辑

13.2 辅助工具

  • NP管理器:MT管理器替代品,支持Dex合并
  • Apktool M:在线反编译工具
  • GDA Pro:强大的反编译分析工具
  • Frida:动态Hook框架(无需修改APK)

十四、Smali高级指令详解

14.1 寄存器操作

# 寄存器类型
v0-v15 # 局部寄存器(16个)
p0-p3 # 参数寄存器(方法参数)

# 常用赋值
const/4 v0, 0x1 # 4位常量(-8到7)
const/16 v0, 0x10 # 16位常量
const v0, 0x1000 # 32位常量
const-wide v0, 0x100L # 64位常量(long/double)
const-string v0, "vip" # 字符串常量

# 数组操作
new-array v0, v1, [I # 创建大小为v1的int数组
fill-array-data v0, :array_0 # 填充数组数据

14.2 方法调用类型

invoke-virtual # 调用实例方法(有this)
invoke-static # 调用静态方法
invoke-direct # 调用私有/构造方法
invoke-super # 调用父类方法
invoke-interface # 调用接口方法

十五、APK结构深度解析

APK文件结构:
├── META-INF/ # 签名信息
│ ├── MANIFEST.MF
│ └── CERT.SF
├── AndroidManifest.xml # 清单文件(反编译后)
├── classes.dex # Dex字节码(可多个)
├── resources.arsc # 编译后的资源索引
├── res/ # 资源文件
│ ├── layout/ # 布局
│ ├── drawable/ # 图片
│ └── values/ # 字符串、颜色等
├── assets/ # 原始资源
└── lib/ # native库(.so)

关键文件定位技巧

  • 字符串res/values/strings.xml
  • 布局ID:在public.xml中查找对应ID
  • 图片资源:根据ID在res/drawable-*中查找

十六、代码混淆应对方案

16.1 混淆特征识别

# 混淆后的类名特征
Lcom/a/b/c/a; # 短类名
La/b/c/d/e/f; # 深层嵌套

# 字符串加密特征
invoke-static {v0}, Lcom/sdk/util;->a(Ljava/lang/String;)Ljava/lang/String;
move-result-object v0 # 解密后的字符串

16.2 反混淆技巧

  1. 字符串搜索:搜索URL、类名、关键词
  2. API定位:搜索ToastAlertDialog等系统API
  3. 资源ID跟踪:通过R$id.xxx定位代码位置
  4. 日志分析:搜索Log.d/e/i找到关键代码段

十七、动态调试技术(无需修改)

17.1 Frida Hook示例

// Hook isVip方法
Java.perform(function() {
var cls = Java.use('com.app.VipManager');
cls.isVip.implementation = function() {
console.log('[*] isVip() called, returning true');
return true; // 强制返回true
};
});

17.2 Xposed模块(需Root)

// Xposed钩子
findAndHookMethod("com.app.VipManager",
lpparam.classLoader,
"isVip",
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
param.setResult(true); // 直接返回结果
}
});

十八、常见错误排查

18.1 安装失败问题

# 错误:INSTALL_PARSE_FAILED_NO_CERTIFICATES
# 解决:重新签名
apksigner sign --ks keystore.jks app.apk

# 错误:INSTALL_FAILED_INVALID_APK
# 解决:检查AndroidManifest.xml语法

# 错误:INSTALL_FAILED_UPDATE_INCOMPATIBLE
# 解决:卸载原版后安装

18.2 闪退问题排查

# 1. 检查日志
adb logcat | grep "FATAL"

# 2. 常见闪退原因
- 签名校验未绕过
- 删除了必要的方法调用
- 寄存器数量不匹配(.registers)
- 资源ID未找到

# 3. 快速修复:在onCreate首行添加
.method protected onCreate(Landroid/os/Bundle;)V
.registers 2
return-void # 直接返回测试是否还闪退
.end method

18.3 寄存器错误修复

# 错误:register v10 exceeds register count
# 解决:增加.registers数量
.method public test()V
.registers 12 # 至少要比使用的最大寄存器大1
# 使用v0-v11
.end method

十九、资源ID定位技巧

19.1 从布局到代码

<!-- res/layout/activity_main.xml -->
<Button android:id="@+id/btn_vip"/>

<!-- 反编译后ID在public.xml -->
<public type="id" name="btn_vip" id="0x7f0800a1" />

<!-- 在Smali中引用 -->
const v1, 0x7f0800a1 # 加载ID
invoke-virtual {p0, v1}, Lcom/app/MainActivity;->findViewById(I)Landroid/view/View;

19.2 快速查找工具

# 搜索资源引用
grep -r "0x7f0800a1" smali/

# 搜索字符串
grep -r "去开通VIP" smali/

二十、加固与反加固

20.1 常见加固方案

加固厂商 特征 脱壳工具
360加固 libjiagu.so BlackDex, FART
腾讯乐固 libshell.so dexHunter
百度加固 libbaiduprotect.so dcc工具
网易易盾 libnesec.so Frida脚本

20.2 通用脱壳步骤

  1. 内存Dump:在运行时从内存中Dump Dex
  2. 修复DEX:修复Dump出的Dex文件头
  3. 替换资源:将原APK中的classes.dex替换
  4. 重新打包:使用apktool重新编译

二十一、反破解检测绕过

21.1 常见检测项

# 1. 调试检测
invoke-static {}, Landroid/os/Debug;->isDebuggerConnected()Z
move-result v0
if-nez v0, :cond_detected # 检测到调试

# 破解:强制返回false
const/4 v0, 0x0
return v0

# 2. Root检测
invoke-static {}, Lcom/sdk/RootCheck;->isRoot()Z
# 破解同上

# 3. 模拟器检测
invoke-static {}, Lcom/sdk/EmulatorCheck;->isEmulator()Z
# 破解同上

21.2 签名校验深度绕过

# 多重校验应对方案
# 在Application的attachBaseContext中插入
.method protected attachBaseContext(Landroid/content/Context;)V
.registers 2
invoke-super {p0, p1}, Landroid/app/Application;->attachBaseContext(Landroid/content/Context;)V
return-void # 跳过所有初始化校验
.end method

二十二、实战:完整破解流程案例

案例:某视频App(VIP+去广告)

步骤1:定位VIP校验

# 搜索关键词
grep -r "isVip" smali/ | grep ".method"
# 结果:smali/com/app/UserManager.smali

步骤2:修改VIP方法

# 原代码
.method public isVip()Z
.registers 2
iget-boolean v0, p0, Lcom/app/UserManager;->vipStatus:Z
return v0
.end method

# 破解后
.method public isVip()Z
.registers 2
const/4 v0, 0x1
return v0
.end method

步骤3:移除广告Activity

<!-- AndroidManifest.xml -->
<!-- 删除 -->
<activity android:name="com.google.android.gms.ads.AdActivity"/>

步骤4:屏蔽广告加载

# 搜索showAd方法
.method public showAd()V
.registers 1
return-void # 直接返回
.end method

步骤5:绕过签名校验

# 搜索signatures
.method public getSignatures()[Landroid/content/pm/Signature;
.registers 2
const/4 v0, 0x0
return-object v0 # 返回null
.end method

步骤6:重新打包测试

apktool b app -o cracked.apk
apksigner sign --ks mykey.jks cracked.apk
adb install cracked.apk

二十三、法律与道德边界

23.1 合法使用场景

个人学习研究安全漏洞分析兼容性修改(自己设备)开源软件修改

23.2 非法行为

破解后分发盗取付费内容绕过安全机制获利恶意植入代码

23.3 自我保护原则

  1. 不传播破解版
  2. 不用于商业目的
  3. 不侵犯隐私数据
  4. 保留原始版权信息

二十四、快速查询手册

24.1 修改对照表

目的 搜索关键词 修改方式 Smali代码
解锁VIP isVip/isLogin 赋值 const/4 v0, 0x1
去广告 showAd/ADActivity 删除/return-void return-void
绕过登录 isLogin/getUser 强制true const/4 v0, 0x1
跳过启动页 SplashActivity 修改LAUNCHER 修改Manifest
去更新 checkUpdate 删除调用 return-void
无限资源 coin/gold 赋值最大值 const v0, 0x7fffffff

24.2 正则表达式集合

# 获取布尔值
invoke-interface \{.*\}, Landroid/content/SharedPreferences;->getBoolean\(.*\)Z\s*move-result (.*)

# 获取字符串
invoke-interface \{.*\}, Landroid/content/SharedPreferences;->getString\(.*\)Ljava/lang/String;\s*move-result-object (.*)

# 替换为
$0 \n const $1, 0x1 # 布尔
$0 \n const-string $1, "vip" # 字符串

二十五、结语

逆向工程是一门需要耐心和实践的技术。建议从简单的开源APK开始练习,逐步掌握Smali语法和Android运行机制。记住:

技术本身中立,但使用者的选择决定了其价值。

请始终在法律和道德框架内使用这些技术,将其用于学习、安全研究和正当的兼容性改进。

正文完
 0
评论(没有评论)
验证码