📜 ⬆️ ⬇️

The game "guess anime on frame" - protection against cheating

Probably, many participated in games where you had to guess a movie or a series of shots from it. Very often, these tops-games are found on the forums. And recently I was shown a site entirely dedicated to guessing anime by frame. With an automated game: taking into account points, with options for answers.

After several games, my interest as an anime artist was satisfied, and an IT person woke up in me. It became interesting, and what is on the site protection from cheating. In the course of a brief analysis, it turned out that with cheat protection everything is sad, you can even hack the game with basic knowledge of JS. Here I would go out to my IT interests, but no, I wondered what was to be done to protect such a game from cheaters. So this article appeared.

(picture to attract attention)

Then I will talk about the weak points found in the game and about the methods of protection against cheating for such games that I managed to invent.

The essence of the game


At each step, the player is shown a frame from the anime and 4 possible answers, of which 1 is correct. The game goes to the first incorrectly guessed frame. For each frame, the player is given 15 seconds. Also, once you can skip a frame or use the hint "50 to 50".
')

Technical details and "hacking" of the game


Looking at the URLs of the site pages, I easily found that it works in PHP. And the fact that the game took place without reloading the page spoke of using AJAX. Client functionality was in the only script game.js.

The first thing that disappointed me about the security of the game is that game.js is not obfuscated. Extra spaces have been removed there, but, apart from this, the code is in its original form.

But it was still sadder. Running Firebug and looking at the contents of the AJAX responses, I found one very interesting option.

Yes, this parameter contained nothing more than the index of the correct answer, from 0 to 3. I didn’t expect that everything would be so simple that it wasn’t even interesting. Hopes that it will be necessary to connect Google Images for guessing, collapsed.

Then there was the matter of technology. First of all, I passed the code from game.js through JS Beautifier, having received readable code. The code was pretty simple and without any protection. AJAX responses were processed in the startGame function. It only remained to override this function. For this, I connected a small greasemonkey script.

In the script, I simply highlighted the desired button using the response number received from the XML. Subsequently made automatic pressing it in 2 seconds. I will not give the code, so as not to indulge the cheaters, let them think at least a little if they wish. There are literally 3 lines. But I was surprised that with such protection no one with the maximum number of points appeared in the top.

Weak points of the game and protection from cheating


The transfer of the correct answer together with the options and the riddle is difficult even to call a weak point, the authors in general, most likely, did not think about the cheaters. The correct answer number, of course, should be saved to the session and checked on the server side, which is easy to do with PHP.

The first thing I’ll consider is protection on the client side. The game has two limitations in JS: it ends automatically if the time to guess a frame has expired, or in the case of switching to another window. I do not quite understand why to prohibit switching to another window, while time is already limited. Only if the player does not quickly google the frame. But so decided the creators of the site.

Protection against switching to another window.
Its weak point is that JS is completely under the control of the client. Fully solve the problem can not, you can only make it difficult for an attacker to break. In order to somehow protect the game from JS changes, it, of course, needs to be obfuscated. It would be very good to generate and obfuscate js-file on the fly every time the page loads, putting there different functions for calculating a certain token that would be tested via AJAX. So it would be difficult for an attacker to spoof JS. It is difficult, but not quite.

In the end, to disable protection from switching to another window, you only need to override window.onblur. But even this can be solved by periodically checking whether the event handler of this event has been redefined.
var onblur_handler = function() { alert('game over'); }; window.onblur = onblur_handler; var check_onblur = function() { if (window.onblur !== onblur_handler) { alert(', !     IP.   !'); window.onblur = onblur_handler; } } setInterval(check_onblur, 2000); // evil code setTimeout(function() { window.onblur = function() { console.log('cheating'); }; }, 2500); 

An attacker, of course, may not execute our JS at all, but if it is obfuscated, and even contain some tokens for an AJAX request, this will cause trouble.

Thus, it turns out that our application will have to send a response number and a token received from JS to the server; and receive from the server a link to the next image and response options.

Time limit
With a time limit, you can do the same, leaving protection on the client side. But you can insure, checking the time and on the server. But it is worth considering that the picture is not instantly displayed at the client, and after clicking on the button, the request to the server does not come immediately either. Therefore, you need to give the client some odds compared to the server. It would be ideal to analyze the “lag” of the client, and take action only if it is significant.

