以不可检测的方式检查WebSocket框架。

问题描述 投票:6回答:2

我如何在 Chrome 扩展或 Firefox 附加组件中读取网页的 WebSocket 框架,而不被网页检测到?

从 Chrome Dev Tools 扩展检查 WebSocket 框架。 制定一个类似的问题,但开发一个NPAPI插件已经没有意义,因为它很快就会被删除。

javascript google-chrome google-chrome-extension websocket firefox-addon
2个回答
11
投票

除了 Rob W 的方法外,还有一种方法可以完全掩盖与页面的任何交互 (用于Chrome浏览器)

也就是说,你可以干掉一些重炮,然后使用 chrome.debugger.

请注意,使用它将阻止你打开相关页面的Dev Tools(或者更准确地说,打开Dev Tools将使其停止工作,因为只有一个调试器客户端可以连接)。 此后,这个问题得到了改进:可以连接多个调试器。

这是一个相当低级的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
  }
}

我已经测试了这个方法(修改了上面的链接示例),它是可行的。


21
投票

拦截WebSocket数据很简单。只需在页面构建WebSocket之前执行以下脚本即可。这段代码是对 WebSocket 构造函数。当一个新的WebSocket构造函数被创建时,该代码段会认购 message 事件,在那里你可以对数据做任何你想做的事情。

这个代码段被设计成与原生代码无法区分,因此修改不会轻易被页面检测到(不过,请参见本文章末尾的备注)。

(function() {
    var OrigWebSocket = window.WebSocket;
    var callWebSocket = OrigWebSocket.apply.bind(OrigWebSocket);
    var wsAddListener = OrigWebSocket.prototype.addEventListener;
    wsAddListener = wsAddListener.call.bind(wsAddListener);
    window.WebSocket = function WebSocket(url, protocols) {
        var ws;
        if (!(this instanceof WebSocket)) {
            // Called without 'new' (browsers will throw an error).
            ws = callWebSocket(this, arguments);
        } else if (arguments.length === 1) {
            ws = new OrigWebSocket(url);
        } else if (arguments.length >= 2) {
            ws = new OrigWebSocket(url, protocols);
        } else { // No arguments (browsers will throw an error)
            ws = new OrigWebSocket();
        }

        wsAddListener(ws, 'message', function(event) {
            // TODO: Do something with event.data (received data) if you wish.
        });
        return ws;
    }.bind();
    window.WebSocket.prototype = OrigWebSocket.prototype;
    window.WebSocket.prototype.constructor = window.WebSocket;

    var wsSend = OrigWebSocket.prototype.send;
    wsSend = wsSend.apply.bind(wsSend);
    OrigWebSocket.prototype.send = function(data) {
        // TODO: Do something with the sent data if you wish.
        return wsSend(this, arguments);
    };
})();

在Chrome扩展中,该代码段可以通过以下方式运行 脚本run_at:'document_start'使用内容脚本在页面上下文中插入代码。.

火狐也支持 内容脚本,同样的逻辑也适用于(与 contentScriptWhen:'start').

注意:前面的代码段被设计成在页面的其余部分之前执行时与本地代码无法区分。检测这些修改的唯一(不寻常和脆弱的)方法是。

  • 将无效参数传递给WebSocket构造函数,捕捉错误并检查与实现相关的(浏览器特定的)堆栈跟踪。如果比平时多了一个栈帧,那么构造函数可能被篡改了(从页面的角度看)。

  • 对构造函数进行序列化。未修改的构造函数会变成 function WebSocket() { [native code] }而一个打了补丁的构造函数看起来像 function () { [native code] } 这个问题只存在于Chrome浏览器中;在Firefox中,序列化是相同的)。

  • 序列化 WebSocket.prototype.send 方法。由于函数没有被绑定,因此将其序列化 (WebSocket.prototype.send.toString())揭示了非本地实现。这种情况可以通过覆盖 .toString 方式 .send,而该页面又可以通过严格的对比与 Function.prototype.toString. 如果你不需要发送的数据,不要覆写 OrigWebSocket.prototype.send.

© www.soinside.com 2019 - 2024. All rights reserved.