| name | performing-dynamic-analysis-of-android-app |
| description | 使用 Frida、Objection 和 Android Debug Bridge 对 Android 应用进行运行时动态分析, 在执行过程中观察应用行为、拦截函数调用、修改运行时值,并识别静态分析遗漏的漏洞。 适用于测试 Android 应用的运行时安全缺陷、Hook 敏感方法、绕过客户端保护措施 或分析混淆应用。适合 Android 动态分析、运行时 Hook、Frida Android 插桩或实时应用行为分析相关请求。
|
| domain | cybersecurity |
| subdomain | mobile-security |
| author | mahipal |
| tags | ["mobile-security","android","frida","dynamic-analysis","owasp-mobile","penetration-testing"] |
| version | 1.0.0 |
| license | Apache-2.0 |
执行 Android 应用动态分析
适用场景
适用于以下情况:
- 静态分析结果需要在实际 Android 设备上进行运行时验证
- 目标应用使用了混淆技术(DexGuard、自定义打包器)导致静态分析效果有限
- 测试需要观察实际 API 调用、解密数据或运行时生成的值
- 评估 Root 检测、防篡改检测或反调试实现
不适用场景:未经授权不得在生产环境中使用——动态插桩可能改变应用行为并触发安全告警。
前置条件
- 已 root 的 Android 设备或模拟器(Genymotion、带可写系统的 Android Studio AVD)
- 设备上安装了与架构匹配的 Frida 服务端(arm64、x86_64)
- Python 3.10+ 及
frida-tools 和 objection 包
- 已配置 ADB 且设备已连接
- 目标 APK 已安装在设备上
工作流程
步骤 1:在 Android 设备上设置 Frida 服务端
adb shell getprop ro.product.cpu.abi
adb push frida-server-16.x.x-android-arm64 /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &
frida-ps -U
步骤 2:枚举应用攻击面
frida-ps -U -a
objection --gadget com.target.app explore
android hooking list activities
android hooking list services
android hooking list receivers
android hooking list classes
android hooking search classes com.target.app
步骤 3:Hook 敏感方法
android hooking watch class com.target.app.auth.LoginManager
android hooking watch class_method com.target.app.auth.LoginManager.authenticate --dump-args --dump-return
android hooking watch class javax.crypto.Cipher --dump-args
android hooking watch class java.security.MessageDigest --dump-args
android hooking watch class okhttp3.OkHttpClient --dump-args
android hooking watch class java.net.URL --dump-args
步骤 4:编写自定义 Frida 脚本进行深度分析
Java.perform(function() {
var Cipher = Java.use("javax.crypto.Cipher");
Cipher.doFinal.overload("[B").implementation = function(input) {
var mode = this.getAlgorithm();
console.log("[Cipher] 算法: " + mode);
console.log("[Cipher] 输入: " + bytesToHex(input));
var result = this.doFinal(input);
console.log("[Cipher] 输出: " + bytesToHex(result));
return result;
};
function bytesToHex(bytes) {
var hex = [];
for (var i = 0; i < bytes.length; i++) {
hex.push(("0" + (bytes[i] & 0xFF).toString(16)).slice(-));
}
hex.();
}
});
frida -U -f com.target.app -l hook_crypto.js --no-pause
步骤 5:绕过 Root 检测
Java.perform(function() {
var RootBeer = Java.use("com.scottyab.rootbeer.RootBeer");
RootBeer.isRooted.implementation = function() {
console.log("[RootBeer] isRooted() 已绕过");
return false;
};
var File = Java.use("java.io.File");
var originalExists = File.exists;
File.exists.implementation = function() {
var path = this.getAbsolutePath();
var rootPaths = ["/system/app/Superuser.apk", "/system/xbin/su",
"/sbin/su", "/system/bin/su", "/data/local/bin/su"];
if (rootPaths.indexOf(path) >= 0) {
console.log("[Root] 已阻断检测: " + path);
;
}
originalExists.();
};
{
= .();
.();
} (e) {}
});
步骤 6:运行时分析网络通信
Java.perform(function() {
try {
var OkHttpClient = Java.use("okhttp3.OkHttpClient");
var Interceptor = Java.use("okhttp3.Interceptor");
var Chain = Java.use("okhttp3.Interceptor$Chain");
console.log("[OkHttp] 正在监控网络请求...");
var Request = Java.use("okhttp3.Request");
Request.url.implementation = function() {
var url = this.url();
console.log("[OkHttp] URL: " + url.toString());
return url;
};
} catch(e) {
console.log("[OkHttp] 未找到,尝试 HttpURLConnection");
}
var = .();
..(). = () {
.( + .());
.();
};
});
步骤 7:提取解密数据和机密
objection --gadget com.target.app explore
android keystore list
android keystore dump
android heap search instances com.target.app.model.User
android heap evaluate <handle> "JSON.stringify(clazz)"
memory search "password" --string
memory search "api_key" --string
核心概念
| 术语 | 定义 |
|---|
| 动态插桩 | 通过向运行中的进程注入代码,在运行时修改应用行为 |
| 方法 Hook | 替换或包装函数实现,以拦截参数和返回值 |
| Frida 服务端 | 运行在目标设备上的守护进程,接收来自主机的插桩命令 |
| Dalvik/ART 运行时 | Android 运行时环境;Frida 在 ART 级别 Hook Java/Kotlin 方法 |
| 堆检查 | 检查应用内存堆中的活跃对象,以提取运行时数据 |
工具与系统
- Frida:动态插桩工具包,用于向原生 Android 进程注入 JavaScript
- Objection:高级 Frida 封装,提供预置的 Android 和 iOS 安全测试命令
- frida-trace:自动化方法追踪工具,用于快速侦察应用行为
- Drozer:Android 安全评估框架,用于测试 IPC 和导出组件
- Android Studio Profiler:CPU、内存和网络活动的运行时监控
常见问题
- Frida 版本不匹配:设备上的 Frida 服务端必须与主机上的 frida-tools 版本匹配,版本不匹配会导致连接失败。
- 反 Frida 检测:某些应用通过检查 Frida 服务端进程、扫描内存中的 Frida 特征或监控
/proc/self/maps 来检测 Frida。使用 Frida Gadget 注入或自定义服务端构建版本。
- 混淆类名:应用 ProGuard/R8 后,类名和方法名会被缩短(如
a.b.c.d())。使用 android hooking search classes 发现实际运行时名称。
- 多 DEX 应用:跨多个 DEX 文件的大型应用可能在启动时未加载所有类。在应用完全初始化后,Hook 类加载器或使用
Java.enumerateLoadedClasses()。