讨论 第三方「minebbs安卓版」行为分析

Nico6719

【Lv:5】

管理成员
版主
译者
开发者
正式会员
注册
2020/08/13
消息
1,268
金粒
32.35金粒
[MD] ## 背景 逛论坛时看到一个举报帖([主题 #50425](https://www.minebbs.com/threads/minebbs.50425/)),有坛友说装了【软件资源 - minebbs安卓版】之后手机里蹦出色情广告。我点进去看了一眼,顺手把安装包下下来。 在装的时候系统就报了毒,但是我还是按了无视风险继续安装。打开后一开始挺正常,就是个套壳浏览器在加载论坛页面。过了没多久,右下角先冒出两个透明的方框,又过了一会儿,方框里加载出 2 个违规广告)。 这倒让我来了兴趣,于是乎我把 APK 传到电脑上做静态分析和逆向,并发现了一些有意思的地方。 ## 分析与逆向结果 ### 1. 样本概况 包名 `com.minebbs.www`,versionName 1.0 / versionCode 1,compileSdk 31。签名证书别名 BLACKACE,插件里还捎带了一个 `blackace.jks` 密钥库——签名密钥库这种东西随安装包一起发出来,要么打包流程糙,要么这套东西本来就是套模板批量产的。查了下证书,主体字段 C/ST/L/O/OU/CN 全填的 "blackace",自签,有效期直接签到 2124 年,SHA-256 指纹 `BC:A4:68:4E:52:B2:CE:57:42:94:9B:20:27:6C:A6:AA:06:91:??:08:C1:2E:10:E3:C7:3D:C0:E7:85:99:C9:1E`。 架构上是个 WebView 壳套插件化框架:壳层代码在 `app.blackace.*`(SplashActivity 起来转到 WebActivity 加载论坛页),插件框架用的 `top.niunaijun.shadow`。Manifest 里注册了 P0 到 P9 共十组插件容器,摆明了按多插件平台设计的,不是给某一个广告插件临时搭的台子。宿主 dex 约 8MB,里面塞了个主插件 `assets/1`(1.36MB 的插件 APK,dex 2.1MB),另有 `assets/config.json`(十六进制密文)和 `assets/ads-nl.txt`(广告拦截规则表)。包里的字符串大部分过了 `a1.a.B(byte[],byte[])` 循环 XOR 混淆,批量还原出来 271 条。 有个细节值得单独说:整个包就 `libmmkv.so` 一个 native 库,没有任何加固壳。所以"广告 SDK 零命中"不是被壳挡住扫不进去,是包里真没有。 样本指纹放这儿,手里还有这个包的可以对一下:SHA-256 `fc455a0c270a300afdb02c4d15dda584ce131cef74bf4c3d0c8c41baa724961b`,MD5 `fb5147cf3849b90473f02a269de998a9`,大小 6,535,922 字节。 还有个不好解释的地方:targetSdkVersion 停在 28(minSdk 21),目标版本还留在 Android 9。这意味着 Android 10 之后的分区存储、包可见性那套管控对它统统不生效。 ### 2. 配置解密 `config.json` 是 DES 密文,密钥 `helloace`(AppConfig 里写死的,DES/ECB),解开是这么个东西: ``` {"appId":"4dc788c8ebb8554fc1f???3f6ebddd2c","enableSplash":false,"webUrl":"https://www.minebbs.com","isProxy":false} ``` 工具类 `DesUtils` 里还有一条 DES 密钥常量 `microsoft.com`(取前 8 字节)。配置都存在 MMKV 里(`internal_config` / `internal_config_content` / `proxy_config` / `app_config`),其中 `InternalConfig` 提供 `getInjectJs()`、`getPlugins()`、`getOSSConfig()` 这几个口子,OSS 的 bucket/endpoint/id/secret 一应俱全——远程配置一到手,注入什么脚本、下发哪个插件、去哪下载,全由它分发。 ### 3. 广告 SDK 零命中,但三条远程广告通道都在 前面说了包里一个广告 SDK 都没有。没有,是因为广告代码压根不随包走: (1)网页脚本注入。`c2/d.java` 的 `onPageFinished` 会在每个页面加载完之后,把 `AppLib.getInjectJs()` 和 `AppLib.getInjectJsList()` 拿到的内容拼起来 `evaluateJavascript` 注入页面,这两个口子的内容来自远程配置的 `js` / `jsList` 字段。列表里以 http 开头的条目更直接,包装成 `<script src>` 就往页面里塞,注入完还打个 `web_client_inject` 埋点。顺带一提,manifest 里 `usesCleartextTraffic="true"` 是开着的,配上"http 地址直接当脚本加载"这种写法,注入内容在传输链路上就有被替换的余地,风险不只是"作者想投什么"。 (2)广告插件云端下发。`PluginManager` 里硬编码了插件键 `ad-plugin`(本地文件名代号 "2"),这个文件不在安装包的 assets 里,运行时按远程插件清单(`PluginBean`:`urls[]` 加 `md5`)从云端下载、校验 MD5 之后动态加载。日志原文都能看到:「未安装插件,开始安装: ad-plugin」。 (3)开屏广告位。`SplashConfig` 带 `adId`、`showTime`、`url`、`actionType`、`actionExt` 一组字段,开关和内容同样远程说了算(我手里这个样本本地配置是 `enableSplash: false`,槽位留着,没开)。 ### 4. 现象还原:两个透明方框 → 2 个违规广告 回头看手机上那个时序——先出空框、内容后到——跟这套机制正好对得上:注入脚本或广告插件先在右下角搭出悬浮容器,这时候素材还没到,看上去就是个透明方框;远程素材异步拉回来,广告才画上去。两个框、两个广告,对应两个广告位。至于内容是脚本注入画的还是下发插件画的,包里没有浮窗原生代码,两条通道又都在服务端手里,光看包体分不出来。 它加载的网页本身就是 minebbs.com,网页自己的广告位也会在客户端里显示。但结合"右下角悬浮、异步加载、内容违规"这几个特征,前两条通道的可能性大得多。 ### 5. 动态代码加载与 APK 安装能力 插件机制本身就是任意代码执行:`PluginManager` 按远程清单从 OSS(`getOSSConfig()` 里 bucket/endpoint/id/secret 齐全)拉插件下来动态加载,服务端想下发什么代码都行。下载失败有重试,启动失败会拉黑——「所有下载失败,跳过该插件」「该版本启动失败已拉黑」这类日志都在。 装 APK 的口子也有:`HostLib.requestInstall(File)`,配着 `REQUEST_INSTALL_PACKAGES` 权限,走 `ACTION_VIEW` 加 `application/vnd.android.package-archive`,`file://` 和 FileProvider 两条路径都备好了。 另外还有个常驻的前台代理 `ProxyService`(通知渠道 `channel_black_ace_foreground`,显示名 "BlackAce Proxy"),里面是 `ace_proxy` 核心加 geoip/geosite 路由数据,配着 `assets/ads-nl.txt` 那份 154,736 行的拦截规则和本地代理(127.0.0.1)。这份规则表我看了下文件头,来自 blocklistproject 的 Ads List——它确实在老老实实拦网页广告,就是拦不住自己注入的那份,想想还有点讽刺。 ### 6. 遥测与日志上报 `getDeviceId()` 采的是 `android_id`。`HttpInterceptor` 给每个请求都附一串指纹头:`did` / `ak` / `sv` / `sn` / `dv` / `dp` / `hv` / `lang` / `region` / `pyv` / `pykv` / `pv`。 事件走 `sendEvent` → `/a/lr`,端点 `https://testapp-blackace.blackace.app`(另有 `/a/jc` `/a/nb` `/a/pc` `/a/gj` `/a/tf` 这些路径,分析期间全部 521,源站挂了)。日志上传是 `packetLogFile()` 把 `logcat.txt` 和 `python.log` 打成 `log.zip` 交给 `UploadUtils`,上传路径模板里连 `apk/%s/%s.apk`、`audio/%s/%s.mp3` 这种都有。 ### 7. 权限清单 Manifest 声明了:INTERNET、ACCESS_WIFI_STATE / ACCESS_NETWORK_STATE / CHANGE_WIFI_STATE / CHANGE_NETWORK_STATE、FOREGROUND_SERVICE、REQUEST_INSTALL_PACKAGES、WRITE_EXTERNAL_STORAGE、QUERY_ALL_PACKAGES、ACCESS_COARSE_LOCATION / ACCESS_FINE_LOCATION / ACCESS_LOCATION_EXTRA_COMMANDS、NEARBY_WIFI_DEVICES、RECORD_AUDIO、CAMERA。 短信、通话记录、通讯录倒是没要。但对一个"论坛浏览器"来说,相机、录音、精确定位、装应用、枚举全部已装应用,哪一项都超出它该管的范围。另外 `allowBackup` 是开着的,旧版 Android 上连 `adb backup` 都能把应用数据整包拖出来——取证比想象中容易,下面那些留痕我就是这么翻出来的。 ## 结论 1. 广告不是安装包里自带的广告代码画出来的。主流广告 SDK 一个都没扫到(AdMob、穿山甲、优量汇、快手、Unity、AppLovin、InMobi 这些全比对过),统计和推送 SDK 也是零。 2. 但广告能力是架构上留好的口子:远程脚本注入、广告插件云端下发、开屏广告位,三条通道都攥在服务端手里,不发版就能随时换内容。今天塞色情广告,明天换什么都有可能。 3. 真正该警惕的不是广告,是它整套"运行时换代码"的能力——云端下发插件动态加载、弹窗装 APK、采设备指纹、打包上传日志。广告只是这套东西最轻的用法。 --- *以上内容基于静态分析与逆向得出,内容仅代表个人观点。* [/MD]
 

附件

  • 1792475921094.webp
    1792475921094.webp
    174 KB · 查看: 4
  • 1792475956273.webp
    1792475956273.webp
    413.1 KB · 查看: 4
最后编辑:
没想到在minebbs里也能看到这样的分析帖,除了看起来用ai,辅助过,但也很棒!
 

在线会员

  • 伊希娅
  • DillanWest
  • JJXFCJW
  • 龙亚的游戏太空球
  • Hangx
  • shvdvfd
  • nbdwxq
  • 那时的她很好
  • in7
  • 诺诺noo
  • 天禅吖TvT
  • 浪人丿
  • 2433539854
  • zbwuming
  • ice_watermelon
  • Huode
  • 向着日落许愿
  • 娜娜奇
后退
顶部 底部