📜 ⬆️ ⬇️

NotCaptcha is not a captcha

Recently, in the topic habrahabr.ru/blogs/spam/74007 it was told about a new kind of captcha.

Captcha is certainly interesting, though controversial, which caused a lot of comments about how convenient it is for the user, and how easy it is to break it theoretically.

In one of the comments it was noted that for the same url, though different pictures are shown, but with the same correct answer. This suggested that there was a mistake somewhere in the algorithm.

')
After downloading the captcha installation files, I noticed there an interesting function:

function my_decrypt($encrypt_string, $key) {
$dec = '' ;
$arr = explode( "\n" , wordwrap($encrypt_string, 2, "\n" , 1));
for ($i = 0; $i < count($arr); $i++) {
$dec .= chr(hexdec($arr[$i])) ^ $key;
}
return $dec;
}


* This source code was highlighted with Source Code Highlighter .


Obviously, for "encryption" (if I may say so), xor per constant is used.
It can be bypassed by the usual frequency analysis.
Having opened another file, we will see that the list of angles (in dec), separated by the characters | , we will take advantage of this.

Because I only had MSVS on hand, the sample code would be in C #
static void Main( string [] args)
{
while ( true ) {
Console .Write( "Input image url: " );

// i
var str = HttpUtility.ParseQueryString( new UriBuilder( Console .ReadLine()).Query)[ "i" ];
// HEX ,
var bytes = new byte [str.Length / 2];
var cnt = new Dictionary< byte , int >();
for ( var i = 0; i < bytes.Length; i++) {
bytes[i] = byte .Parse(str.Substring(i * 2, 2), NumberStyles.HexNumber);
if (!cnt.ContainsKey(bytes[i]))
cnt.Add(bytes[i], 0);
cnt[bytes[i]]++;
}
// , , 5
var avg = cnt.Keys.Average(p => ( decimal )p);
// ,
var nums = (bytes.Length + 1) / 3.5;

// , |
var candidates = cnt.Where(kvp => Math .Abs(kvp.Value - nums) <= 2).ToList().ConvertAll(p => p.Key);
// ,
candidates.Sort((a, b) => ( int )( Math .Abs(b - avg) - Math .Abs(a - avg)));
// «» xor
var key = ( byte )(candidates[0] ^ Encoding .ASCII.GetBytes( "|" )[0]);
// -xor'
for ( var i = 0; i < bytes.Length; i++)
bytes[i] ^= key;

//
var angles = Encoding .ASCII.GetString(bytes).Split( '|' ).ToList().ConvertAll(p => int .Parse(p));

Console .WriteLine( "Image at position {0} is upright" , angles.IndexOf(0));
}
}


* This source code was highlighted with Source Code Highlighter .


Use this: to compile, run, and at the entrance to submit a complete address of the image type http://notcaptcha.webjema.com/wp-content/plugins/wp-notcaptcha/lib/notcaptcha.php?i=424b430f4141460f4144430f4043430f430f45430f4a430f424046&r=1257161610

In principle, if it were not for this “childish” encryption algorithm, then the captcha would not be so easy to break, but this is another story ...

PS: for a snack:
image

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


All Articles