Frame repetition.
This problem is not entirely related to security, but I will consider it too. The bottom line is that once frames are randomly selected, then within one game two frames can match. It is not right. Solve the problem can be quite simple. Given that the total number of frames is not very large, you can load all frames (or rather, their identifiers) into the array when you start the game, sort it randomly, save the array into the session, and take turns issuing frames to the player. In PHP, random sorting is just a function.
 shuffle($screenshots); 

Links to screenshots.
Another weak point of the game - links to screenshots. On the website of the game, they all have the format of the form /web/ANIME_ID/SCREENSHOT_INDEX.jpg, that is, the answer is already displayed in the address of the picture. Therefore, it is not necessary to give direct links to screenshots at all. You can always give a screenshot with PHP using the same address. Just before each new riddle you need to save to the session the identifier of the selected frame and send this frame when accessing a specific php script.

The problem of the finite number of screenshots.
Finally, the most difficult problem. The fact is that the number of frames is limited, so in new games they will be repeated. An attacker can simply write a program that collects all the frames and the corresponding anime. After that, it remains only to compare the current frame with all saved sets using another program. I note that if the problem of links would not have been solved, it would be enough for an attacker to compare only the links.

In fact, any player with time can remember the frames that will be repeated. But unlike cheaters, he will do it on his own. To combat the cheaters, it only remains to complicate the process of software frame comparison.

To achieve the goal, it will be necessary to make changes to the frame each time the user is transferred. If you do not do this, it will be easy for an attacker to find two identical files of the same frame. You can change the pictures using the GD library, included in the PHP package.

The simplest is to randomly change the quality of the JPEG transmitted to the client.
 function open_screenshot($filename) { return imagecreatefromjpeg($filename); } function echo_screenshot($image) { $quality = rand(60, 100); ob_start(); imagejpeg($image, null, $quality); $buffer = ob_get_clean(); header('Content-Type: image/jpeg'); header('Content-Length: '.strlen($buffer)); echo $buffer; } $image = open_screenshot(dirname(__FILE__).'/1.jpg'); echo_screenshot($image); 

If this is not enough, then you can play with the brightness and contrast or other filters.
 function filter_image($image) { $brightness = rand(-10, 10); $contrast = rand(-10, 10); imagefilter($image, IMG_FILTER_BRIGHTNESS, $brightness); imagefilter($image, IMG_FILTER_CONTRAST, $contrast); return $image; } 

However, all these manipulations only slightly distort the colors, but leave the possibility of a simple pixel-by-pixel comparison. To complicate the task, you can crop the frame horizontally and vertically, keeping the proportions and then increasing it to its original size.
 function cut_image($image) { $k = rand(98000, 100000) * 0.00001; $w1 = imagesx($image); $h1 = imagesy($image); $w2 = round($k * $w1); $h2 = round($k * $h1); $x = rand(0, $w1 - $w2); $y = rand(0, $h1 - $h2); $result = imagecreatetruecolor($w1, $h1); imagecopyresampled ($result, $image, 0, 0, $x, $y, $w1, $h1, $w2, $h2); return $result; } 

Now, if there are a lot of frames in the game, the comparison task will not be so trivial. Although if at the disposal of the attacker there are comparison algorithms like in Google Images, then this will not be a hindrance either. As well as the effect of circumcision is less when comparing reduced versions of frames.

The picture consists of 6 frame options, obtained by the above method. As you can see, there are different values ​​of brightness and contrast everywhere. If you look closely, you may find that in some frames the image is cropped at the edges more than in others.

By the way, I didn’t come up with a protection from a banal googling screenshot. Unless to distort it even more strongly, but it can affect and recognition by the person.

Perhaps this is all I can say about the technical side of protection against cheaters in this case. I think that such ideas would sooner or later have occurred to any developer who was concerned about the protection of such games.

Conclusion


After all, I have not yet become even from an IT interest, because hacking the protection of this level is not a big reason to boast.

In fact, the lack of protection against cheating is also protection. Cheating in this case does not give anything, and the ease of dishonest play kills any interest in it. Of course, if the site would like to maintain real ratings, then it would be worthwhile to take care of the protection.

By the way, I want to note that something described in this article can be applied not only to this kind of games, but to something more serious. For example, online tests.

PS
I still haven’t written the address of the site so that it doesn’t look like an advertisement. But I will not play with you in the "guess the site by the screenshot". The site in question is guessanime.com .
I have nothing to do with the site. If the article somehow touches the owners, I'm sorry.

Source: https://habr.com/ru/post/184260/


All Articles