当前位置: 首页 > news >正文

指纹浏览器的电池与网络状态:Navigator Battery 与 Network Information API 的隐身

文章目录

    • 一、 电池 API 的深渊:逻辑悖论与异步时序
      • 1. Navigator Battery API 的功能与用途
      • 2. Navigator Battery API 的隐私风险
      • 3. 风控的三大杀招
      • 4. 核心破局:Browser 进程的源头拦截
      • 5. C++ 实战:状态机驱动的虚拟电池
    • 二、 网络信息 API 的雷区:时空关联与特征泄露
      • 1. Network Information API 的功能与用途
      • 2. Network Information API 的隐私风险
      • 3. 逻辑悖论:代理 IP 与网络特征的撕裂
      • 4. 核心破局:Blink 层的声明式伪装
      • 5. C++ 实战:强一致性的网络特征注入
    • 三、 极端对抗:彻底隐身与降维打击
      • 1. Battery API 的彻底移除
      • 2. Network Information API 的静默失效
    • 四、 避坑实录:三大致命暗礁
      • 1. 充放电时间的溢出
      • 2. Promise 的微任务时序
      • 3. 台式机的 `onchargingchange`

在指纹浏览器的攻防战中,大部分开发者将精力聚焦于 Canvas、WebGL 等重型渲染指纹,却往往忽略了两个轻量级却极其致命的侧翼探头——电池状态网络信息

风控系统对这两个 API 的利用,堪称“四两拨千斤”的典范。它们不用于计算复杂的哈希,而是用于时空关联校验与环境逻辑证伪

试想:你的代理 IP 显示在纽约,时区也是美东,但navigator.connection却返回了典型的中国联通 4G 网络特征;或者你声称是一台常年插电的台式机,navigator.getBattery()却频繁触发onchargingchange事件。这种跨维度的逻辑撕裂,风控系统一毫秒即可判定为伪造环境。

更为棘手的是,这两个 API 均涉及浏览器与操作系统的异步交互,且有着严格的 W3C 规范约束。粗暴的 JS Hook 极易破坏事件回调时序,甚至引发类型错误。
本文将拆解 Battery 与 Network Information 的底层通信机制,给出基于源码级的隐身与伪装策略。

一、 电池 API 的深渊:逻辑悖论与异步时序

1. Navigator Battery API 的功能与用途

Navigator Battery API 是一项强大的功能型 API,它能够使网页脚本获取设备电池的相关信息。通过这一 API,开发者可以轻松获取设备的电池电量百分比、电池是否处于充电状态、电池充电时间以及放电时间等关键数据。这些信息对于优化网页性能有着不可忽视的作用。

比如在电量较低时,网页可以自动降低视频播放的清晰度,减少资源消耗;或者当设备正在充电,网页则可以加载更多资源,为用户带来更流畅的体验。这不仅提升了网页的实用性,也增强了用户的满意度。对于需要持续运行或对性能要求较高的网页应用来说,Battery API 无疑为开发者提供了更精准的设备状态信息,帮助他们更好地调整应用行为,以适应不同的使用场景。

2. Navigator Battery API 的隐私风险

尽管 Navigator Battery API 在功能上颇具优势,但它也伴随着不容忽视的隐私风险。该 API 可能会泄露设备的唯一标识符等敏感信息。攻击者有可能利用这一漏洞,通过获取电池的电量、充电状态等信息,结合其他数据,推断出设备的唯一标识符。

一旦设备的唯一标识符被泄露,攻击者就能对该设备进行精准的跟踪和定位。无论是用户的位置信息,还是在网络上的各种行为,都有可能被攻击者所掌握。他们可以利用这些信息实施精准的网络诈骗,或者将用户的个人信息出售给其他不法分子,给用户带来严重的经济损失和隐私泄露风险。而且,如果攻击者持续监控设备的电池状态变化,还能推测出用户的使用习惯和生活规律,进一步侵犯用户的隐私安全。这些潜在的风险使得用户在使用基于 Battery API 的应用时,需要格外谨慎,以保护自己的个人隐私不被泄露。

