百趣云 百趣云的博客

Frida hook WebView:监控 loadUrl 与 JSBridge 的完整方案

为什么要监控 WebView

混合开发 App 的核心逻辑经常不在 Java 层而在 H5 里:登录态的传递、支付回调、加密参数的生成,都通过 WebView 的 JSBridge 在 native 和 H5 之间穿梭。只 hook Java 层会漏掉一半的信息流。监控 WebView 要抓三个点:loadUrl(加载了什么页面)、JSBridge(双向通信内容)、evaluateJavascript(执行了什么 JS)

监控 loadUrl 与页面加载

Java.perform(function() {
    var WebView = Java.use('android.webkit.WebView');

    WebView.loadUrl.overload('java.lang.String').implementation = function(url) {
        console.log('[loadUrl] ' + url);
        // javascript: 伪协议的调用也会走这里,JS 注入一目了然
        this.loadUrl(url);
    };

    WebView.evaluateJavascript.implementation = function(script, cb) {
        console.log('[evalJS] ' + script.substring(0, 500));
        this.evaluateJavascript(script, cb);
    };

    // postUrl 带 body,别漏
    WebView.postUrl.implementation = function(url, data) {
        console.log('[postUrl] ' + url + ' data=' + Java.use('java.lang.String').$new(data));
        this.postUrl(url, data);
    };
});

监控 JSBridge:双向都要抓

JSBridge 的本质是 @JavascriptInterface 注解暴露的 Java 对象。监控分两步:

第一步:找出 bridge 对象名

var WebView = Java.use('android.webkit.WebView');
WebView.addJavascriptInterface.implementation = function(obj, name) {
    console.log('[addJSInterface] name=' + name + ' class=' + obj.getClass().getName());
    this.addJavascriptInterface(obj, name);
};

跑一次 App 就知道 H5 里 window.xxx 对应哪个 Java 类。

第二步:hook bridge 类的所有方法

function hookBridge(className) {
    var cls = Java.use(className);
    cls.class.getDeclaredMethods().forEach(function(m) {
        var mName = m.getName();
        cls[mName].overloads.forEach(function(overload) {
            overload.implementation = function() {
                var args = Array.from(arguments).map(String).join(', ');
                console.log('[JSBridge] ' + className + '.' + mName + '(' + args.substring(0, 300) + ')');
                var ret = this[mName].apply(this, arguments);
                if (ret) console.log('[JSBridge ret] ' + String(ret).substring(0, 300));
                return ret;
            };
        });
    });
}

反向监控:H5 回调 native 的 hidden 通道

很多 App 的 JSBridge 是"伪协议 + shouldOverrideUrlLoading"实现的(H5 跳转 jsbridge://method?params),这种不走 addJavascriptInterface,要 hook WebViewClient:

var WebViewClient = Java.use('android.webkit.WebViewClient');
WebViewClient.shouldOverrideUrlLoading.overload('android.webkit.WebView', 'java.lang.String').implementation = function(view, url) {
    if (url.indexOf('jsbridge://') === 0 || url.indexOf('js://') === 0) {
        console.log('[Bridge-URL] ' + decodeURIComponent(url));
    }
    return this.shouldOverrideUrlLoading(view, url);
};

精髓:四个实战要点

  1. 多 WebView 实例。App 里可能有多个 WebView(主页面、广告、支付各一个),hook 是类级的所以全覆盖,但日志里要带上 this.hashCode() 区分实例,否则分不清哪条日志是哪个页面的。
  2. X5/UC 内核的类名不同。腾讯 X5 内核是 com.tencent.smtt.sdk.WebView,UC 是 com.uc.webview.export.WebView,方法名类似但包名不同。逆向前先确认 App 用的哪个内核(jadx 搜 import)。
  3. 加密参数常在 Bridge 里生成。很多 App 的 H5 签名是 H5 调 native bridge 算的——监控 bridge 方法的输入输出,签名算法的入参出参直接到手,比逆 SO 快得多。
  4. evaluateJavascript 是回调注入点。想主动调 H5 的 JS 函数(比如让 H5 的签名函数给你算签名),用 evaluateJavascript 注入调用代码,配合 handler 拿返回值——这是"借鸡生蛋"式签名服务的实现基础。

总结

  1. WebView 监控三件套:loadUrl、addJavascriptInterface、evaluateJavascript
  2. 伪协议型 Bridge 要 hook shouldOverrideUrlLoading
  3. X5/UC 内核实类名不同,先确认内核再写 hook
  4. Bridge 方法是签名算法的富矿,优先审查

交流微信:run1255

By 百趣云 阅读量:2 On