2

I am using solutions provided in following topics to inspect WebSockets traffic (messages) on the web page, which I do not own (solely for learning purposes):

Like this:

(function(){
var ws = window.WebSocket;

window.WebSocket = function (a, b, c) {
   var that = c ? new ws(a, b, c) : b ? new ws(a, b) : new ws(a);
   that.addEventListener('open', console.info.bind(console, 'socket open'));
   that.addEventListener('close', console.info.bind(console, 'socket close'));
        that.addEventListener('message', console.info.bind(console, 'socket msg'));
        return that;
    };

    window.WebSocket.prototype=ws.prototype; 
}());

The issue with the provided solutions is that they are listening on only 1 of 3 WebSocket connections ("wss://..."). I am able to see in the console the messages that I receive or send, but only for one connection.. Is there something I am missing? Is it possible that two other service are any different and prohibiting the use of prototype extension technique?

p.s. I will not provide an URL to the web resource that I am doing my tests on, in order to avoid possible bans or legal questions.

Alex
  • 4,607
  • 9
  • 61
  • 99
  • There are two possibilities, I think. One is `iframe`s and the like. The other is that the value of `windows.WebSocket` is grabbed by other scripts before you can update it in your script and it just happens that one of them is doing it a little late. – Ouroborus Jun 29 '19 at 20:03
  • @Ouroborus I couldn't figure out how to solve this issue.. there seemed to be no iframes.. So I used another approach which you can check in the answer section below. – Alex Jul 23 '19 at 07:51

1 Answers1

1

Okay, since it's been weeks and no answers, then I will post a solution which I ended up using.

I have built my own Chrome extension that listens to WebSocket connections and forwards all requests and responses to my own WebSocket server (which I happen to run in C#).

There are some limitations to this approach. You are not seeing the request header or who is sending the packets.. You are only able to see the payload and that is it. Also you are not able to modify the contents in any way or send your own requests (remember - you have no access to header metadata). Naturally, another limitation is that you have to be running Chrome (devtools APIs are used)..

Some instructions.

Here is how you attach debugger to listen to network packets:

    chrome.debugger.attach({ tabId: tabId }, "1.2", function () {
        chrome.debugger.sendCommand({ tabId: tabId }, "Network.enable");
        chrome.debugger.onEvent.addListener(onTabDebuggerEvent);
    });

Here is how you catch them:

function onTabDebuggerEvent(debuggeeId, message, params) {
    var debugeeTabId = debuggeeId.tabId;

    chrome.tabs.get(debugeeTabId, function (targetTab) {
        var tabUrl = targetTab.url;

        if (message == "Network.webSocketFrameSent") {

        }
        else if (message == "Network.webSocketFrameReceived") {
            var payloadData = params.response.payloadData;

            var request = {
                source: tabUrl,
                payload: params.response.payloadData
            };

            websocket.send(JSON.stringify(request));
        }
    });
}

Here is how you create a websocket client:

    var websocket = new WebSocket("ws://127.0.0.1:13529");

    setTimeout(() => {
        if (websocket.readyState !== 1) {
            console.log("Unable to connect to a WebsocketServer.");
            websocket = null;
        }
        else {
            console.log("WebsocketConnection started", websocket);

            websocket.onclose = function (evt) {
                console.log("WebSocket connection got closed!");

                if (evt.code == 3001) {
                    console.log('ws closed');
                } else {
                    console.log('ws connection error');
                }

                websocket = null;
            };

            websocket.onerror = function (evt) {
                console.log('ws normal error: ' + evt.type);
                websocket = null;
            };

        }
    }, 3000);

Creating the server is outside the scope of this question. You can use one in Node.js, C# or Java, whatever is preferable for you..

This is certainly not the most convenient approach, but unlike java-script injection method - it works in all cases.

Edit: totally forgot to mention. There seems to be another way of solving this, BUT I have not dig into that topic therefore maybe this is false info in some way. It should be possible to catch packets on a network interface level, through packet sniffing utilities. Such as Wireshark or pcap. Maybe something I will investigate further in the future :)

Alex
  • 4,607
  • 9
  • 61
  • 99