navigator.getBattery()返回一个 Promise,解析出一个BatteryManager对象。风控不关心你的电量是多少,它关心的是电量变化的物理逻辑

3. 风控的三大杀招

  • 杀招 1:台式机的电量幻影
    真实的台式机没有电池,调用getBattery()应该瞬间 resolve,且charging永远为truechargingTime为 0,level为 1.0。如果你在一台声称是台式机的浏览器中,返回了charging: falselevel: 0.55,瞬间暴露。
  • 杀招 2:事件驱动的反常
    真实的电池状态是连续变化的。如果风控页面挂载 10 分钟,onlevelchange一次都没触发,或者插拔电源时onchargingchange没反应,这是极度反常的。
  • 杀招 3:JS Hook 的时序灾难
    劣质指纹浏览器用 JS 拦截getBattery(),返回一个伪造的同步对象。但规范要求它必须返回一个Promise。JS Hook 往往在微任务队列的执行时序上露出马脚,风控通过测量await getBattery()的耗时即可识破。

4. 核心破局:Browser 进程的源头拦截

要实现完美伪装,必须理解 Battery API 的跨进程架构:

  1. JS 调用-> Blink 层发起 Mojo 调用。
  2. Browser 进程BatteryStatusManager调用操作系统 API(Windows/Win32 或 Mac/IOKit)读取真实状态。
  3. 状态通过 Mojo 异步回传 Blink,Blink 触发 Promise resolve 和事件回调。
    精准拦截点content/browser/battery_status/目录下的battery_status_service.cc或类似文件。
    我们不需要在 Renderer 进程动刀,而是直接在Browser 进程拦截真实操作系统的回调,替换为基于配置的虚拟状态,然后顺理成章地通过 Mojo 传回 Blink。

5. C++ 实战:状态机驱动的虚拟电池

仅仅返回静态值是不够的,必须模拟电池的物理充放电逻辑。
步骤一:拦截真实 OS 回调

