Reverse Engineering onemillionchessboards.com Frontend with DevTools to Build a Bot
A twitter user by the name of nolen has once again released another banger website, onemillionchessboards.com. Its not to hard to understand what this website is about….
TLDR: its 1 million chessboards… with some caveat rules that apply to make it more fun.
I played around with it for a bit and enjoyed it but I was more interested about how things were built so I decided to look under the hood.
The creator shared on twitter a little of how is app works on the backend:
On the front-end, I wanted to see if the user checks matched the back-end checks and while I didn’t verify everything, it was pretty robust.
So I did the next best thing and decided I would make a bot instead. The bot would make moves so fast it can survive easily and eat as many pieces as possible in the process.
Reversing applications using local JavaScript file overrides
The frontend is using React which we can see easily from the React Developer Tools Extension lighting up:
I actually don’t know how to use the react developer tools plugin so instead I decided to look at the raw JavaScript using the built-in Chromium DevTools and modify the functionality from there by overwriting the JavaScript file myself with a local file:
With this I now have the ability to modify front-end code, add functionality, remove client-side security checks and what not. This makes it very convenient especially with applications that deal with web sockets as having to recreate the full initialisation, security checks and compression might not be easy to see from a simple web-socket proxy (ie. Burpsuite).
There s also a few built-in functionalities that help with reversing the code.
Pretty Printing
The code is minified but you have the ability to unminify it (pretty print) so that its easier to read and modify:
Using JavaScript breakpoints
You can also add breakpoints in your custom file as such:
They will trigger when the code reaches your breakpoint and you can use it to see the values of each variables, which could help reversing the application:
Note
It’s not a foolproof method and may end up crashing the tab when you make changes. In this case, its usually easier to close the tab and reopen it:
Reversing the onemillionchessboards application
With these functionalities in mind, we can now look at reversing the frontend application code. I usually like to start with functions that talk to the backend since they’re the ones that will have an impact on the application in the end. So I search for any backend requests via WebSockets, HTTP(S) requests or else.
For this application, I found the function that sends a msg via a websocket to the backend when a move is made, the $1a465e5e0e1a643e$var$protoSendMove
function:
The arguments are not minified so its fairly easy to guess what each argument does:
ws
is the websocket itselfpiece
is the piece we want to movetoX
is the x location we want to move totoY
is the y location we want to move tomoveType
andmoveToken
are the only two interesting ones here since its uncertain what they mean.
By doing a bit more digging, we can find references to MoveType
around the application and see that it’s basically an integer value that can denote a normal move, a castle move or en passant move:
By checking where the $1a465e5e0e1a643e$var$protoSendMove
function is called, we can see what moveToken
is generated from the getIncrMoveToken
function:
Going one step further, we can see that it’s basically a token that gets sent with our request and gets incremented on every move made:
So now we know how to make moves via code directly.
From here, I looked around and found a getMoveableSquares
function that returns which squares you are allowed to move to but also which squares will end up capturing a piece which is really convenient since we can use that to prioritise our moves later on:
When looking at the Map returned by the getMoveableSquares
function we can see the captured pieces:
With all that in mind we can make a function that moves a piece we selected to a nearby moveable square, prioritising squares that end up capturing an opponent’s piece:
Note
This function could obviously be improved a lot more to make a more intelligent bot (eg. retrieve the full map and optimise moves based on that). Nevertheless, this is only an example to showcase what can be done by simply using built-in DevTools.
makeMove
is a custom function which reuses the code from the message create function we found earlier:
Now that we have this, we just need to wrap the code in an interval so that it triggers often (while making sure we don’t trigger too much to overwhelm the server or have our moves dropped).
In the end, I decided to modify the $a2d3bef833187ce9$export$474cd6ee072cf5a4
function which is called when you select a chess piece as it already has all the handlers I need to make the bot work. It also allows means I don’t have to create a button or anything and can simply select any piece to start the bot.
I added a startConquest
function here:
The function is basically an “interval” version of the function described previously:
gws is a global variable which holds the websocket object that I populate during initialisation. Tried to get it dynamically using
$parcel$interopDefault
but since its a react minified file, scopes are protected by exports and what not and I couldnt make it work so resorted to using a global variable (not ideal but its also only a PoC so not a huge problem).
The bot in action
In the end the result is pretty cool, I can just select any piece and they will start zooming around randomly, eating as many of the opposing pieces as possible.
Conclusion
DevTools are great to create PoCs, reverse engineer applications and can help when validating security checks, especially when dealing with web-sockets and the likes. They give a lot of power to the user and can drastically increase reverse engineering speed as they don’t require you to recreate the whole functionality to test things.
Overall, a great tool to have in your arsenal.