Javascript 以不可检测的方式检查腹板箱框架
我如何在Chrome扩展或Firefox插件中以页面无法检测到的方式读取网页的WebSocket框架Javascript 以不可检测的方式检查腹板箱框架,javascript,google-chrome,google-chrome-extension,websocket,firefox-addon,Javascript,Google Chrome,Google Chrome Extension,Websocket,Firefox Addon,我如何在Chrome扩展或Firefox插件中以页面无法检测到的方式读取网页的WebSocket框架 提出了一个类似的问题,但是开发NPAPI插件不再有意义,因为它很快就会被删除。拦截WebSocket数据很容易。在页面构造WebSocket之前,只需执行以下脚本。此代码段猴子修补了WebSocket构造函数:当创建新的WebSocket构造函数时,代码段订阅消息事件,从中可以对数据执行任何操作 此代码段设计为与本机代码无法区分,因此页面无法轻松检测到修改(不过,请参阅本文末尾的备注) 在Chr
提出了一个类似的问题,但是开发NPAPI插件不再有意义,因为它很快就会被删除。拦截WebSocket数据很容易。在页面构造WebSocket之前,只需执行以下脚本。此代码段猴子修补了
WebSocket
构造函数:当创建新的WebSocket构造函数时,代码段订阅消息
事件,从中可以对数据执行任何操作
此代码段设计为与本机代码无法区分,因此页面无法轻松检测到修改(不过,请参阅本文末尾的备注)
在Chrome扩展中,该代码段可以通过运行在“document\u start”的with运行,请参阅
Firefox还支持,同样的逻辑也适用(使用contentScriptWhen:'start'
)
注意:前面的代码片段设计为在页面其余部分之前执行时与本机代码无法区分。检测这些修改的唯一(不寻常和脆弱)方法是:
- 将无效参数传递给WebSocket构造函数,捕获错误并检查依赖于实现(特定于浏览器)的堆栈跟踪。如果比通常多了一个堆栈帧,那么构造函数可能被篡改(从页面的角度看)
- 序列化构造函数。未修改的构造函数变成
function WebSocket(){[native code]}
,而修补的构造函数看起来像function(){[native code]}
(这个问题只出现在Chrome中;在Firefox中,序列化是相同的)
- 序列化
WebSocket.prototype.send方法。由于函数未绑定,因此序列化它(WebSocket.prototype.send.toString()
)将显示非本机实现。这可以通过覆盖.send
的.toString
方法来缓解,而页面又可以通过与函数.prototype.toString
进行严格比较来检测。如果不需要发送的数据,请不要覆盖OrigWebSocket.prototype.send
除了Rob W的方法外,还有一种完全屏蔽与页面交互的方法(对于Chrome)
也就是说,你可以拿出一些重炮来使用
请注意,使用它将阻止您打开相关页面的开发工具(或者更准确地说,打开开发工具将使其停止工作,因为只有一个调试器客户端可以连接)。这已经得到了改进,因为:可以连接多个调试器
这是一个相当低级的API;您将需要使用自己构建查询。此外,1.1文档中没有相应的事件,您需要查看
您应该能够接收类似的WebSocket事件,并检查它们的
payloadData
:
{"method":"Network.webSocketFrameSent","params":{"requestId":"3080.31","timestamp":18090.353684,"response":{"opcode":1,"mask":true,"payloadData":"Rock it with HTML5 WebSocket"}}}
{"method":"Network.webSocketFrameReceived","params":{"requestId":"3080.31","timestamp":18090.454617,"response":{"opcode":1,"mask":false,"payloadData":"Rock it with HTML5 WebSocket"}}}
应该提供一个起点
事实上,这里有一个起点,假设tabId
是您感兴趣的选项卡:
chrome.debugger.attach({tabId:tab.id}, "1.1", function() {
chrome.debugger.sendCommand({tabId:tabId}, "Network.enable");
chrome.debugger.onEvent.addListener(onEvent);
});
function onEvent(debuggeeId, message, params) {
if (tabId != debuggeeId.tabId)
return;
if (message == "Network.webSocketFrameSent") {
// do something with params.response.payloadData,
// it contains the data SENT
} else if (message == "Network.webSocketFrameReceived") {
// do something with params.response.payloadData,
// it contains the data RECEIVED
}
}
我已经测试过这种方法(链接的示例如上所述进行了修改),它很有效。只是为了给@Xan answer添加一个例外(我没有足够的代表对他的答案发表评论,所以我将其添加到这里,因为我相信它可以为其他人节省一些时间)
如果WebSocket连接是在通过about:
、data:
和blob:
方案加载的上下文中建立的,则该示例将不起作用
有关相关错误,请参见此处:只需连接WebSocket构造函数并注册一个消息侦听器。无论使用何种浏览器,这都将始终有效。@RobW,谢谢您的评论。WebSocket构造函数是由页面创建的,如果我创建了它,我就不会得到结果。你可以对构造函数进行猴子补丁。@RobW这是什么意思?在WebSocket函数中注入一些东西?您的赏金不会改变您的问题指定得非常糟糕的事实。目前还不清楚为什么当前的答案不能满足您的需要,这样Rob可能会得到(应得的)一半赏金。@wZVanG我已经编辑了答案并更新了片段。使用中的某个同步方法插入代码段,修改实际上是无法检测到的(不过请参见我答案末尾的注释)。@Noitidart的方法2和3是同步的,在Firefox中也可用。@wZVanG您可以覆盖Function.prototype.toString
,并返回匹配的自定义值如果输入是自定义构造函数,则为“reality”。但这反过来又可以通过创建新的脚本上下文(iframe)来解决并从该上下文中使用函数.prototype.toString
来获得真正的序列化。网页不太可能使用我笔记中的方法,因为这些方法非常复杂,并且输出是非标准的(并且在浏览器决定更改内部时可能会中断)@wZVanG不,因为正如我在前面的评论中解释的那样,那些专门针对我的答案中的代码的人可能会绕过它。如果你只重写构造函数而不是。send
,那么你是非常安全的,尤其是当你使用Firefox时。@wZVanG那么检测修改的唯一方法就是传递错误的参数向构造函数报告并检查错误的堆栈跟踪。这可以通过捕获错误、重写堆栈跟踪然后重新引用错误来应对。但是在从您的网站上看到pastebin后,我认为不需要这种额外的对策。问题是,这些事件不属于1.1协议的一部分。在内部,Dev工具使用更高的版本。你这是什么意思?我会有问题吗?不,我只是不确定它是否有效。现在我测试了它,它确实有效。@wZVanG Th
chrome.debugger.attach({tabId:tab.id}, "1.1", function() {
chrome.debugger.sendCommand({tabId:tabId}, "Network.enable");
chrome.debugger.onEvent.addListener(onEvent);
});
function onEvent(debuggeeId, message, params) {
if (tabId != debuggeeId.tabId)
return;
if (message == "Network.webSocketFrameSent") {
// do something with params.response.payloadData,
// it contains the data SENT
} else if (message == "Network.webSocketFrameReceived") {
// do something with params.response.payloadData,
// it contains the data RECEIVED
}
}