Skip to content

Instantly share code, notes, and snippets.

@Xaekai
Forked from twilight-sparkle-irl/userscript.md
Created August 18, 2016 04:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xaekai/6f56a863b8e679dfdaa153ac5efec3a2 to your computer and use it in GitHub Desktop.
Save Xaekai/6f56a863b8e679dfdaa153ac5efec3a2 to your computer and use it in GitHub Desktop.
Aggressive Userscripting For Et Cetera

So, recently I've seen an uptick in stuff like SystemJS and Webpack on the clientside.
This basically kills userscripting, which is very rude.
However, you can still get around this by completely proxying everything.

Let's take pony.town for example. A very antiuserscripting site.

What you'll want to do is download the script used to bootstrap and edit it to your hearts desire. You can do this by popping open the inspector, and looking for the path needed. I have an old script that you can adapt if you so desire. Instead of having to access and overwrite things from window, without the contexts needed and being unable to peek inside closures, you can now just serve up your own modifications to the script. The real issue is serving it.

Now, for Windows, Burp Proxy and Fiddler should have built in proxy interception functions. (Mac and Linux users can use burp proxy too but it's not meant for this so eh)

However, Linux can do something much more advanced. If you have node.js, you can use something like this script to proxy requests. (http-proxy module is the only requirement)

var http = require('http'),
    httpProxy = require('http-proxy'),
    fs = require('fs'),
    path = require('path');
    
var proxy = httpProxy.createProxyServer({
  target: {
    host: 'example.com',
    port: 80
  }
});

var server = http.createServer(function(req, res) {
  console.log(req.url)
  if (req.url === "/script.js") {
    fs.createReadStream(path.join(__dirname, 'script.js')).pipe(res)
  } else if (["/"].indexOf(req.url) > -1) {
    fs.createReadStream(path.join(__dirname, 'index.html')).pipe(res)
  } else {
    proxy.web(req, res);
  }
});

server.on('upgrade', function (req, socket, head) {
  proxy.ws(req, socket, head);
});

console.log("listening on port 8000")
server.listen(8000);

If you want to modify this, you'll want to edit the var server declaration. req.url is what the requested item is, and fs.createReadStream(path.join(__dirname, 'script.js')).pipe(res) is just piping script.js from the current working directory as a response. proxy.web(req, res) merely proxies the request instead of intercepting it. Any other info can be gotten from the node-http-proxy documentation and the default node module http documentation

If you have to deal with /etc/hosts and very picky userscripts, you can edit /etc/hosts to point picky.example.com somewhere else (picky.example.com 127.0.2.1 pickyexample), and then set target to "picky.example.com"

The dot at the end causes it to ignore /etc/hosts due to it being fully qualified.

For example, here's a full tar.gz of the required setup for pony.town, which requires ssl and correct domain name. You can peek around and see what I had to do (generate an ssl cert, the mods to the nodejs script, etc) However, if you have issues with the dot at the end, you can always try and use the IP. For example, 138.201.14.251 is the IP for pony.town.

Either way, with configuration, you now have full control over what the server sends you and therefore what it sees and what the client sees.

Have fun!

Next up: Me creating/implementing a format for flexible diffing so "oh shit, the devs updated, time to copy and paste" is a thing of probably not going to happen as much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment