前言

最近学习学习安卓逆向,网上随便找了个app练习下,这次主要是纯java层的分析(native层分析不来)。

初步分析

直接把app丢到jadx中反编译看下

image-20241114204707598

好家伙,随便找个就直接是flutter写的,正当我准备放弃时,发现com包下还是能看出有许多广告SDK的。

image-20241114204838782

大致看了下AndroidManifest.xml 也发现了很多广告Activity

这些Adxxxx的应该都是

image-20241114205015377

app虽然是flutter写的,但这些sdk还是在java层,所以调用这些广告sdk的方法应该也在java层,所以还是可以破解绕广告的。

flutter调用java方法

MainActivity中注册了 Flutter 插件

image-20241114205437215

Flutter 可以通过 平台通道(Platform Channels) 与 Java 进行通信。平台通道是 Flutter 提供的一种机制,使得 Dart 代码能够与 Android 的 Java(或 Kotlin)代码互相通信。通过平台通道,Flutter 可以调用原生平台的功能,或者反过来,由原生平台调用 Flutter 的功能。

具体可以参考https://docs.flutter.dev/platform-integration/platform-channels

https://juejin.cn/post/6844904158349230088

这里有个类比较关键,io.flutter.plugins.GeneratedPluginRegistrant,这个类是根据插件配置文件自动生成的。利用flutter插件就可以做到flutter与java的通信,也就是这里是我们找到广告调用点的关键。

全局搜索 GeneratedPluginRegistrant 我们定位到

image-20241114210139656

这里添加了许多插件,通过这些插件名字我们发现了一个比较可疑的类

image-20241114210354835

名字是 com.windmill.windmill_ad_plugin.WindmillAdPlugin ,有 ad 字段,很可能就是用于广告加载的插件

点进去看下,最终添加的插件是 com.windmill.windmill_ad_plugin.WindmillAdPluginDelegate

image-20241114210533084

com.windmill.windmill_ad_plugin.WindmillAdPluginDelegate 中定位到 onMethodCall 方法,这里就是最终dart代码调用java(kotlin)的地方了

image-20241114210934714

这里代码逻辑比较多,其实有个技巧就是可以直接网上搜下这些广告sdk的文档

比如这里我们明显可以发现这些有广告sdk特征的类

image-20241114211108861

网上搜下

image-20241114211144496

直接就有现成的文档 https://doc.sigmob.com/ToBid%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/SDK%E9%9B%86%E6%88%90%E8%AF%B4%E6%98%8E/Android/%E5%88%9D%E5%A7%8B%E5%8C%96%E8%AF%B4%E6%98%8E/

image-20241114211229609

直接搜索 .startWithAppId 快速定位到广告初始化的地方

image-20241114211400038

setupSdkWithAppId 方法正好是在onMethodCall 方法中调用的

image-20241114211446312

所以这里直接把setupSdkWithAppId方法中 WindMillAd.sharedAds().startWithAppId 的代码注释掉就可以了

这里给出对应的frida脚本

Java.perform(function() {

    let WindmillAdPluginDelegate = Java.use("com.windmill.windmill_ad_plugin.WindmillAdPluginDelegate");
    WindmillAdPluginDelegate["setupSdkWithAppId"].implementation = function (methodCall, result) {
        console.log(`WindmillAdPluginDelegate.setupSdkWithAppId is called: methodCall=${methodCall}, result=${JSON.stringify(result)}`);
        // console.log(JSON.stringify(methodCall));
        console.log(methodCall.method.value);
        // console.log(JSON.stringify(result));
        let resultInstance = Java.cast(result, Java.use("io.flutter.plugin.common.MethodChannel$Result"));
        resultInstance.success(null);
    }

});

考虑在非root环境下持久生效,可以直接改smali代码(这个app刚好没做签名校验,改起来也比较方便)

直接加个goto把中间 WindMillAd.sharedAds().startWithAppId 的跳过就可以了

image-20241114211841334

image-20241114211952410

然后回编译,签名,安装。反编译回编译修改smali代码可以使用apktool,或者直接mt、np管理器改。

完美运行

image-20241114212429649