电信网络诈骗中,犯罪分子使用的“共享屏幕”类视频会议软件不断升级演变(如图1)。从“手机QQ”、“腾讯会议”等市面上常见的网络会议软件,到自研的“会议”、“云服务”软件,再到更具隐蔽性的“云视听”软件。
近期出现的一款名为“微服务”的视频会议软件,更是能绕过大狗平台线索分析脚本的检测,让追踪调查愈发困难。此 APP 最早出现时间为2024年6月,目前大狗平台发现的样本已有200余个。
图1 “屏幕共享”骗局中涉案APP的演变过程
大狗涉网线索分析平台专家团队研究员@yyy 针对“微服务”APP 样本展开深入研究,以下是他分享的一些技术研判思路,希望能为解决这一问题提供新的见解。
分析过程
1►
了解APP样本
将 APK 文件上传至大狗平台进行自动化分析,从解析出的 APK 专业报告中可以发现:
1、应用名称和图标较之前“云服务”类 APP 已经发生了改变,但是界面截图和 APP 提供的功能依然具有极大的相似性,初步判断为同团伙样本;
2、在 SDK 信息栏同样识别出了“实时音视频”类开发工具包。不同之处在于:变更了 SDK 提供商,同时关键 ID 中只识别到了文件路径,需要进一步逆向分析来获取调证 ID、KEY。
图2 APK专业报告
了解完样本之后,将 APK 文件放入 Jadx 中,进行反编译,获取程序源代码。
2►
通过Jadx分析
● 2.1. 分析思路
1、这里已经明确了,要分析的实时音视频 SDK 在源码中的文件路径为:lib/armeabi-v7a/libliteavsdk.so。所以,直接去资源文件 lib 中查看相关的 so 文件信息,进行确认。
2、找到 so 文件后,可以在网上搜索库文件的名字,查找相关的文章或信息。这个样本中,第三方库文件名称为 libliteavsdk.so ,搜索结果显示为国内某厂商提供的 实时音视频SDK。
可以先搜全名, 如果没有结果可以进行拆分搜索(如: liteavsdk, liteav)。
3、接下来,去看该 SDK 提供商的开发者文档,查看它是如何初始化的。初始化过程中是否需要Key,或者某些ID等标识,我们需要获取的就是这个 ,了解后便可以开始进行下一步了。
由于 SDK 初始化过程中用到的 Key 或者某些 ID,是区别不同用户身份的唯一标识,因此也会作为向相关 SDK 提供商发起数据调证时,需要提取的关键 ID。
● 2.2. 找SDK初始化位置
阅读开发者文档可以发现, 当调用 enterRoom时需要传递一个叫 TRTCParams的参数,里面有一个字段叫SDKAppID(如图3),这个就是我们要找的,继续下一步。
图3 SDK开发者文档
当知道在调用哪个函数会携带 SDK ID 信息时,就可以在 Jadx 中全局搜索这个函数名字,帮助我们快速定位该函数在哪些位置发生了调用,这里搜索 enterRoom (如图4)。
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/8-1721709967.png)
图4 全局搜索 enterRoom 函数
可以看到,匹配到很多结果,可以检查调用, 查看有哪些地方调用了SDK。不过种方式很难定位并找到 APP ID,因此尝使用 Frida Hook 来查找。
3►
使用Frida分析
● 3.1. 分析思路
1、首先,在 Jadx 中查找 SDK 文档提供的初始化函数,明确目标。除个别定制的情况外,进行初始化操作必定会调用第三方 SDK 厂商提供的初始化函数。
2、此外,要明确需要 Hook 的具体函数,因为 Java 中存在多态的情况,Hook 后可能并不会被触发。因此,需要明确 Hook 的是被调用的类,而不是接口或被继承的类。
● 3.2. 开始Hook
尝试直接 Hook enterRoom 函数的代码如下:
let TrtcCloudJni = Java.use("com.tencent.liteav.trtc.TrtcCloudJni");
TrtcCloudJni["nativeEnterRoom"].implementation = function (j, enterRoomParams, i) {
console.log(`TrtcCloudJni.nativeEnterRoom is called: j=${j}, enterRoomParams=${enterRoomParams}, i=${i}`);
this["nativeEnterRoom"](j, enterRoomParams, i);
};
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/9-1721709968.png)
图5 直接Hook enterRoom 函数
从运行结果可以看出,Hook 后并没有按预期来执行,尝试在界面上点击加入房间并输入任意房间号之后,提示: 网络错误, 请检查网络! 猜想可能的原因如下:
1、是因为网络不通?
但是进行抓包后,在云真机操作台中分析网络请求,发现所有的网络都是通的。
2、是因为是模拟器的原因?
用真机打开该APP,仍然报一样的错误,甚至换了好几部手机都是一样的错误……
说明真正的错误并不是由上述问题导致的,于是换了个分析思路:能否直接将按钮 Hook 掉,来追踪到底是什么原因导致发出这个错误的?有没有可能直接把这个报错给跳过?
于是开始进行 Java 层上的 Hook,刚开始认为按钮虽然在前端实现,具体按下事件处理程序应该是在 Java 层上。找到这个具体的位置,上面的问题就能解决了,但是结果却恰恰相反。
4►
分析uni-app
结合之前 APK 分析报告中,识别到数字天堂(DCloud)开发工具SDK,查看 AndroidManifest.xml 发现其入口是 DCloud-uniapp 平台下的前端应用的框架(如图6)。
我们可以将一些特殊的名称拿到搜索引擎上去查一下, 在这里就是通过搜索知道这是基于DCloud Uniapp框架开发出来的,给后续分析提供很大的帮助。
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/0-1721709969.png)
图6 AndroidManifest.xml 文件
查看 uni-app 平台的开发文档发现,具体业务逻辑可以通过编写 JS 代码来实现,整个框架都是基于 H5 来做的。接着,通过搜索找到这个框架打包出来的 APK 结构信息(如图7)。
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/1-1721709970.png)
图7 uni-app框架打包的APK结构信息
或者也可以不用搜 APK 结构信息,直接在Jadx上将所有可疑的文点开来看, 也能够找到想要的内容。
之后开始着手看这些文件,发现真实业务逻辑代码经过了混淆,让其难以看懂和理解。
于是就想到,既然这样有没有可能使用到 WebView,带着这个问题,通过编写 Frida 脚本来 Hook WebView 的loadUrl 函数,发现确实使用到了 WebView(如图8)。
let WebView = Java.use("android.webkit.WebView");
WebView.loadUrl.overload("java.lang.String").implementation = function (url) {
console.log(url)
return this.loadUrl(...arguments);
};
图8 Hook WebView 的 loadUrl 函数
紧接着,开始分析前端代码。做法比较简单:通过 Frida 把 loadUrl 的参数改写,直接访问自己起的服务,这样就可以达到调试的效果。
结果还是不行,因为这些并不是业务代码,还需要继续分析,对错误提示的字符串进行全局搜索(如图9)。
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/2-1721709972.png)
图9 全局搜索
发现错误提示的字符串在 app-service.js 中,WebView 中并没有加载这个 js 文件。既然 WebView 中没有加载,那是不是在 java 代码中加载的呢?带着这个问题,继续回到 Java 代码中查找。由于程序加载文件必然会读文件,所以直接 Hook 读文件那个函数,然后打印堆栈就可以实现,代码如下:
function traceStack() {
let stackString = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
console.log(stackString);
}
Java.use("java.io.File").$init.overload("java.lang.String").implementation = function () {
// console.log('call ', arguments[0])
if (arguments[0].endsWith("app-service.js")) {
traceStack();
}
return this.$init(...arguments);
};
运行结果显示,程序确实加载了 app-service.js 文件(如图10)。
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/1-1721709973.png)
图10 打印读文件函数堆栈
let WXViewWrapper = Java.use("io.dcloud.feature.weex.WXViewWrapper");
WXViewWrapper["render"].implementation = function (template, options, jsonInitData) {
console.log(
`WXViewWrapper.render is called: template=${template}, options=${options}, jsonInitData=${jsonInitData}`
);
this["render"](template, options, jsonInitData);
};
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/0-1721709973.png)
图11 最终调用函数位置
现在的问题是:如何修改这个 JS 代码?由于代码是混淆无法读懂,更别说修改了。再次去网上查找相关反混淆的工具,功夫不负有心人,找到一个可以用的 Github – kuizuo/js-deobfuscator。解密后,所有逻辑一目了然, 可以不用继续 Hook 下去了。
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/8-1721709974.png)
图12 检查函数
请求时会调用 isTrueVersion 这个函数来检查(图12),里面检测的并不是网络错误, 网络错误只是一个误导。这里检查的是当前日期,需要的日期是 “20240701” 。由于分析的时候已经是第二天了,时间不匹配,因此就会报这个错误。然后将其它几个函数也还原了,最后发现 APP ID 是从服务器返回的(图13)。
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/4-1721709975.png)
图13 从服务器返回 APP ID
传递的参数是 SDK 最后转化为 APP ID,只要加入房间都会调用 enterRoom 函数(图14、图15)。
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/8-1721709975.png)
图14 传递SDK转化为 APP ID
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/0-1721709976.png)
图15 加入房间触发 enterRoom 函数调用
说明按照上面直接Hook enterRoom 函数的方式是可以行的,至此,分析结束。
总结:’微服务’ 视频会议
APP线索核查建议
1►
分析结论
针对最新样本“微服务”视频会议 APP 样本的分析,揭示了以下关键信息:
-
应用程序采用了代码混淆技术,以掩盖其真实业务逻辑。要进行业务逻辑分析,需要先使用反混淆工具还原相应的代码。
-
同时,该 APP 会对系统时间进行检测,当时间超出预设范围时,操作 APP 将会触发“网络错误,请检查网络!”的提示。
-
要想在不修改代码的情况下获取 SDKAppID,需要确保 APK 文件在有效时间内。
2►
线索核查建议
建议大家在案件发生后,及时对相关 APK 和网站进行固证。在调查过程中,可以尝试通过大狗平台进行关联分析,获取相关团伙的最新样本。
如果涉案 APP 仍在有效时间内,可以通过下面的 Frida 脚本 Hook enterRoom 函数,获取 APP 中实时音视频 SDK 的 AppID 线索。
let TrtcCloudJni = Java.use("com.tencent.liteav.trtc.TrtcCloudJni");
TrtcCloudJni["nativeEnterRoom"].implementation = function (j, enterRoomParams, i) {
console.log(`TrtcCloudJni.nativeEnterRoom is called: j=${j}, enterRoomParams=${enterRoomParams}, i=${i}`);
this["nativeEnterRoom"](j, enterRoomParams, i);
};
此外,根据还原的 JS 代码,我们了解到 APP ID 是从服务器返回的。感兴趣的朋友,可以进一步研究该样本 API 网站。
最后,当遇到复杂的APP、网站线索分析问题时,欢迎大家咨询无糖信息专家服务进行处理~
![剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析 剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/8-1721709977.gif)
原文始发于微信公众号(无糖反网络犯罪研究中心):剖析‘共享屏幕骗局’最新样本:某视频会议软件 SDK 线索分析