I recently found the site https://skribbl.io/ which is an online game where you have to guess what people are drawing.
It shows the word to guess at the top of the page, so the amount of letters in the word is known. After some time, one letter is revealed, and after some more time, a 2nd letter is revealed.
I noticed that the same words keep appearing again and again, so I was curious if you could cheat at the game by taking advantage of the known amount of letters.
I started making a list of words that appeared. Quickly looking at my list and randomly guessing helped me in a few cases, but I would like to really optimize my strategy. So here are my questions:
--> Is it possible to write a script that directly reads from the HTML and shows me the words that are likely to be the solution?
If it is not possible in the browser, is it maybe possible to read from text file somewhere and have a luascript figure out the solution?
If the game is written in HTML and java script, the field that shows the partially filled out text is probably a text field that can be read.
You can write JavaScript of your own and run it on any site you like. So you could write JavaScript that reads this text field and writes its guesses somewhere. Look up a script called Tampermonkey or Greasemonkey to learn more about ‘user scripts’.
You don't need to install Greasemonkey to do these types of tests. In Firefox you can hit Ctrl+Shift+C, bring up the JS console, and just start entering commands and playing with the webpage. You only need Greasemonkey to run the script every time you load the page.
Also, be aware that some web engines obfuscate the page to make reverse engineering harder to do, and also that what you're trying to do probably violates the site's terms of service, and you can get banned.
Depending on how it's implemented, you may not be able to get the whole word during the drawing process. It may well be (and will be, if the implementation is smart) that the browser does not get the word at all during the drawing process, and even when one or two letters are revealed, the browser only gets those letters and nothing else. The server sends the browser the whole word only when it's supposed to show it. That way there's absolutely no way of cheating in this manner.
At least if the implementation is smart, as said.
I understand that finding a cheat is an interesting intellectual exercise and hacking challenge, but in the end... what's the point? If you succeed in creating a cheat, you'll just be ruining the game for yourself, and everybody else.
Yes, this is just a little challenge. I don't think every single player at skribbl.io will somehow catch wind of what I'm doing (since tasvideos forums don't appear in google anyway) and if they do - which I highly doubt - it may motivate the game creator to make his game more robust. I do not think I will be playing very long in any case. The game is getting old after a while. It's not like there is a leaderboard or anything that you could aim for 1st place.
Ideas to make the game robust:
Don't make length of word public knowledge
Add tons of more new words
Instead of writing timer and current word to HTML, draw it in a Canvas.
You might be right. But then again, what I'm doing hardly qualifies as reverse engineering. I'm not digging in the game script or changing anything. All I do is see this HTML:
And trying to run something that compares against a list of known words.
I would run my script outside of the webpage if I could. For example, if it is possible to open the website HTML from file, I would write a luascript (since I'm better at lua than javascript/HTML/HTML5).
Can the site owner detect if I'm running a custon script? Can he see what's inside the script?
Here is as far as I got:
Language: javascript
var list = document.createElement("ul");
var sol1 = document.createElement("li");
var sol2 = document.createElement("li");
var sol3 = document.createElement("li");
var sol4 = document.createElement("li");
sol1.setAttribute("id", "sol1");
sol2.setAttribute("id", "sol2");
sol3.setAttribute("id", "sol3");
sol4.setAttribute("id", "sol4");
var text1 = document.createTextNode("<1>");
var text2 = document.createTextNode("<2>");
var text3 = document.createTextNode("<3>");
var text4 = document.createTextNode("<4>");
sol1.appendChild(text1);
sol1.appendChild(text2);
sol1.appendChild(text3);
sol1.appendChild(text4);
list.appendChild(sol1);
list.appendChild(sol2);
list.appendChild(sol3);
list.appendChild(sol4);
var bar = document.getElementsByClassName("gameHeader")[0];
bar.appendChild(list);
//list of possible solutions should be created right after the current word, but it's not working ...
//Also, optional TODO: Show the length of the word somewhere.
currentWord = "";
currentWordLength = 0;
Solutions = {"","","",""};
table = {};
table[4] = [
"afro",
"arch"]; // The list is much longer, but I don't want to ruin the game by making possible words public knowledge.
table[5] = [
"alien",
"angel" // The list is much longer, but I don't want to ruin the game
];
// for now, I'm only working with 4 and 5 letter words.
function fetchWord() {
currentWord = document.getElementById("currentWord").innerHTML;
currentWordLength = currentWord.length
}
function updateSolution() {
// When at least 1 letter is not a "_", compare the word against the list above.
// If it is a 4 letter word, compare against table[4], if it is 5 letters, compare against table[5].
// Then spit out possible solutions and change the unordered list we created at the top of this script.
}
fetchWord()
updateSolution()
//TODO: Create a button that runs fetchWord() and updateSolution()
//OR make the script auto-update when the timer reaches 30 and 15 seconds (I believe this is when 1st and 2nd letter is revealed).
For example, if the word is
_ r _ _ _
then I know the word is 5 letters long and possible words are:
bread
cream
dress
prune
truck
wrist
When it becomes
_ r _ _ e
then the only possible outcome is that it is "prune" or a new word.
Warp is right. Look into game.js if you wish to confirm this, using the dev tools. You can use a beautifier (built into Firefox devtools) and then an IDE like WebStorm to make sense of what's going on. (I'm not saying anything else due to their RE clauses.)
As for how you plan to cheat, the idea is right. Note that some words have unusual patterns: not all words are full words. Some 'words' have spaces in them, and some have dashes. These are the only patterns I have seen.
However, it is not very fast. You will get the word every time, but only after a significant delay (the first letter reveal) and other people might guess before you in that time, if the drawer is good. Another exploit is to iterate all the words that correspond to the current word template (if there are three letters, then you know the word is a three letter one, and your cheat can type all three letter words.) There is no limit to the number of guesses you can make.
Another idea is that the game tells you when you are close to the answer. If the word is 'rat', and you type 'at', the game answers " 'at' is close! ". This happens if the current guess is one letter off the answer.
Two uses for this:
- Poke for words stealthily. If you seem to spamming randomly in chat, people will not suspect cheating, when in reality you are poking around. When you get a match, type the word.
- Cut number of guesses. Say you have the word 'cab' and 'rat' in your wordlist, and the letter a is revealed. Given these are the only two words in your wordlist, poke for the first by typing 'ab'; if it does not work, then it is the other word.
xy2, thanks for your post. Did you research the game or have you been playing on skribbl.io independently?
I think I once saw someone get kicked after they spammed in the chat, so I'm not sure.
Guessing in the chat is fine, and lots of people do it anyway. But guessing every single word is going to be suspicious, indeed.
I researched the game following your post. I played for a while (if you saw someone named God, that was me) to get how the game itself worked and its rules, then did a bit of 'RE' (the code isn't obfuscated, so not a lot of RE) to confirm what Warp said. Once you have a grasp on how the game works and how it's made, then it becomes much easier.
However, I had no experience in JS before this (quickly learned the syntax at learn x in y minutes and looked up whatever I needed afterwards.) So it is a very surface approach and I recognize my un-skilledness; you should dive deeper yourself if you want concrete, unquestionable answers.
From what I saw, you could make around ~100 guesses in a round pretty easily. I never saw someone getting kicked, even when spamming answers myself, so something to look into.