📜 ⬆️ ⬇️

Passage of the Labyrinth Captcha on Javascript

There is a not very well-known browser game. The gameplay in it is very simple and monotonous, which contributes to the appearance of bots. To combat them, a captcha was introduced into the game, occasionally crawling out during battle. 50 seconds are given for guessing, if you guess for 20, then they will give an additional bonus. Captcha two types: "Guess the pony" and "Pass the labyrinth". I didn’t usually have problems with guessing ponies, but going through a maze in 20 seconds is not always a trivial task. And I thought, is it possible to write Userscript, which would independently go through the maze and tell me the correct answer ...

The first thing to start with is gathering information. We cause the maze to appear, climb into the source code, and see what is there and how. There we find the inserted image, and we learn two things: first, the image is on the same domain as the toy itself. This makes it easy to work with canvas. Secondly, it is in the form with id = "riddleform", which is the first image. In the same form is another image.

Disclaimer: jQuery is used in the script. Throwing boots optional; I know that connecting jQuery in order to pull out one image is not a good use of it. The fact is that this script was planned as part of another, in which jQuery was already used.

Start writing code
$('#riddleform img').load(function(){// -      if (this.src == "http://ehgt.org/v/battle/answer.png") return;//  ,       var rmimg = $('#riddleform img')[0]; var canvas = document.createElement("canvas"); canvas.width = rmimg.width; canvas.height = rmimg.height; var ctx = canvas.getContext("2d"); ctx.drawImage (rmimg, 0, 0); var data = ctx.getImageData(0, 0, canvas.width, canvas.height); }); 

')
As a result, we have the variable data, in which the image is loaded. We stop. We begin to collect images of mazes and save them.

All images have an address of the form " hentaiverse.org/riddlemaster.php?uid= [here is the user's ID, the same for all images] & v = [here, apparently, md5 hash]". For example, " hentaiverse.org/riddlemaster.php?uid=123456&v=834a6b57de2d4e6d777478d7c2803d664293e7ec ".

After collecting about ten pictures, open them and begin to consider them.



(Images reduced)

So, the image is noisy, it may or may not pass through a bright triangle, which occupies the lower left corner, and a dark triangle, which occupies the upper left corner. Both may be present. There may not be one. Entry and exits are always in the same place. All images are the same size (615x615), and they are all in jpg format.

A bunch of large images will not decorate the article, so I’ll just put the links.
habrastorage.org/storage2/bfe/dcc/6a0/bfedcc6a0dc3b80e44d372a4b6660411.jpg
habrastorage.org/storage2/5c1/b6e/7c3/5c1b6e7c3fb4db6e547b95ecf0d5d81c.jpg
habrastorage.org/storage2/e85/6bc/c1e/e856bcc1ee6542acc66ab03601901eff.jpg
habrastorage.org/storage2/48d/535/62e/48d53562e8edb7d787419a726a5fea77.jpg
habrastorage.org/storage2/001/c2e/d34/001c2ed34a22d82fd467c3fcd36993e7.jpg
habrastorage.org/storage2/eca/80a/75a/eca80a75a60b41498f3d847afc207e71.jpg

Further - more interesting. It is easy to see that the noise in all the images is the same. Further, although the colors of the “walls” differ from the image to the image, the color of the “tracks” is always the same. If you look closer, it becomes clear that most of the cells are the same on all mazes.



Black squares denote cells that are always passable . The red dot indicates the central cell. The cells located between the black dots on the diagonal are always busy. They are not interesting for us. We need to find out if the cells on the same horizontals and verticals as the black points are free or occupied.

The first thought that comes to mind is “The noise is the same, the color of the cell too. We can simply take any pixel in the cell and look at its color. ” However, this does not work. A more detailed study shows that the noise is not exactly the same. In addition, for each cell would have to choose a pixel, find out what it can be colors, take into account the triangles; In short: a lot of fuss.

Just in the maze of cells 37x37. Create an array into which we will load this maze.
 var clear = []; for (var tmp=0; tmp<38; ++tmp) clear[tmp] = []; for (var r=1; r<38;++r){ for (var t=1; t<38; ++t){ if ((r%2 == 1) && (t%2 == 1)){clear[r][t] = true;continue;} if ((r%2 == 0) && (t%2 == 0)){clear[r][t] = false;continue;} } } 

It remains to figure out how to distinguish empty cells from occupied ones. If we can’t choose one pixel by one, then we’ll select by all: add and divide. Smash the cells, to put it simply. Look closely again. Cells are 15x15 pixels.
 var sum = [0,0,0]; var amount = 0;//      for (var j=t*15; j<t*15+15; ++j){ for (var k=r*15; k<r*15+15; ++k){ sum[0] += data.data[getrdata(j, k)];//getrdata     ,   sum[1] += data.data[getrdata(j, k)+1];//      , sum[2] += data.data[getrdata(j, k)+2];//    ,  1  2. ++amount; } } sum[0] = Math.round(sum[0]/amount); sum[1] = Math.round(sum[1]/amount); sum[2] = Math.round(sum[2]/amount); 

It remains to find out which colors correspond to empty cells. There are four kinds of them: pure, light, dark, and “light-dark,” depending on whether the triangles that I talked about at the beginning appeared. Fortunately, there are no cells that would be on the border of these triangles. In short: the colors were obtained by creating a diva into which all the colors of the cells were thrown. Then from there the necessary ones were chosen. For a while, the script was driven when it ran into an impassable labyrinth.
 if ( (sum[0]>190)&&(sum[0]<202) && (sum[1]>170)&&(sum[1]<183) && (sum[2]>130)&&(sum[2]<145) ){//normal clear[r][t] = true; }else if ( (sum[0]>148)&&(sum[0]<160) && (sum[1]>135)&&(sum[1]<143) && (sum[2]>103)&&(sum[2]<114) ){//dark clear[r][t] = true; }else if ( (sum[0]>203)&&(sum[0]<213) && (sum[1]>190)&&(sum[1]<197) && (sum[2]>157)&&(sum[2]<169) ){//light clear[r][t] = true; }else if ( (sum[0]>171)&&(sum[0]<180) && (sum[1]>158)&&(sum[1]<167) && (sum[2]>133)&&(sum[2]<143) ){//grey clear[r][t] = true; }else{ clear[r][t] = false; } 

There is a trifle: go through the maze. This will make a recursive algorithm.
 function makeway(x,y,data){ if ((y == 11)&&(x == 37)) return 'A';//    A if ((y == 27)&&(x == 37)) return 'B';//   if ((y == 37)&&(x == 11)) return 'D'; if ((y == 37)&&(x == 27)) return 'C'; var t = ''; if (x<37 && data [x+1][y]) {data [x+1][y] = false; t = makeway (x+2, y, data);}//   ... if (t != '') return t; if (x>1 && data [x-1][y]) {data [x-1][y] = false; t = makeway (x-2, y, data);}// ... if (t != '') return t; if (y<37 && data [x][y+1]) {data [x][y+1] = false; t = makeway (x, y+2, data);} if (t != '') return t; if (y>1 && data [x][y-1]) {data [x][y-1] = false; t = makeway (x, y-2, data);} if (t != '') return t; return '';//   } 

After that, it remains only to create a div in the document and call
 answerdiv.innerHTML = makeway (1, 1, clear); 

Pay attention to the fact that we "jump through the cage." If a neighboring cell is free, then we jump through it, because we know for sure that that cell is free: it is one of the cells with black dots.

All this is great, but such code is not very convenient to debug. So he broke down, did not find the passage, because he did not recognize the cell as free. Question: where did he break down? Expand the script. Add the variable ctx to the arguments to the makeway function, and in the beginning ...
 ctx.fillStyle = "rgb(0,0,0)"; ctx.fillRect (y*15,x*15,15,15); 

... And paint the passed cell with black. Add to the script code ...
 $('body')[0].appendChild(canvas); 

... And in the cycle, immediately after checking for free cells ...
 ctx.fillStyle = "rgb(" + sum[0] + ',' + sum[1] + ',' + sum[2] + ")"; ctx.fillRect (t*15,r*15,15,15); 

Now this canvas will appear in the document, which may look like this:

It remains only to open the image in the paint, poke a pipette into the impassable cell, and see its color.
And finally, leave a link to the archive with several images and an html file in which you can insert the desired image and look at the result, as well as several working files: dl.dropbox.com/u/42049925/rm.zip

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


All Articles