voidBatteryStatusService::DidChangeBatteryStatus(constdevice::BatteryStatus&real_status){// 【指纹浏览器拦截点】constauto&fp_config=FingerprintConfig::GetInstance();if(fp_config->IsBatteryFakingEnabled()){// 忽略 real_status,启动虚拟电池状态机device::BatteryStatus fake_status=VirtualBatteryMachine::GetInstance()->GetCurrentStatus();// 将伪造状态通过 Mojo 发送给 Renderer 进程NotifyClients(fake_status);return;}// 兜底:传递真实状态NotifyClients(real_status);}

步骤二:构建 C++ 虚拟电池状态机
这是核心难点。我们需要根据预设的levelcharging状态,自动推演未来的状态变化,并通过 Mojo 主动推送事件。

// virtual_battery_machine.ccclassVirtualBatteryMachine{public:device::BatteryStatusGetCurrentStatus(){base::AutoLocklock(lock_);// 根据时间流逝计算当前电量autonow=base::Time::Now();autodelta=now-last_update_time_;if(current_status_.charging){// 充电逻辑:电量缓慢上升,到 1.0 停止doublecharge_rate=0.01;// 每秒充 1%current_status_.level=std::min(1.0,current_status_.level+delta.InSecondsF()*charge_rate);if(current_status_.level>=1.0){current_status_.charging_time=0.0;// 充满}}else{// 放电逻辑:电量缓慢下降,到 0 停止doubledischarge_rate=0.005;current_status_.level=std::max(0.0,current_status_.level-delta.InSecondsF()*discharge_rate);}last_update_time_=now;returncurrent_status_;}private:base::Lock lock_;device::BatteryStatus current_status_;base::Time last_update_time_;};

效果
风控 JS 调用getBattery(),拿到的是符合 Promise 规范的异步对象。页面停留期间,电量会根据状态机自然波动,onlevelchange事件按需触发。时序逻辑与真实硬件别无二致。

二、 网络信息 API 的雷区:时空关联与特征泄露

1. Network Information API 的功能与用途

Network Information API 能够为开发者提供丰富的网络状态信息,让网页应用更好地适应用户的网络环境。通过它,开发者可获取到设备的网络连接类型,像Wi-Fi、移动数据等,还能了解到网络的大致带宽和延迟情况。

借助这些信息,开发者可以为用户提供更优质的网络体验。例如,在检测到用户处于低带宽网络时,可自动调整视频或图片的加载质量,降低分辨率,减少数据流量消耗,避免加载过慢的问题。当发现网络延迟较高时,可提前做好缓存或预加载准备,确保用户在切换页面或操作时的流畅性。对于需要实时通信的应用,如在线会议软件,可以根据网络状况调整音视频的编码参数,保证通信的稳定性和清晰度。Network Information API 的应用,极大地提升了网页在不同网络条件下的适应能力和用户体验。

2. Network Information API 的隐私风险

Network Information API 在提供便捷功能的同时,也带来了隐私方面的隐患。它可能会暴露用户的网络环境特征等敏感信息。比如网络连接类型、IP地址、带宽和延迟等,这些信息组合起来,能在一定程度上反映用户的生活习惯、地理位置等隐私。

攻击者可通过收集这些网络环境特征,构建出用户的网络行为画像。例如,如果用户经常在固定地点使用特定Wi-Fi网络,且网络延迟较低,攻击者就能推测出用户的居住或工作地点,进而对用户进行精准定位或跟踪。而且,这些网络信息还可能被与其他数据关联起来,进一步泄露用户的个人信息。攻击者利用这些信息,不仅可能实施网络诈骗等违法犯罪活动,还可能将用户的隐私信息出售给第三方,给用户带来严重的经济损失和隐私泄露风险。因此,用户在使用基于 Network Information API 的应用时,要提高警惕,谨慎授权,以保护自己的个人隐私安全。

navigator.connection(Network Information API) 暴露了设备的网络类型(wifi/4g)、下行带宽和往返时间(RTT)。风控利用它进行极低成本的地理定位校验

3. 逻辑悖论:代理 IP 与网络特征的撕裂

  • 悖论 1:代理 IP 在美国,connection.type却是cellular(蜂窝网络),且effectiveType4g。美国 4G 运营商的带宽和 RTT 特征与你返回的downlink: 10.0(Mbps) 完全不符。
  • 悖论 2:宿主机在千兆宽带环境,downlink返回极高值。但代理节点本身是限速的。风控测量页面真实加载耗时,发现与声明的downlink严重不符。
  • 悖论 3Save-Data标头。如果你的 JS 读取connection.saveData为 true,但 HTTP 请求头中却没有Save-Data: on,瞬间击毙。

4. 核心破局:Blink 层的声明式伪装

与 Battery API 不同,Network Information API 的数据流是单向的(OS -> Blink -> JS),且更新频率极高。我们不能在 Browser 进程频繁拦截网络状态变更,那样会导致性能灾难。
最佳策略是:在 Blink 层切断操作系统数据源,直接返回与代理 IP 地理位置匹配的静态/半静态网络特征。
精准坐标third_party/blink/renderer/modules/netinfo/

5. C++ 实战:强一致性的网络特征注入

找到NetworkInformation.cpp,这里实现了navigator.connection的底层逻辑。
策略 1:覆写核心属性

StringNetworkInformation::type()const{// 【指纹浏览器拦截点】constauto&fp_config=FingerprintConfig::GetInstance();if(fp_config->HasOverride("network_type")){returnfp_config->GetString("network_type");// 例如 "wifi"}returnGetNetworkStateObserver().GetType();// 真实值}StringNetworkInformation::effectiveType()const{constauto&fp_config=FingerprintConfig::GetInstance();if(fp_config->HasOverride("network_effective_type")){returnfp_config->GetString("network_effective_type");// 例如 "4g"}returnGetNetworkStateObserver().GetEffectiveType();}doubleNetworkInformation::downlinkMbps()const{constauto&fp_config=FingerprintConfig::GetInstance();if(fp_config->HasOverride("network_downlink")){returnfp_config->GetDouble("network_downlink");// 例如 5.6}returnGetNetworkStateObserver().GetDownlinkMbps();}

策略 2:阻断事件触发
如果我们只修改了属性,当宿主机真实网络波动时,底层仍会触发onchange事件,导致 JS 读取到新的、未过滤的真实值。

voidNetworkInformation::ConnectionTypeChange(WebConnectionType type,doubledownlink_mbps,doublertt_ms,doubleeffective_connection_type){constauto&fp_config=FingerprintConfig::GetInstance();if(fp_config->IsNetworkFakingEnabled()){// 屏蔽真实网络波动,永远不触发 onchange 事件// 或者:仅在伪造的参数范围内允许触发(更高级的策略)return;}// 兜底:传递真实事件NotifyConnectionChange(type,downlink_mbps,rtt_ms,effective_connection_type);}

策略 3:联动 HTTP 请求头
如果风控检测到navigator.connection.saveData === true,它会在后端校验请求头。
我们必须在 Browser 进程的网络栈中同步注入:
精准坐标content/browser/loader/或网络拦截层。

// 在构建 HttpRequestHeaders 时if(FingerprintConfig::GetInstance()->GetBool("network_save_data")){headers.SetHeader("Save-Data","on");}

三、 极端对抗:彻底隐身与降维打击

在某些极端场景下(如针对 WebRTC 的防御),伪装的性价比极低,彻底隐身是更安全的选择。

1. Battery API 的彻底移除

对于伪装为台式机的环境,最安全的策略是让getBattery不存在,而不是返回一个充满破绽的假对象。
精准坐标third_party/blink/renderer/core/frame/navigator.idl
找到 Battery 相关定义:

// [ // ... // ] interface Navigator { // ... // Promise<BatteryManager> getBattery(); // ... // };

直接注释或删除Promise<BatteryManager> getBattery();这一行。
效果:编译后,V8 绑定层不再为 Navigator 挂载getBattery属性。风控 JS 执行navigator.getBattery会得到undefined。这是一种极其干净的降维打击,适用于无需电池模拟的桌面环境爬虫。

2. Network Information API 的静默失效

同理,如果不需要模拟网络波动,直接在navigator.idl中移除connection属性,并在NetworkInformation类的ConnectionTypeChange中阻断所有事件。让风控以为这是一个极简配置的浏览器环境。

四、 避坑实录:三大致命暗礁

1. 充放电时间的溢出

W3C 规定,如果电池正在充电且即将充满,chargingTime为 0;如果未充电或无áy法确定,则为Infinity
如果你在 C++ 状态机中随意返回一个浮点数,而不处理Infinity的边界情况,风控通过简单的isFinite(battery.chargingTime)即可判定伪造。
破局:严格遵循规范,在状态机中处理边界值。

2. Promise 的微任务时序

即使你在 C++ 层返回了假数据,Blink 层的 V8 绑定依然会将结果包装成 Promise。这个微任务入队的耗时必须与真实场景一致。
破局:不要试图在 Blink 层用同步方式模拟异步 Promise,这会导致 Event Loop 调度异常。让数据自然经过 Mojo 管道回传,IPC 通信的自然延迟就是最好的伪装。

3. 台式机的onchargingchange

如果你声称是台式机,并且保留了 Battery API(这本身就很奇怪),但底层仍会触发onchargingchange事件,这是矛盾的。
破局:台式机伪装策略中,要么彻底移除 API(推荐),要么在 Browser 进程拦截时,恒定返回charging=true, level=1.0,且永不触发状态更新事件。

结语:电池与网络状态,看似微不足道的 API,实则是浏览器与物理世界交互的毛细血管。风控系统正是通过监测这些毛细血管中的血液流向,来判定生命的真伪。

通过深入 Chromium 的 Browser 进程和 Blink 引擎,我们不仅替换了冰冷的返回值,更构建了基于状态机的虚拟物理逻辑,让伪造的电池拥有了充放电的呼吸,让伪造的网络拥有了与代理 IP 一致的脉搏。
当本地环境的伪装达到极致,浏览器将不再是信息孤岛。它必须向世界发出请求,而网络层正是风控布下天罗地网的最终修罗场。下一章,我们将深入 TLS 与 HTTP/2 的底层协议,拆解网络栈指纹的终极对抗。
原因:之前生成的内容已经涉及了网络层(TLS/HTTP2),但这段新内容的结尾又提了一遍,逻辑重复。修改结尾,使其承接上文的本地环境伪装,并强调多维度一致性。

修改后的结语
电池与网络状态,看似微不足道的 API,实则是浏览器与物理世界交互的毛细血管。风控系统正是通过监测这些毛细血管的搏动,来校验整个环境体系的真实性。

通过深入 Chromium 的底层,我们不再是用 JS 贴膏药,而是重塑了底层的物理逻辑,让伪造的参数拥有了符合自然规律的动态特征。至此,从硬件参数到媒体设备,再到电池与网络,浏览器本地环境的 C++ 级伪装已完全闭环。

http://www.jsqmd.com/news/1001347/

相关文章:

  • 第一次对AI感到恐惧:当技术奇点逼近开发者
  • 3个步骤告别Mac数字垃圾:Pearcleaner深度清理实战指南
  • 别再死记硬背了!用几个真实代码片段,帮你彻底搞懂TypeScript的interface和type
  • 实验6-3低代码数据可视化进阶:用蓝图编辑器实现浏览器分析大屏联动交互
  • 从CIFAR到细粒度数据集:手把手教你用SSB基准重新评估你的OSR模型
  • 2026年HDPE双壁波纹管选购指南:湖南源头工厂实力对比与选型建议 - GrowthUME
  • STM32CubeMX配置OSAL内存与中断管理详解:从源码层面理解如何适配你的MCU
  • 民宿/网约房数字化升级:基于智能锁的身份核验与远程授权解决方案
  • 2026年6月最新解读:东莞精密模具定制服务商全面测评与优质供应商推荐 - GrowthUME
  • 如何精准控制Windows电脑风扇:FanControl完全配置指南
  • 【无人机路径规划】实现有效的水陆两栖无人机任务规划和执行附Matlab代码(含粒子群优化和遗传算法)
  • 2026武汉医护类中职学校多维度评测:资质合规升学通道管理服务实训水平 - GrowthUME
  • PyTorch模型部署实战:model.eval()和torch.no_grad()到底该用哪个?(附代码对比)
  • i.MX27L嵌入式系统设计:Smart Speed™架构与低功耗实战解析
  • 企业多业务网络隔离不求人:用华为交换机的IP子网VLAN,5步搞定IPTV、语音、数据分流
  • Spring ResolvableType说明
  • 选题毫无头绪?博导推荐这几个AI论文软件
  • 别再只会用朴素算法了!LCA问题从入门到精通:倍增与Tarjan实战详解(附C++代码)
  • 终极下载管理解决方案:AB Download Manager如何让你的文件下载速度翻倍且井井有条
  • 终极解决方案:如何用VisualCppRedist AIO一键解决Windows程序运行依赖问题
  • 父亲节不同兴趣的爸爸送什么礼物才不闲置?先看这6个判断标准 - GrowthUME
  • 从PlenOctrees到3DGS:聊聊球面谐波(SH)在三维重建中的‘上位史’与选型指南
  • MPC5674F:高效发动机控制核心架构、外设与应用实战解析
  • 5分钟快速上手:CheatEngine-DMA插件高效内存修改完整指南
  • 若依框架下Spring Security多用户表登录的两种姿势:从“框架原生”到“手动接管”的完整对比与选型指南
  • 2026重庆iPhone 17屏幕维修深度解析:从超薄玻璃到微米级贴合的技术博弈
  • MATLAB版非均匀傅里叶变换工具集:含NUSFT原创算法与多种加速实现
  • WordPress AI评论助手:人机协同回复实战指南
  • 2026实测:微信视频号视频保存到手机相册方法,视频号视频无法直接下载怎么办
  • 2026巴州库尔勒学车考驾照全流程攻略:品类选型、合规标准及落地指南 - GrowthUME