你没注意的那个按钮,我把这种“APP安装包”的链路追完了:真正的钩子其实在第二次跳转

引子:一颗“安装”按钮背后的链路
很多人点一个“立即安装”或“下载 APK”的按钮时,只看到了页面的外观和承诺的功能,却没有意识到在背后悄悄发生的跳转与信息传递。一次偶然的分析让我沿着一个看似普通的安装流程把整条链路追查到底,结果发现:第一跳只是外壳,真正改变用户体验和归因的“钩子”其实在第二次跳转上。下面把这个过程、常见手法、如何复现与防护建议完整呈现出来。
用一句话概括结果 表面上第一跳负责把用户带离当前页面,第二跳才真正把“追踪参数/深度链接/环境判断/安装包来源”写入到安装流程,从而影响安装统计、广告计费、以及后续的动态内容下发。
常见的跳转链路结构(简化版) 用户点击按钮 -> 页面A(第一跳) -> 页面B(第二跳) -> Play 商店或 APK 下载/Intent 调用 -> 安装 -> 应用内深度打开
为什么第二跳重要:几个典型用途
- 插入 Install Referrer:在跳到 Play 商店的链接中加入 referrer 参数(例如 play.google.com/store/apps/details?id=…&referrer=xxx),从而把特定渠道标注写入 Google Play 的安装引用,影响广告归因与分成。
- 动态环境判断与分流:第二跳可以根据UA、IP、Referer、Cookie或前端指纹做更精细判断(是否为模拟器、是否来自特定国家、是否为爬虫),再决定给出哪个安装包或下载页面。
- 注入深度链接/参数:第二跳把要传递给应用的参数编码后放入 intent 或 install referrer,从而在应用首次打开时触发特定的页面或活动(例如引导页、优惠券、用户 ID 绑定等)。
- 隐蔽的二次加载或恶意回填:某些链路利用第二跳载入隐藏脚本或通过重定向实现“链路接力”,最终把用户带到带有额外 SDK 或受控制签名的 APK 上。
如何一步步把链路追到第二跳(实操方法) 下面是我常用且可靠的复现/分析流程,既适合安全研究者也适合产品或运营同学自检。
1) 初步观察(只用浏览器)
- 在桌面使用浏览器开发者工具(Network 面板)或 curl 查看 header:curl -I -L -v "目标URL" 可以看到服务器返回的 3xx 以及 Location。
- 注意:很多页面在第一跳使用 JavaScript 或 meta refresh 做跳转,curl 无法执行 JS。这时需要后续步骤。
2) 捕获完整 HTTP(S) 流量
- 配置手机或模拟器使用代理(mitmproxy / Charles / Burp),安装根证书以便抓取 HTTPS。
- 在真实设备或 emulator 上执行点击,记录完整请求链(包括 cookies、referer、User-Agent、POST 数据)。
- mitmproxy 能把每一步 302/303、JS XHR、fetch、以及页面加载带来的请求一并记录。
3) 处理 JS 激活的跳转
- 使用无头浏览器(Puppeteer / Selenium)在可控环境里加载页面,观察所有导航和 window.location 的变化。
- 或者在浏览器里手动打开并观察 DevTools 的 Network 面板,找到由 JavaScript 动态生成的第二跳 URL。
4) 调查 Play 安装引用与 intent 调用
- Play 安装引用常见形式:play.google.com/store/apps/details?id=com.xxx&referrer=utm_source%3Dxxx%26…。第二跳往往在跳转到 play 的 URL 中填充 referrer 字段。
- 在 Android 设备上安装后,用 adb logcat 查看 referrer 到底长什么样:adb logcat | grep -i referrer 或者查看应用使用 Play Install Referrer API 接收的内容。
- 若是通过 intent:// 或 market:// 触发下载,要在代理里捕获那一步的请求与参数。
5) 脚本化复现与解码
- 把抓到的第二跳 URL 的 referrer 或 query 参数解码(有时是 base64 或 URL encode)来查看里面的归因、tracker id、广告平台参数(Adjust/AppsFlyer/Branch 等常见字段)以及是否包含用户或设备指纹信息。
典型样例(简化示例) 用户点击 -> siteA(第一跳)302 -> siteB(第二跳)302 -> https://play.google.com/store/apps/details?id=com.example.app&referrer=utmsource%3Dadnet%26af_tranid%3D12345
在这个链路中:
- 第一跳可能只是把流量从落地页转到域名更短/更稳定的中间域;
- 第二跳在构造跳到 play 的 URL 时,把 af_tranid 或其他归因字段写进 referrer,从而让广告平台或中间商获得安装归因与计费依据。
常见的追踪/归因平台参数(识别钩子的线索)
- AppsFlyer:aftranid, pid, afsub1…
- Adjust:utmsource, adjusttracker, adjust_reftag…
- Branch/Deferred Deep Link:link click data(有时以 base64 编码)
- 普遍特征:大量被 encode 的 query 字段,长长的 token、base64 字符串或被分段的 JSON。
为什么很多人没注意到?
- 第一跳往往很短暂,动画化或用“加载中”遮住,用户感受不到背后的多个 HTTP 请求。
- 大部分跳转由 JS 在客户端完成,传统的爬虫/简单 curl 无法看到真正的后续跳转。
- 转跳到 Play 或 Intent 之后,系统级的安装流程把 referrer 等参数当作黑盒传递,普通用户无法直观看到。
对不同角色的建议(务实可操作)
普通用户(在意隐私/安全)
- 优先通过官方应用商店安装:官方渠道能提供基本的签名与安全检查。
- 看包名与开发者:不要只看应用图标或名字,确认包名和开发者信息。
- 权限与评论:安装前划过评论,看历史评分与权限请求,若 APK 来自非信任站点要谨慎。
产品/运营人员(厘清归因与计费)
- 审计第三方渠道:把落地页、追踪中间域和广告素材链路串起来,确保归因参数是可解释的。
- 要求合作方公开跳转逻辑:中间域和跳转策略应透明,避免“黑盒”重定向影响统计。
- 使用 Play Install Referrer API(Official):相较于旧的 referrer Broadcast,新的 API 更可靠且更不易篡改。
开发者/安全工程师(减少风险泄露)
- 在应用内验证 referrer 与 deep link:不要盲信传入参数,做签名校验或短期 token 验证。
- 审计 SDK:第三方 SDK 常被用于链路或埋点,定期静态与动态审计可发现异常流量或请求。
- 日志与溯源:把安装来源、referrer 的原始字符串存入安全日志,便于事后追踪。
进阶:如何检测是否被“第二跳”操控(给研究者的检查清单)
- 捕获点击到安装之间的全部 HTTP 请求:使用设备代理 + 分析工具,确认哪里写入 referrer。
- 检查所有中间域名的跳转历史:WHOIS 和 CDN 信息有助于判断是否为广告网络或中介。
- 解码所有被 encode 的参数,寻找常见 tracker 字段或加密痕迹。
- 在多个设备与网络环境下重复测试(不同 User-Agent、不同 IP、关闭 cookie),观察第二跳是否有针对性分流。
- 对照 Play Console 的安装归因日志,核对是否与中间跳转中包含的参数一致。
结论:别被“第一跳”骗了
很多落地页把跳转逻辑拆成了两段:第一跳负责表现(快、看起来合法),第二跳负责“注入”——注入归因、注入指令、注入分发路径。若只看第一跳,很容易漏掉整个装包/归因链路的关键环节。无论你是担心广告计费准确性、用户隐私,还是想避免被恶意 APK 利用不透明链路,追查到第二跳往往能揭示真相。