引子
上个月,一位企业客户报告说,他们使用的第三方浏览器扩展无法正常工作。对该扩展的调查表明,该浏览器扩展依赖于一个在浏览器沙箱之外运行的NativeMessaging Host(NMH)组件。在审查客户提供的进程监控日志时,我们发现,Native Host可执行程序在启动数十分钟后就意外退出。并且,在这次意外退出后,下一次浏览器内扩展试图调用它时,浏览器到本地的调用就会失败,从而导致浏览器扩展无法提供其预期功能。
不幸的是,我既没有NMH可执行文件的源代码(甚至没有二进制文件),在进程监控器日志中也没有找到明显的线索(例如,注册表读取或写入失败),所以,我们很难搞清楚问题到底出在哪里。我对支持工程师说,要是能看到浏览器扩展和NMH之间交换的JSON信息,也许就能帮我们找到问题的根源所在。
"我们需要像Fiddler这样的工具来监视NMH信息,而不是HTTPS信息。"
这有什么难的?
从技术上讲,我并不熟悉与浏览器扩展有关的东西,所以,在排除了我能想到的几个可能的根源问题后,我就忙其他的事情去了。
但这一构想一直萦绕在我的脑海里:像Fiddler一样的工具,但用于检查本地信息传递。
建立这个系统有多难?会有多大用处?
自从2015年底“抛弃”Fiddler和Telerik后,我就没写过多少C#代码;偶尔写一点,大多也是Fiddler的插件,而不是独立的应用程序。不过,Native Messaging远没有HTTPS那么复杂,所以应该不会太难,对吧?
我们希望在调试器中实现以下功能:
显示从浏览器扩展到Native Host的信息
允许将这些信息记录到一个文件中
允许在任何方向上注入任意的消息
(扩展目标)允许修改这些消息
在接下来的几个晚上,我打开尘封多年的Visual Studio IDE,努力回忆C#异步编程的工作方式。
关于NativeMessaging Meddler
NativeMessaging Meddler的源代码和编译版本都可以从GitHub下载。
NativeMessaging Meddler(NMM)是一个基于.NET 4.8的Windows应用程序。它的底部提供了一行选项卡,以便于我们在不同的选项卡之间进行切换;在默认情况下,直接运行.exe程序的话,它仅显示帮助文本:
NMM工具可以响应来自浏览器扩展本身的NativeMessages,也可以代理现有扩展和现有NMH可执行文件之间的消息。
安装Demo扩展
要测试该工具的基本功能,您可以安装Demo Extension:
在Chrome或Edge中访问about://extensions
启用开发者模式
按下Load Unpacked按钮
选择sample-ext文件夹
一个新的 "N "图标将出现在工具栏上
安装完演示扩展后,还必须注册演示的Native Host应用。为此,请更新其清单,以反映您放置它的位置。
使用记事本或类似编辑器打开manifest.json文件
将path字段设置为.exe的完整路径。确保反斜杠都是成对使用的。
将allowed_origins字段设为来自about:extensions页面中的扩展的ID值。
接下来,更新注册表,以便浏览器能够找到您的主机:
在记事本中编辑installregkeys.reg文件,更新文件路径以指向manifest.json文件的位置。确保反斜杠都是成对使用的。
双击InstallRegKeys.reg文件将其导入注册表。
运行演示扩展
安装好了主机和扩展后,现在就可以测试该工具了。从工具栏中的扩展点击“N”图标,导航到它的演示页面。这时,NMM的实例应自动打开。
在Outgoing Messages框中键入“Hello World!”,单击Post Message to port按钮。这时,该消息应该出现在NMM应用程序内的Monitor选项卡上:
如果你勾选右上方的“Reflect to extension”选项,然后再次发送消息,应该会看到NMM工具收到消息,并将其发回该扩展的页面,并展示在“Incoming Messages”部分。
“Reflect to extension”将收到的信息复制给发送方
如果我们想通过NMM注入我们选择的新信息,该怎么办?
进入NMM的Injector选项卡,在底部输入框中输入一个简单的JSON信息。然后,点击“Send to Browser/Extension”按钮。这时,我们会看到该信息出现在浏览器内的“Incoming Messages”部分。
注意:你的信息必须是格式正确的JSON,否则它将永远无法到达。
好了,我们现在已经能够成功地使用NMM工具来接收和发送来自Demo扩展的消息了。
代理消息
虽然我们的演示扩展很适合测试Native Messaging功能,而且如果我们正在开发一个使用Native Messaging功能的新扩展,它可能会对模拟有所帮助,但本文的重点是监视现有扩展与主机之间的通信。
好了,那就开干吧。
首先,转到Configure Hosts选项卡,该选项卡在注册表中搜索您的PC上当前注册的所有本机主机(Native Host):
我们的计划是最终让拦截本机主机成为一种点击式体验,但目前,我们只是使用该选项卡来查找我们要拦截的本机主机的文件系统位置。如果某个条目多次出现,请选择优先级最低的实例。
例如,假设我们对Chrome浏览器中一些Windows-to-Web身份验证场景中使用的BrowserCore主机感兴趣。我们可以看到清单文件的位置,以及从清单文件中提取的EXE的名称:
在某些情况下,您可能会发现Exe字段显示“???”,如上面的vidyo条目那样。这是因为,如果清单文件无法解析为合法的JSON,就会出现这种情况。Chromium在宽松模式下使用定制的JSON解析器来解析清单,它允许JavaScript风格的注释。但是NMM工具使用严格的JSON解析器,无法解析这些注释。不过,这对我们的目的来说并不重要。
注意清单文件的位置,并在您选择的编辑器中打开它。注意:如果该文件在特权位置,您可能需要以更高的权限来打开您的编辑器(以管理员身份)。
提示:您可以通过Alt+DblClick选择一个项目,或者在选择该项目时点击Alt+Enter,以打开Windows资源管理器,找到清单的位置。
在清单中,通过在文件名末尾的.exe前引入.proxy一词来改变路径字段。
然后,请保存该文件。
注意:在某些情况下,即使是管理员也无法在默认情况下写入该文件。在这种情况下,你需要使用管理员的权限来取得文件的所有权,以授予自己修改文件的权限。
当然,也还有其他不需要改变文件系统权限的方法,但我们在这里就不做介绍了。
接下来,将nmf-view.exe文件复制到包含Native Host的文件夹中,并将其重命名为前面写入清单的文件名。
现在,我们已经成功安装了NMM代理。每当浏览器扩展下次试图启动Native Host时,它就会激活我们的NMM调试器,而NMM调试器又会生成原始的Native Host(在本例中是BrowserCore.exe),并代理两者之间的所有信息。
现在,请访问一个您可以登录的网站,如https://office.microsoft.com。然后,点击右上方的登录按钮,监视我们的调试器生成的Native Host,收集来自Windows 10 Accounts扩展的请求,将其传递给BrowserCore.exe,读取Host的回复,并将其传回扩展。我们的调试器允许我们从两个方向读取JSON消息的全文。
注意:这个截图是经过编辑的,因为它包含秘密令牌。
干的漂亮,是吧?
篡改消息
当我完成所有这些工作时,我很兴奋。同时,我也很失望……JSON的纯文本渲染并不具有很好的可读性,而且建立一个编辑消息的用户界面工作量也很大。我感叹……我在15年前就已经为Fiddler写好了我想要的所有代码。它同时具有JSON渲染和消息编辑功能……但是,现在我已经不再使用Fiddler,所以不能直接复制其源代码了。
然后,我突然想明白了。我不需要在NMM中重新实现Fiddler的部分功能。我可以让这些工具协同工作:NMM可以把它从浏览器扩展和Native Host收到的信息传递给Fiddler,如果Fiddler修改了信息,NMM就可以用修改后的信息来替代。
太棒了!
配置篡改过程
首先,重新编辑manifest.json文件,在路径中添加一个.fiddler组件,并将.proxy.exe文件重命名为.proxy.fiddler.exe,具体如下所示:
这段新的文字预示着你希望NMM开始使用Tamper using Fiddler选项设置。为了调试像BrowserCore.exe这样的“single-shot”本地主机,我们不能直接使用NMM的监控选项卡右上方的复选框,因为调试器和本地主机生成和完成事务的速度比我们这些弱小的人类点击鼠标的速度快得多。注意:您也可以指定字符串.log.,以启用将流量日志写到桌面上的选项。
现在,启动Fiddler;可以使用-noattach命令行参数,这样它就不会注册为系统代理。在Web Sessions列表下的QuickExec框中输入bpu ToApp并按回车键。
这将创建一个请求断点,对所有包含ToApp字符串的请求都会触发该断点,NMM用它来记录发送到原始Native Host的请求。
通过Fiddler的检查器,我们可以使用JSON Treeview、TextView或SyntaxView检查器来检查消息的JSON。
如果我们对消息感到满意,请点击Run to Completion按钮,这时,NMM应用程序就会把未经修改的原始消息发送到原始的Native Host。然而,如果我们想篡改消息,可以从下拉菜单中挑选一个成功响应,如200_SimpleHTML.dat:
这时,模板响应将出现在响应文本视图中:
现在,请用您想要使用的文本覆盖模板文本:
……然后按绿色“Run to Completion”按钮。这时,Fiddler将修改后的文本返回给NMM代理,然后NMM代理将修改后的消息传递给原始Native Host:
就这里来说,原始Native Host并不知道如何处理GetFiddledCookies请求,所以,它会返回一个错误,而该错误将传回浏览器。
提示:如果您的目标是篡改从Native Host发送到扩展的消息,请在Fiddler的QuickExec框中输入bpu ToExt。或者,您也可以使用Fiddler的其他篡改功能,比如让它只拦截包含某些文本的消息,自动重写某些消息,等等。
祝您阅读愉快!
本文翻译自:https://textslashplain.com/2022/01/08/debug-native-messaging/如若转载,请注明原文地址