0x00 前言
Proxifier 新版已升级到 WFP 框架进行代理,本文已过期
本文为流水账形式, 查看解决方案请 点这里
时间过的真快呢, 不知不觉高考完的第一个国庆就来了. 有了5天的长假, 我又想起来 Chromium-EyeProtect 更新的事情了(上次更新是四个月前, 看到 README.md 的图了么).不过, 用几天完成更新赶上最新的 v77.0.3865.90 (Stable) 后却出现了我意料之外的情况…
Proxifier 居然不能正常代理 Chromium 的流量了. 具体表现是连 Verbose Log 都无法看到任何关于 chrome.exe 的信息, 就像 Chromium 直接绕过了 LSP 去访问互联网一样…
排除 Proxifier 的问题后, 我还是不太甘心就这样放弃掉 Proxifier, 于是就有了下面这一堆踩坑和这篇 Blog .
0x01 初步分析
查了部分 LSP 的资料后, 我的第一感觉是 Chromium 在创建 Socket 的时候是不是加了什么大魔法, 于是搜索文件名带 sock 和 net 的文件逐个排查之.
但一路翻下来所有文件最新的修改几乎都在我完成上一个EP版本之前, 也就是说这一堆文件应该都不是问题的根源. 于是继续深入到 net\socket\tcp_socket_win.cc 和 net\base\winsock_util.cc 进行排查, 依然没什么收获.
0x02 陷入江局
“既然上面的文件都没什么重大变化, 会不会是什么隔离功能被启用了?” 抱着这样的想法我搜索了一下 layered service provider, 没想到还真让我搜出一堆结果来
然而事情总是没那么顺利, 这一堆文件中只有 security_level.h 和(可能存在的)绕过LSP功能有关, 其他文件基本都是和 net-export 中的记录功能相关的.
当我看到上面这段注释时还非常兴奋, 顺着这个 flag 搜索之, 找到了下面的 features.cc, 发现这确实是一个默认启用的隔离功能.
但是现实往往很残酷 , Git告诉我这个功能三四年前就有了, 而且进一步的搜索表明 这个 Flag 并不是绕过 LSP 而是阻止其加载不需要的 LSP 模块 (结论不一定完全正确). 于是排查一度陷入僵局.
0x03 暴力排查
既然常规的方法解决不了问题, 那我们只有试试暴力解决了… 从v75一个一个版本装到v77有问题的版本总能找到是哪段 commit 在搞鬼吧…
于是我拿出虚拟机开始一个版本一个版本试, 不过最后还真给我试出来了
几个小时的安装-卸载-再安装终于让我将问题版本定位到 77.0.3826->77.0.3828 之间, 这个范围已经相对(从v75到v77的几万个commit)而言较小了, 于是果断拿出 gitk 开始翻日志
中间过程就不提了, 只有亲自翻过 Chromium 的 commit 的人才能理解那是什么感觉… 翻了半天终于让我找到一个和 Network 有关的 commit, 但这怎么看也不像和我的问题有关…
因为根据这个 commit 来看, 它只是个和测试有关的开关, 和我的问题并没有什么关系. 不过抱着试试看的态度我删掉了这个开关并重新编译 Chromium, 没想到选择居然真的能被 Proxifier 代理了
于是就有了 这么一个支持 Proxifier 的 Chromium-EyeProtect
0x04 技术细节
虽然问题解决了, 但我还是想研究一下具体的技术细节, 于是继续深挖.
首先, 追着这个 flag 我们会回到刚才的 feature.cc 中. 其实刚才我已经离问题的根源很接近了, 但这个 switch 默认是禁用的, 所以我也没在意
具体这个 switch 是怎么被激活的我暂时没有研究, 这里先分析激活后的效果.
(本来这里应该还有更详细的分析, 但 Chromium 的沙盒机制太复杂我一时也摸不透, 就简单的写一下吧.)
激活后网络请求会走沙盒, 然后 bypass LSP. (好水的技术细节
0x05 解决方案
水了这么半天还没说解决方案呢. 简单的归纳起来有两个方案
- 由于该 feature 并未建立对应的 flag, 因此只能在启动时加上命令行参数来禁用:
--disable-features=NetworkServiceSandbox
- 对于重新编译的 Chromium, 可以简单的移除上面提到的 testing/variations/fieldtrial_testing_config.json 中新增的那几行, 比如 这样
- 当然, 你也可以直接使用最新版的 Chromium-EyeProtect, 默认已包含2了中的补丁