从 Chrome 扩展中挂钩 Websocket

Posted

技术标签:

【中文标题】从 Chrome 扩展中挂钩 Websocket【英文标题】:Hooking Websockets from a Chrome Extension 【发布时间】:2018-10-04 15:32:55 【问题描述】:

我正在尝试创建一个可以挂钩特定页面的 WebSocket 的 Chrome 扩展内容脚本。当前,当页面被访问时,内容脚本会像这样将另一个脚本注入页面:

    var s = document.createElement('script');
    s.src = chrome.extension.getURL('Script.js');
    s.onload = function () 
        this.remove();
    ;
    (document.head || document.documentElement).appendChild(s);

然后我的 Script.js 包含 websocket 的 addEventListener。

Window.WebSocket.addEventListener("message",function(event)
console.log("Websocket read");
)

但是当我运行扩展时,我收到一个错误,无法读取未定义的属性 addEventListener。所以我不完全确定这是否是正确的方法。我已经验证脚本确实被注入了页面,但是我将如何在页面的原始 onmessage WebSocket 之上覆盖或创建自己的侦听器。有可能吗?

【问题讨论】:

你能试试像window.WebSocket.addEventListener这样的小写窗口吗? 您好,当我将其更改为 window.WebSocket.addEventListener 时,我收到此错误:Uncaught TypeError: window.WebSocket.addEventListener is not a function 使用onmessage 代替window.WebSocket.onmessage = function(event) console.debug("WebSocket message received:", event); ; 你在哪里定义了Window.WebSocket?我不是 chrome 扩展的专家,但我认为这是错误的。在 javascript 中,您应该首先使用 new 关键字创建一个 websocket 实例。 这能回答你的问题吗? ***.com/questions/22868897/… 【参考方案1】:

您可以使用 wshook 覆盖原来的 WebSocket 类并添加可用于任务的回调

您可以直接复制脚本wsHookjs并粘贴到您的代码之前,或者像普通的javascript一样导入然后开始使用它。

导入库

<script src='wsHook.js'></script>

那么你可以只为之前或之后或两者添加回调来拦截 websocket 发送请求:

wsHook.before = function(data, url, wsObject) 
    console.log("Sending message to " + url + " : " + data);


// Make sure your program calls `wsClient.onmessage` event handler somewhere.
wsHook.after = function(messageEvent, url, wsObject) 
    console.log("Received message from " + url + " : " + messageEvent.data);
    return messageEvent;

注意:内容脚本可以在页面加载之前加载。有关如何在页面加载之前加载内容脚本的更多信息,您可以查看此post

【讨论】:

这似乎不是我正在寻找的解决方案,因为我不是部署或发布网站或页面的人。相反,我试图将通用脚本注入其他网站或页面,这些网站或页面利用 websockets 并挂钩该特定实例。 @Akali 您可以在页面加载之前注入脚本,有关如何在页面加载之前加载内容脚本的更多信息,请查看here。 你是在暗示我注入了 wsHook.js 的完整性? 即使我的内容脚本在页面加载之前运行,然后我是否会将 @Akali 您不需要在任何网站中注入脚本标签,只需覆盖WebSocket,这是在您加载内容脚本后由wshook 脚本完成的WebSocket 将由库包装,然后将加载页面,该页面将使用更新后的WebSocket【参考方案2】:

WebSocket 是一个类。 addEventListener 函数仅在类的实例中可用。因此,您必须找到网页创建的变量并将侦听器添加到该变量中。例如:

var mySocket = new WebSocket("wss://127.0.0.1:8080");

你会做这样的事情:

mySocket.addEventListener("message", (e) => console.log(e));

但是,这会丢失所有初始消息,这取决于您是否能够访问变量,这在所有情况下可能都不可能。

相反,您可以用自己的类覆盖该类,这样当他们创建 WebSocket 实例时,它实际上就是您的类。

一个例子是这样的:

class MyWebSocket extends WebSocket

    __constructor()
    
        super(...arguments);
    

    addEventListener(name, callback)
    
        // call the original event listener
        super.addEventListener(name, function()
        
            console.log("Im sneakily listening in here", arguments);

            // call their callback
            callback(...arguments);
        );
    


// Override the real web socket with your version
window.WebSocket = MyWebSocket;

请记住,上面的代码是伪代码,未经测试。

如果您只想查看套接字数据。您可以打开 chrome 开发工具,单击“ws”过滤器。然后单击列出的 Web 套接字并查看正在传输的原始数据。

这是一个可以在您的上下文脚本中使用的工作示例。

while(document == null || document.head == null);

var s = document.createElement("script");

function hookWebSocket()

    window.RealWebSocket = window.WebSocket;

    window.WebSocket = function()
    
        var socket = new window.RealWebSocket(...arguments);

        socket.addEventListener("message", (e) =>
        
            console.log("The message is: ", e);
        );

        return socket;
    


s.innerhtml = `
    $hookWebSocket.toString()

    hookWebSocket();
`;

document.head.prepend(s);

【讨论】:

是的,我知道如果您找到该变量,则可以这样做,但这不是为依赖它的每个可能站点查找 websocket 变量的通用解决方案。这就是为什么我希望有一种方法可以在内部挂钩它。但我确实认为覆盖 WebSocket 类以便我的实例化而不是原始类可能是唯一的解决方案。 @Akali 我添加了一个工作示例供您使用。 所以这实际上是在文档头部附加或插入脚本标签,然后从那里挂钩 websocket? @Akali 这是一个宾果游戏【参考方案3】:

你可以试试这个吗?

s.onload = function () 
  this.parentNode.removeChild(this);
;

【讨论】:

脚本的注入部分不能正常工作。

以上是关于从 Chrome 扩展中挂钩 Websocket的主要内容,如果未能解决你的问题,请参考以下文章

在 chrome 扩展中,如何从当前 chrome 用户以外的 gmail 用户获取访问令牌?

Chrome 扩展 - 从网页中检索全局变量

从 Chrome 扩展程序访问网页的 localStorage

如何从 chrome 扩展中读取文件?

chrome 更新后,jQuery ajax 调用无法从网页解码为 utf-8 字符集到 Chrome 扩展中

从 chrome 扩展写入数据库