我破解了AppLovin的广告中介加密协议

Hacker News Top 新闻

摘要

一名研究人员逆向工程了AppLovin的广告中介加密协议,发现其使用弱的非加密伪随机数生成器和静态盐值来加密设备信息,即使在用户拒绝追踪权限的情况下,也允许在应用间确定性重新识别iPhone。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/05/16 03:41

# 我破解了AppLovin的中介加密协议。来源:https://www.buchodi.com/i-broke-applovins-mediation-cipher-protocol/ 2026年5月15日 我破解了AppLovin为其广告中介流量包裹的加密算法,并从我的用户同意的移动流量研究面板中解密了数千个真实请求。结论直截了当:加密的竞价请求携带了足够的设备数据,足以在不同发布者的应用中确定性地重新识别同一台iPhone,即使用户拒绝了ATT。这个数据包在每次横幅加载时,大约每30秒,只要用户在玩,就会到达AppLovin以及大约12个下游广告网络。认为ATT是确定性识别用户的唯一途径是错误的。设备指纹识别同样有效。 ## 加密算法 每个AppLovin中介请求都是通过HTTPS POST发送到`ms4.applovin.com/1.0/mediate`。在TLS层内部,有效载荷被包裹在AppLovin构建的第二层加密中。经过base64解码后,线缆信封格式为: `` 2:8a2387b7dbed018e5e485792eac2b56833ce8a3a:T7NreIR729giTKR-thJPcKeT6JXevACogl57SIFzwKp-1BASwpBT6v: `` 三个冒号分隔的字段,然后是密文: 1. 版本标签 (`2`) 2. 一个40字符的协议ID, 3. 发布者AppLovin SDK密钥的54字符后缀。 SDK密钥是AppLovin在注册时向每个发布者应用颁发的共享密钥,以明文形式存储在iOS的`Info.plist`或Android的`AndroidManifest.xml`中。 加密算法需要两个成分:一个盐值和那个SDK密钥。盐值是一个内置于每个AppLovin SDK二进制文件中的32字节常量,前21个有效字节后面跟着11个零字节。这些字节在我检查过的每个IPA和APK中都是相同的(iOS上的Solitaire Associations Journey、Hypermarket3D、Ludo Star、Yik Yak;Android上的Hypermarket3D)。线缆上的40字符协议ID字段是`sha1(salt).hex()`。 加密算法: `` salt = (通用32字节常量,内置于SDK) sdk_key = (每个发布者唯一的86字符字符串,内置于应用包中) dk = SHA-256(salt || sdk_key[:32]) # 每个发布者唯一的32字节派生密钥 protocol_id = SHA-1(salt).hex() # 标识版本的常量 counter = System.currentTimeMillis() # 8字节小端 — 加密时的挂钟时间 masked_ctr = counter ⊕ uint64(dk[0:8]) # 线缆上出现的内容 for i in 0..N-1: if i % 8 == 0: x = (counter + i) x = (x ⊕ (x >>> 33)) * 0xC2B2AE3D27D4EB4F x = (x ⊕ (x >>> 29)) * 0x85EBCA77C2B2AE63 ks = x ⊕ (x >>> 32) ciphertext[i] = plaintext[i] ⊕ ((ks >> ((i % 8) * 8)) & 0xFF) ⊕ dk[i % 32] `` 关于这个结构的一些事实: - 密钥流是一个SplitMix64终结器——Sebastiano Vigna 2014年的PRNG。SplitMix64是语言标准库为游戏和模拟中的快速随机数生成而提供的那种随机性。它通过了统计随机性测试;它没有通过密码学安全性测试,也没有声称要通过。 - 在加密层没有MAC、没有AEAD、没有认证。攻击者可以篡改密文。 - 加密计数器是`System.currentTimeMillis()`。线缆上的每个加密信封在解密之前就泄露了设备加密时的挂钟时间,精确到毫秒:恢复被掩码的计数器,与`uint64(dk[0:8])`异或,得到时间戳。 - 我已经成功解密了来自一个应用的5,394个信封,以及来自其他五个应用的数千个信封,零失败。 ## 传输的内容 解密的明文是gzip压缩的JSON,包含大约三十个顶级键。其中两个承载了隐私权重: - **`device_info`** — AppLovin自己复制的设备指纹负载。大约50个字段。 - **`signal_data[]`** — 一个不透明令牌的数组,每个令牌对应发布者应用中安装的一个需求合作伙伴广告网络。 一个来自拒绝ATT请求的真实`device_info`: 字段|值|它是什么 ---|---|---|--- `revision`|`iPhone14,3`|硬件型号代码 (iPhone 13 Pro Max) `os`|`18.6.2`|操作系统补丁版本 `tm`|`5918212096`|总RAM字节数 (= 5.51 GB) `ndx`×`ndy`|`1284 × 2778`|原生像素屏幕尺寸 `kb`|`en-US,es-ES`|已安装的键盘 `font`|`UICTContentSizeCategoryXXXL`|辅助功能文本大小 `tz_offset`|`-4`|时区 `volume`|`40`|系统音频音量 `mute_switch`|`1`|物理静音开关位置 `bt_ms_2`|`1770745989000`|设备启动时间 (毫秒时间戳) `dnt`/`idfa`|`true`/`00000...`|ATT已拒绝 — IDFA归零 `idfv`|`81E958C3-...-51DE7CE11819`|每个应用供应商的稳定标识符 另外还有35个字段:屏幕安全区域边距、空闲内存、运营商代码、国家代码、区域设置、方向、状态栏高度、单调时钟、电池标志、安全连接状态。实际上是iOS向第三方代码公开的所有系统属性。用户拒绝了ATT。IDFA已归零。其他一切都流走了。 ## 迷你信封 一个典型的发布者应用编译了大约18个需求合作伙伴SDK:Meta、Google、Mintegral、Vungle、ironSource、Unity、InMobi、BidMachine、Fyber、Moloco、TikTok、Pangle、Chartboost、Verve、MobileFuse、Bigo、Yandex,加上AppLovin自己的。当横幅需要填充时,AppLovin SDK本地调用每个SDK,并询问“准备一个竞价信号”。每个需求SDK独立构造一个不透明令牌,其中包含其发布者后端所需的任何设备数据。AppLovin SDK将它们全部捆绑到`signal_data[]`中,并将整个内容放入其加密信封内发送。AppLovin的服务器然后将每个令牌通过服务器到服务器的OpenRTB转发给该竞标者的投标服务器。设备发出一个出站网络调用。数据到达十几个独立的广告技术公司。在我将要引用的请求中,十八个适配器中有十二个返回了竞价信号,大小从29字节(Verve,可能只是一个获取令牌)到14.4 KB(Unity Ads)。在这十二个中,**有四个在AppLovin信封内是可读的;另外八个加密到目标竞标者**,对AppLovin不透明,只能在接收方的投标服务器上解码。值得详述的是这四个可读的。 InMobi的竞价信号 — 36个URL编码的键=值对,完整解码: `` d-devicemachinehw = iPhone17,5 os-v = 26.2.1 h-user-agent = Mozilla/5.0 (iPhone; CPU iPhone OS 18_7...) d-language = en-US d-localization = en_US d-key-lang = ["en-US"] d-device-screen-density = 3 d-device-screen-margins = {"right":0,"left":0,"bottom":34,"top":47} d-media-volume = 15 d-drk-m = 1 d-bat-lev = 25 d-bat-sav = 0 d-bat-chrg = 0 d-av-disk = 6275 MB d-tot-disk = 116837 MB u-app-orientations = 1 u-appbid = com.hitappsgames.wordsolitaire u-appdnm = Solitaire Associations: Journey u-appver = 1.9.0 u-tracking-status = 3 u-age-restricted = 0 s-skan = -1 `` InMobi的令牌包含AppLovin自己的`device_info`没有的信号:以兆字节为单位的可用磁盘空间(6,275 — 每小时变化,熵值非常高)、总磁盘空间、电池电量、充电状态、深色模式偏好、特定型号的安全区域边距尺寸。下游竞标者收集的设备数据比转发它的中介更多。 BidMachine的信号额外包含:IANA时区字符串(`America/New_York`,比数字偏移更具体)、运营商代码、SKAdNetwork接受列表,以及一个单独的36字符UUID,这是BidMachine自己的每个用户标识符。他们构建了自己的持久性跨应用密钥,存储在其SDK的UserDefaults中,并在每次请求时与Apple的IDFV一起发送。 Fyber的信号是最保守的:User-Agent、包名、型号、操作系统、IDFA、IDFV、区域设置,加上一堆内部A/B测试标志名称。 在四个可读的迷你信封中,设备指纹以四种不同的模式到达四家广告技术公司。另外八个将相当的有效载荷以我们无法从外部检查的方式加密发送给另外八家公司。指纹在每次横幅加载时扩散开来。 ## `api_did`哨兵 在`app_info`内部,有一个18字符的十六进制字段叫做`api_did`。AppLovin的服务器在第一次SDK初始化时分配它 — SDK在新安装时向`applovin.com/2.0/device` POST完整的`device_info + app_info`一次,服务器返回一个`device_id`,SDK缓存它并在每次后续请求中作为`api_did`回显。服务器签发、持久、设计为跨应用。 在我观察到的六个不同的物理iPhone上(拒绝ATT — 不同的硬件修订版、不同的IDFV、来自不同发布者的不同应用),**100%的信封中`api_did`以相同的八个十六进制字符开头:`10badd1d`.** 将这些字节读作ASCII:`0xBADD1D` = `BADDID` = "Bad Device ID"。这是一个哨兵 — AppLovin的服务器为每个拒绝ATT的调用者返回相同的前缀,但每个应用有一个随机的尾部盐值。对于授予ATT的用户,我观察到了三个不同的前缀(`1023c...`、`10621...`、`10ebf...`)— 每个IDFA一个,证实了当授予ATT时,`api_did`是IDFA的确定性转换。当拒绝ATT时,前缀不携带任何设备标识信息。AppLovin自己的服务器签发的跨应用标识符干净地尊重了ATT。这是真实的,值得大声说出来。 ## 排除IDFA和`api_did`后的指纹 `api_did`是一个字段。IDFA是另一个。加密信封包含大约48个额外的`device_info`字段,加上12个迷你信封,每个都携带自己的指纹副本。ATT将一个标识符归零。它没有触及: - 硬件型号代码 - 操作系统补丁版本 - 以点和原生像素为单位的屏幕尺寸 - 屏幕安全区域边距(刘海+主屏幕指示器像素 — 特定型号) - 总RAM字节数 - 以兆字节为单位的可用磁盘空间(每小时变化,熵值非常高) - 电池电量和充电状态 - 系统音频音量 - 系统静音开关状态 - 深色模式偏好 - 辅助功能文本大小设置 - 已安装的键盘列表 - 时区偏移(以及在某些竞标者令牌中的IANA时区字符串) - 设备启动时间(以毫秒为单位的时间戳,直到重启前稳定) - IDFV - 每个需求SDK在其自己的存储中独立生成的每个竞标者UUID 我使用九个字段 — `revision + os + tm + ndx + ndy + kb + font + locale + tz_offset` — 对我解密语料库中的十个不同的物理iPhone构建了一个SHA-256指纹。结果:十个不同的设备对应十个不同的指纹。在一个包含多台相同硬件型号iPhone的样本中,达到了100%的唯一性。对于一位拒绝ATT的用户,其设备出现在来自三个不同发布者的三个不同应用中,**指纹哈希在所有三个应用中完全相同**:`321d60c4d72ddf2a`。不同的包名。不同的IDFV。不同的SDK版本。这就是隐私论点,通过直接构造证明:仅查看每次加密中介请求中流动的设备信息负载,在IDFA归零且不考 `api_did`的情况下,数据足以在不同发布者的应用中确定性重新识别同一台物理iPhone,且用户一直拒绝ATT。该负载同时到达AppLovin和大约12个需求合作伙伴,每次横幅刷新时,大约每30秒一次。 ## ATT实际控制了什么 ATT是对Apple签发的跨应用标识符(IDFA)的控制。它在线缆上得到尊重,当用户拒绝时,IDFA确实被归零。AppLovin自己的服务器签发标识符(`api_did`)也得到尊重,`BADDID`哨兵向每个拒绝用户返回相同的值。这两项控制都在标识符层发挥作用。 AppLovin和十二个下游广告网络选择相互发送的协议不在标识符层运作。它在设备指纹层运作,iOS对此没有门控,Apple没有机械控制权,ATT也触及不到。每个加密的中介请求都携带50个设备字段给AppLovin,然后18个不同的竞价信号给18个不同的广告网络,然后通过服务器到服务器的扇出到达这些竞标者的下游DSP。这些方中的每一方都有自己的设备指纹、自己的标识符、自己在发布者和会话之间重新链接同一台物理iPhone的能力。

相似文章