动态运行时分析:用Frida和Xposed Hook关键API

说实话,静态分析能帮你找到很多漏洞,但真正让我头皮发麻的,往往是那些只在运行时才暴露出来的问题。我记得有一次,一个App在静态扫描时干干净净,结果一上线就被爆出Activity劫持——原来攻击者利用了动态注册的Intent Filter,静态代码里根本看不出来。

所以,动态运行时分析,说白了就是给App装上“监控摄像头”。今天我就带你看看,怎么用Frida和Xposed这两个神器,实时监控组件调用和数据流。

为什么需要动态分析?

静态分析有个硬伤:它只能看到代码,看不到运行时的真实行为。你想想看,一个Activity到底被谁调用了?Intent里携带了什么敏感数据?Content Provider的URI在运行时被拼接过吗?这些问题,光看代码是回答不了的。

我个人的习惯是:先静态扫一遍,找出可疑点,然后用动态分析去验证。这样既高效,又不会漏掉运行时才触发的漏洞。

Frida:轻量级动态插桩

Frida是我最常用的工具。它不需要修改App本身,直接注入JavaScript代码就能Hook任意函数。嗯,这里要注意:Frida需要设备有root权限,或者使用Frida Gadget注入。

Hook Activity的启动流程

Activity劫持的核心,就是攻击者能拦截或伪造Intent。我们可以Hook startActivity 来监控所有Activity的启动请求:

// Frida脚本:监控startActivity调用
Java.perform(function() {
    var Activity = Java.use('android.app.Activity');
    var Intent = Java.use('android.content.Intent');

    Activity.startActivity.overload('android.content.Intent').implementation = function(intent) {
        console.log('[+] startActivity 被调用');
        console.log('    Intent Action: ' + intent.getAction());
        console.log('    Intent Data: ' + intent.getDataString());
        console.log('    Intent Component: ' + intent.getComponent());

        // 检查是否有隐式Intent
        if (intent.getComponent() === null) {
            console.warn('[!] 警告:隐式Intent,可能被劫持!');
        }

        // 继续原始调用
        this.startActivity(intent);
    };
});

我在项目中遇到过,有些App会动态设置Intent的Flag,比如 FLAG_ACTIVITY_NEW_TASK。这种Flag如果被恶意利用,攻击者可以把你的Activity启动到自己的任务栈里,实现劫持。所以,我一般还会Hook setFlags 方法:

Intent.setFlags.implementation = function(flags) {
    console.log('[+] setFlags 被调用: ' + flags);
    if (flags & 0x10000000) { // FLAG_ACTIVITY_NEW_TASK
        console.warn('[!] 检测到FLAG_ACTIVITY_NEW_TASK,注意劫持风险');
    }
    return this.setFlags(flags);
};

监控Content Provider的数据流

Provider数据泄露,说白了就是URI被恶意拼接或者权限检查不到位。我们可以Hook ContentResolver.query 来监控所有数据库查询:

Java.perform(function() {
    var ContentResolver = Java.use('android.content.ContentResolver');

    ContentResolver.query.overload('android.net.Uri', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String').implementation = function(uri, projection, selection, selectionArgs, sortOrder) {
        console.log('[+] query 被调用');
        console.log('    URI: ' + uri.toString());
        console.log('    Selection: ' + selection);

        // 检查URI是否包含敏感关键字
        var uriStr = uri.toString();
        if (uriStr.contains('password') || uriStr.contains('token')) {
            console.warn('[!] 警告:查询可能包含敏感数据!');
        }

        return this.query(uri, projection, selection, selectionArgs, sortOrder);
    };
});
小技巧: 我习惯在Frida脚本里加上堆栈打印,这样能知道是谁调用了这些敏感API。用 Java.use('android.util.Log').getStackTraceString(new Exception()) 就能拿到调用栈。

Xposed:系统级Hook框架

Xposed和Frida最大的区别是:Xposed是持久化的,修改后重启App依然生效。适合做长期监控。但Xposed需要刷入框架,对设备要求更高。

Hook ActivityManagerService

Activity的启动最终会走到系统服务 ActivityManagerService。Hook这个服务,能监控到所有App的Activity启动:

// Xposed模块:监控Activity启动
public class MonitorActivity extends IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
        if (!lpparam.packageName.equals("com.android.server")) return;

        findAndHookMethod(
            "com.android.server.am.ActivityManagerService",
            lpparam.classLoader,
            "startActivity",
            Intent.class,
            String.class,
            ... // 其他参数
            new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) {
                    Intent intent = (Intent) param.args[0];
                    XposedBridge.log("[AMS] startActivity: " + intent.toString());
                }
            }
        );
    }
}

我曾经用Xposed抓过一个恶意App,它通过反射调用 ActivityManagerNative.getDefault() 来绕过权限检查。这种手法在静态代码里几乎看不出来,但运行时一Hook就原形毕露了。

数据流追踪实战

光Hook API还不够,你得把数据流串起来。我一般会做三件事:

  1. 标记敏感数据来源:比如从 getIntent().getData() 获取的URI
  2. 追踪数据传递路径:看它经过了哪些Activity、Service、Provider
  3. 检查最终使用点:比如是否被拼接到SQL查询里,或者通过 startActivity 发送出去

下面这张图是我自己总结的组件调用与数据流监控框架:

组件调用与数据流监控框架 数据源 Intent / URI / SharedPreferences Hook层(Frida / Xposed) startActivity / query / openFile / insert 监控点 Intent劫持检测 / Provider数据泄露检测 / 权限绕过检测 分析输出 日志 / 告警 / 堆栈信息 数据流方向

避坑指南

我曾经踩过的坑:
  • Frida脚本里忘记处理 overload 歧义,导致Hook不生效。一定要用 overload('参数类型') 明确指定。
  • Xposed模块里直接修改了系统服务的返回值,结果手机变砖。记住:监控为主,修改为辅,生产环境慎用。
  • Hook ContentProvider时,没考虑多线程并发,导致日志乱序。加个时间戳或者线程ID就能解决。

总结

动态运行时分析,说白了就是给App做“实时体检”。Frida适合快速验证,Xposed适合长期监控。我个人建议:先用Frida做一轮快速扫描,发现可疑点后,再用Xposed做深度追踪。

记住一点:Hook不是目的,理解数据流才是。你只有知道数据从哪里来、经过哪里、最终去了哪里,才能真正堵住漏洞。

核心要点回顾:

  • Hook startActivitysetFlags 监控Activity劫持
  • Hook ContentResolver.query 监控Provider数据泄露
  • Frida适合临时调试,Xposed适合持久监控
  • 始终追踪数据流,不要只看单个API调用

公众号:蓝海资料掘金营,微信deep3321