开发者生态
morning
我破坏了 AppLovin 的中介密码协议
2026-05-16
1 阅读
lmbbuchodi
我破解了 AppLovin 广告中介流量的密码,并解密了在我同意的移动流量研究小组上捕获的数千个真实请求。结论很简单:加密的出价请求携带足够的设备数据,即使用户拒绝 ATT,也可以在不同发布商的应用程序中确定性地重新识别同一台 iPhone。只要用户在玩游戏,该有效负载就会在每个横幅负载上每约 30 秒到达 AppLovin 加上大约 12 个下游广告网络。认为 ATT 是确定性地识别用户的唯一方法的假设是错误的。对设备进行指纹识别也同样有效。密码 每个 AppLovin 中介请求均通过 HTTPS POST 发送到 ms4.applovin.com/1.0/mediate 。在 TLS 层内部,有效负载被包装在 AppLovin 构建的第二个密码中。 Base64 解码后,线路包络为: 2:8a2387b7dbed018e5e485792eac2b56833ce8a3a:T7NreIR729giTKR-thJPcKeT6JXevACogl57SIFzwKp-1BASwpBT6v: 三个冒号分隔的字段,然后是密文:版本标记 ( 2 ) 40 个字符的协议 ID、发布者 AppLovin SDK 密钥的 54 个字符的后缀。 SDK 密钥是 AppLovin 在注册时向每个发布者应用程序颁发的共享秘密,以明文形式存储在 iOS 上的 Info.plist 或 Android 上的 AndroidManifest.xml 中。该密码包含两个成分:盐和 SDK 密钥。 salt 是每个 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() # 标识版本计数器的常量 = System.currentTimeMillis() # 8 字节 LE — 加密时的挂钟 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,带有大约 30 个顶级密钥。其中两个具有隐私权重: device_info — AppLovin 自己的设备指纹负载副本。 〜50 个字段。 signal_data[] — 一组不透明令牌,每个需求合作伙伴广告网络安装在发布商的应用程序中一个。来自 ATT 拒绝的请求的真实 device_info: 字段 值 它是什么版本 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 安装的键盘字体UICTContentSizeCategoryXXXL 辅助功能文本大小 tz_offset -4 时区音量 40 系统音频音量 mute_switch 1 物理静音开关位置 bt_ms_2 1770745989000 设备启动时间(毫秒纪元) dnt / idfa true / 00000… ATT 拒绝 — IDFA 归零 idfv 81E958C3-…-51DE7CE11819 每个应用程序供应商稳定 ID 再加上另外 35 个字段:屏幕安全区域插入、可用内存、运营商代码、国家代码、区域设置、方向、状态栏高度、单调时钟、电池标志、安全连接状态。实际上,iOS 的每个系统属性都会向第三方代码公开。用户拒绝了 ATT。 IDFA 归零。其他一切都在流动。迷你信封 典型的发布商应用程序有约 18 个需求合作伙伴 SDK 编译,其中包括:Meta、Google、Mintegral、Vungle、ironSource、Unity、InMobi、BidMachine、Fyber、Moloco、TikTok、Pangle、Chartboost、Verve、MobileFuse、Bigo、Yandex 以及 AppLovin 自己的 SDK。当横幅需要填充时,AppLovin SDK 会在本地调用每个横幅,并询问“准备出价信号”。每个需求 SDK 独立构建一个不透明令牌,其中包含其发布者后端所需的任何设备数据。 AppLovin SDK 将它们全部捆绑到 signal_data[] 中,并将整个内容发送到其加密的内部