Reputation: 3613
I'm trying to create a Chrome extension content script which can hook the WebSocket of a specific page. Currently when the page is accessed, the content script injects another script into the page like so:
var s = document.createElement('script');
s.src = chrome.extension.getURL('Script.js');
s.onload = function () {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
Then my Script.js contains an addEventListener for the websockets.
Window.WebSocket.addEventListener("message",function(event){
console.log("Websocket read");
})
But when I run the extension I receive an error can not read property addEventListener of undefined. So I'm not entirely certain if that's the correct way to do it. I have verified that the script does get injected the page but how would I override or create my own listener on top of original onmessage WebSocket from the page. Is it possible?
Upvotes: 5
Views: 3699
Reputation: 6268
WebSocket
is a class. The addEventListener
function is only available in an instance of the class. So you must find the variable the web page creates and add the listener to that. For example:
var mySocket = new WebSocket("wss://127.0.0.1:8080");
You would do something like:
mySocket.addEventListener("message", (e) => console.log(e));
However, this will miss all the initial messages and it depends on you being able to get access to the variable which may not be possible in all situations.
Instead, what you can do is override the class with your own class so that when they create a WebSocket
instance, its actually your class.
An example of that would be something like:
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;
Keep in mind the above code is pseudo and untested.
If you just want to see the socket data. You can open chrome dev tools, click the "ws" filter. Then click on the web socket listed and view the raw data being transferred.
Here is a working sample that should work from your context script.
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);
Upvotes: 3
Reputation: 11797
You can use wshook
which overrides the original WebSocket
class and add callbacks which can be used for the task
You can directly copy the script wsHookjs
and paste before your code or import like normal javascript and then start using it.
Import the library
<script src='wsHook.js'></script>
then you can just add callbacks for either before or after or both to intercept websocket send request:
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;
}
Note: Content Script can be loaded before page load. For more information about how to load content script before page load you can check this post
Upvotes: 1
Reputation: 36
Could you try with this?
s.onload = function () {
this.parentNode.removeChild(this);
};
Upvotes: 0