美文网首页Android开发经验谈半栈工程师
数盟可信ID的获取——揭露防刷单的本质

数盟可信ID的获取——揭露防刷单的本质

作者: Gavinme | 来源:发表于2018-08-24 00:22 被阅读58次

    数盟是一家反作弊服务商,主要技术和专利包括数盟可信ID(即设备指纹)、虚拟机识别、反作弊服务等。其中可信ID是其作为防刷单的主要技术手段。

    该项目是『数盟可信id的获取』的样本。由于商业合作才可以拿到,一般在市面上鲜于见到。该样本出自一家接入过数盟解决方案的第三方公司APP,通过逆向的技术拿到了样本。

    由于key是app唯一的,每次初始化请求会记一次(即结算一次),所以请手下留情!

    关于数盟

    官网传送门:https://www.shuzilm.cn

    关于数盟ID

    『数盟ID』:可信ID技术由数字联盟自主研发,用于准确描述移动设备,每个编码对象获得一个唯一的、不变的标识ID。可信ID能帮助APP公司在不同场景下确认设备唯一性,识别修改设备及复用、虚拟机刷量等行为,可以反作弊、防刷单,并通过数字联盟生成的设备ID和客户账户体系的关联,实时有效识别小号恶意注册等行为,并精确识别历史版本用户、弱账户APP的换机状态等。

    可信ID不随任何非硬件信息变化而更改,是真正唯一、真实、安全、高可用的移动设备指纹。

    数盟SDK的项目结构

    SDK结构

    上图为数盟SDK的结构。

    java层代码用来初始化sdk(用来透传native层apkKey和自定义数据)和注册设备信息监听。
    native层libdu.so用来获取可信ID并和数盟服务端建立安全通信。

    可信ID的获取说明

    经过我的调研,发现该ID并不依赖于传统的设备ID——如imei、mac地址、android_id等——在xpose劫持的情况修改,imei等参数并不会导致该ID修改。C方法拦截未测试(有部分设备信息提供本地接口)。

    在app第一次启动会初始化ID,并上传至数盟服务器(api.shuzilm.cn)。因为考虑到计费统计,所以可信ID的获取至少需要网络访问的权限。
    <uses-permission android:name="android.permission.INTERNET" />

    如下图所示获取88位可信ID: 可信ID

    可信ID的获取过程:

    • 程序启动后在主进程中初始化SDK
    • 注册传感器监听
    • 获取网络权限成功后,尝试获取并散列88位可信ID
    • 在sp中缓存以便下次进来使用
    • 推送ID和相关信息至服务端接口api.shuzilm.cn

    程序只有在第一次启动才会执行计算ID和计费的操作。

    应对策略

    那么问题来了,我们怎么应对防刷单策略,可信ID就真的这么安全么?

    对不起,这个问题我不能回答。但是根据上述的调研结果,传统的作弊手段(通过修改设备imei、mac地址、android_id等信息)显然已经达不到目的,更别提采用虚拟机了。

    但是,如果hook数盟ID的获取方法Main#getQueryID(),仔细分析下,其实这只是欺骗了接入方服务器。在结算时一定会被识别出欺骗。
    下面看一下数盟通信模型和设计,当然这只是我的臆测,我应该会这么去做。也许读者也可以提出更好的模型。

    数盟的通信模型

    通信和校验的过程如下(以下APP指接入数盟ID的Android应用):

    1. APP在主进程中初始化,并注册传感器监听;
    2. 运行过程中在登录接口(假如薅羊毛或刷单的接口)通过.so中getQueryID方法获取smid并加入到通用参数中,打包上传APP服务器(app-s);
    3. 注意在调用本地方法getQueryID的时候,会做两件事:一个是网络访问的权限校验,一个是获取smid后上传数盟服务器(sm-s)。注意,这一切是在native中做的;
    4. sm-s收到smid会回调给app-s通知新ID到来(当然已经在本地服务器check之后);
    5. 此处,我们先忽略竞争与冒险的情况,确保4处的回调过程发生在3之前,即app-s先收到回调的smid A在收到APP发送的smid B。比较这两个参数是否一致,如果一致说明客户端没有作弊,否则就视为作弊;
    6. 剩下就是结算的策略了,实时结算或者走结算周期等。

    这一些列步骤看似每一步都有很大漏洞,但是冷静我们来一个个排除!

    • hook java层getQueryID方法,使其返回一个长度为88随机串,同时修改其他设备的信息。
      方法的签名public static String getQueryID(Context context)
      很显然,4中校验通过不了。因为正确的ID会在native发送到数盟服务器。
    • 拦截APP和数盟服务器之间的通信。方法:hook Nativie。
      我一开始就是这么想的,但是native会校验https证书链,从而达到了防代理的作用。那么是否可以通过native层hook(如Cydia)绕过这一层防护,达到网络劫持的目的。前提是,.so中无hook框架的检测。
    • 基于IDA的.so调试和静态分析
      这是一条看起来最靠谱但又非常不靠谱的方法了。调试的过程很不乐观(据说前两年样本很容易),这可能需要高人指点。但是如果能被轻易破解,估计数盟不会拥有7亿的设备ID了,这是一条巨大的产业链。

    另外,数盟后台的可信ID校验(辨别设备ID的真伪)会通过多个纬度,不容置喙的可信ID只是其中的一个纬度。还需要通过分布式系统校验7亿的ID,用来确认ID是否新增,并通过模型确认该ID置信度。设备运行过程会监听和上传设备的传感器数据变化,通过风控模型达到防刷单和虚拟机识别的目的。

    限于目前的技术手段以上是能够想到的方法。

    总结,面对数盟ID的情况,刷单最直接的方法就是破解libdu.so中函数。同时,so库的安全也是整个数盟ID架构的核心和基础。APP信任so库调用结果就跟信任本地的根证书一样!~

    相关文章

      网友评论

      本文标题:数盟可信ID的获取——揭露防刷单的本质

      本文链接:https://www.haomeiwen.com/subject/vxbmiftx.html