Ломаем капчу — сбор данных и их предварительный анализ

13 мая 2014

Итак, мы с вами полны решимости сломать какую-нибудь капчу. С одной стороны, капча не должна быть слишком простой или уже кем-то сломанной, потому что так не интересно. С другой, выбрав слишком сложную капчу можно потратить кучу времени на ее взлом и не добиться никакого результата. Также желательно, чтобы капча использовалась на каком-нибудь более-менее известном сайте, чтобы наш опыт имел хоть какое-то подобие практической значимости.

В итоге мной была выбрана капча совершенно абстрактного, никому не известного, не существующего суверенного коллективного блога, которая выглядит так:

Примеры взламываемой Captcha

Давайте-ка посмотрим, как много информации можно собрать, тупо глядя на эти шесть картинок.

Капча имеет формат PNG и размер 250×60 пикселей. На ней изображены буквы фиксированного размера и фиксированного цвета. Цвет фона также никогда не изменяется. Расстояние между буквами, похоже, не фиксировано. Буквы имеют случайный наклон, но у всех букв он одинаков. Каждая буква имеет случайное вертикальное смещение. Кроме того, на капче присутствует случайный шум, а также фиксированный рисунок из четырех дуг. Картинка обрамлена в черную рамку толщиной в один пиксель. Букв всегда ровно шесть штук.

С одной стороны, капча выглядит не слишком сложной, с другой — не слишком тривиальной. То, что нужно для нашего первого, так сказать, эксперимента. Надо признать, во многих аспектах эта капча довольно проста. Поэтому далее я иногда буду использовать слишком сложные для данного конкретного случая приемы, которые, однако, являются более общими.

В общем случае для взлома капчи нам с вами потребуется некоторое количество распознанных примеров этой самой капчи. Для подобного рода вещей я лично предпочитаю использовать Perl. Многие практические задачи решаются с его помощью за считанные минуты прямо в шеле путем написания сравнительно простых однострочников. Например, следующий однострочник загружает сто примеров капчи:

perl -e 'for my $i (1..100) { print "$i\n"; $d = `wget http://example.ru/login/ -O - 2>&1 `; my ($u) = $d =~ m!src="/captchaa/([^"]+)"!; print "$u\n"; `wget http://example.ru/captchaa/$u -O $u.png 2>&1 >/dev/null`; sleep 1; }'

Распознать примеры можно либо вручную, либо отдав эту задачу на оутсорс, либо автоматически, используя уже упомянутый Антигейт. В общем случае мы можем иметь слишком много примеров для распознования их вручную. Вот как легко и непринужденно можно распознать их Антигейтом:

cat flist.txt | perl -MDigest::CRC=crc32 -lne '$f = $_; chomp $f; if(crc32($f) % 5 == 0) { $s = 3; while ($s > 0) { $k = "a86850deb2742ec3cb41518e26aa2d89"; print "File: $f"; $d = `curl -XPOST -F method=post -F key=$k -F file=\@$f http://antigate.com/in.php -D - -o - 2>&1`; ($id) = $d =~ /OK\|(\d+)/; print "Id: $id"; if($id) { $a = 10; } else { print "Error: $f, s = $s"; sleep 10; $a = -1; $s--; } while($a >= 0) { sleep 5; $r = `curl "http://antigate.com/res.php?key=$k&action=get&id=$id" -D - -o - 2>&1`; if($r =~ /OK\|(\w+)/) { print "LOG|$f|$1"; $a = -1; $s = -1; } else { print "Waiting..."; $a-- }} }}' | tee log0.txt;

Здесь a86850deb2742ec3cb41518e26aa2d89 — это echo qwerty | md5sum, его нужно заменить на настоящий ключ, полученный на antigate.com. Однострочник работает с 1/5 картинок из заданного списка. Можно запускать его параллельно в несколько потоков, заменяя 0 в коде if(crc32($f) % 5 == 0) на 1, 2, 3 и 4.

Антигейт не всегда распознает капчи правильно, поэтому полученный результат обязательно нужно перепроверить вручную. Типичные ошибки — неправильное количество символов, наличие в коде цифр, когда на капче бывают только буквы («0» вместо «O», «9» вместо «g» и так далее). Коды по возможности исправляем, неправильные коды вычищаем. Все это, понятно, при помощи однострочников. Неправильно распознанные капчи при желании можно повторно прогнать через Антигейт. Есть подозрение, что Антигейт хранит соответствие контрольной суммы от картинки коду на этой картинке. Поэтому при повторном прогоне картинки следует модифицировать. Например, сконвертировать их в JPEG при помощи утилиты convert.

Дополнительно не повредит построить статистику того, как часто какие буквы встречаются на капче. Если одни буквы встречаются на два порядка реже других, это означает неправильное распознавание. Например, в случае с исследуемой капчей оказалось, что на ней реально используются только 15 букв латинского алфавита — acgkmopqsuvwxyz. Очевидно, неправильно распознанные коды, обнаруженные таким образом, мы также выкидываем.

На данном шаге мы получаем (1) некое представление об устройстве данной конкретной капчи, а также (2) множество картинок и соответствующие им коды. Этот подготовительный этап крайне важен, пусть вас не вводит в заблуждение кажущаяся его простота. От того, насколько серьезно к нему подойти, зависит успех всего нашего эксперимента. Скоро мы узнаем, что делать дальше со всей этой информацией. Следите за обновлениями.

Дополнение: Ломаем капчу — вычищаем мусор и нарезаем капчу на буквы

Метки: , , .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.