Использование JavaScript для взлома кодов подтверждения
Недавно в Интернете появился JavaScript-скрипт, способный взламывать проверочные коды — GreaseMonkey! Этот скрипт, разработанный «Шоном Фридлом», легко разгадывает CAPTCHA сайта Megaupload. Если вы не верите, вы можете попробовать это сами по адресу http://herecomethelizards.co.uk/mu_captcha/ .
Теперь капча, предоставленная сайтом Megaupload, не прошла проверку с помощью приведенного выше кода. код здесь спроектирован Нет, не очень хорошо. Но что еще интереснее:
1. Интерфейс приложения Canvas getImageData в HTML 5 можно использовать для получения данных пикселей из изображения кода проверки. Используя Canvas, мы можем не только вставлять изображение в холст, но и позже повторно извлекать его из него.
2. Приведенный выше скрипт содержит нейронную сеть, полностью реализованную на JavaScript.
3. После использования Canvas для извлечения данных пикселей из изображения отправьте их в нейронную сеть и используйте простую технологию оптического распознавания символов, чтобы определить, какие символы используются в коде проверки.
Прочитав исходный код, мы можем не только лучше понять, как он работает, но и понять, как реализован этот проверочный код. Как вы видели ранее, используемые здесь CAPTCHA не очень сложны — каждая CAPTCHA состоит из трех символов, каждый символ использует свой цвет и использует только символы из 26-буквенного алфавита, при этом все символы используют один и тот же шрифт.
Цель первого шага очевидна: скопировать код проверки на холст и преобразовать его в изображение в оттенках серого.
функция Convert_grey(image_data){
for (var x = 0; x <image_data.width; x++){
for (var y = 0; y < image_data.height; y++){
вар я = x*4+y*4*image_data.width;
var luma = Math.floor(image_data.data[i] * 299/1000 +
image_data.data[i+1] * 587/1000 +
image_data.data[i+2] * 114/1000);
image_data.data[i] = яркость;
image_data.data[i+1] = яркость;
image_data.data[i+2] = яркость;
image_data.data[я+3] = 255;
}
}
}
Затем разделите холст на три отдельные пиксельные матрицы, каждая из которых содержит один символ. Этого шага очень легко достичь, поскольку каждый символ использует отдельный цвет, поэтому его можно отличить по цвету.
фильтр (image_data [0], 105);
фильтр(image_data[1], 120);
фильтр(image_data[2], 135);
функция filter(image_data, color){
for (var x = 0; x <image_data.width; x++){
for (var y = 0; y < image_data.height; y++){
вар я = x*4+y*4*image_data.width;
// Делаем все пиксели определенного цвета белыми
if (image_data.data[i] == цвет) {
image_data.data[i] = 255;
image_data.data[я+1] = 255;
image_data.data[я+2] = 255;
// Все остальное в черный цвет
} еще {
image_data.data[i] = 0;
image_data.data[я+1] = 0;
image_data.data[я+2] = 0;
}
}
}
}
Наконец, все ненужные мешающие пиксели удаляются. Для этого можно сначала найти те белые (совпадающие) пиксели, которые спереди или сзади окружены черными (несовпадающими) пикселями, а затем удалить совпавшие пиксели.
вар я = x*4+y*4*image_data.width;
var выше = x*4+(y-1)*4*image_data.width;
var ниже = x*4+(y+1)*4*image_data.width;
если (image_data.data[i] == 255 &&
image_data.data[above] == 0 &&
image_data.data[ниже] == 0) {
image_data.data[i] = 0;
image_data.data[я+1] = 0;
image_data.data[я+2] = 0;
}
Теперь, когда у нас есть приблизительная форма персонажа, скрипт далее выполняет необходимое обнаружение краев перед загрузкой в нейронную сеть. Скрипт будет искать крайние левые, правые, верхние и нижние пиксели изображения, преобразовывать их в прямоугольник, а затем повторно конвертировать прямоугольник в матрицу размером 20*25 пикселей.
Croped_canvas.getContext("2d").fillRect(0, 0, 20, 25);
вар края = find_edges (image_data [i]);
Croped_canvas.getContext("2d").drawImage(холст, края[0], края[1],
ребра[2]-ребра[0], ребра[3]-ребра[1], 0, 0,
ребра[2]-ребра[0], ребра[3]-ребра[1]);
image_data[i] = Croped_canvas.getContext("2d").getImageData(0, 0,
обрезанный_canvas.width, обрезанный_canvas.height);
Что мы получим после вышеуказанной обработки? Матрица 20*25, содержащая один прямоугольник, заполненный черным и белым цветом? Отлично!
Затем мы еще больше упростим прямоугольник. Мы стратегически извлекаем точки из матрицы как «фоторецепторы», которые будут переданы в нейронную сеть. Например, определенный фоторецептор может соответствовать пикселю, расположенному по адресу 9*6, с пикселями или без них. Скрипт извлекает серию таких состояний (намного меньше, чем весь расчет матрицы 20x25 — извлекается всего 64 состояния) и передает эти состояния в нейронную сеть.
Вы можете спросить, а почему бы просто не сравнить пиксели напрямую? Нужно ли использовать нейронную сеть? Дело в том, что мы хотим избавиться от этих неоднозначных ситуаций. Если вы попробовали предыдущую демонстрацию, вы заметили, что прямое сравнение пикселей более подвержено ошибкам, чем сравнение через нейронную сеть, хотя это случается нечасто. Но стоит признать, что для большинства пользователей прямого сравнения пикселей должно быть достаточно.
Следующий шаг – попытаться угадать буквы. В нейронную сеть импортируются 64 логических значения (полученных из одного из изображений персонажей), а также ряд заранее рассчитанных данных. Одна из концепций нейронных сетей заключается в том, что результаты, которые мы хотим получить, известны заранее, поэтому мы можем соответствующим образом обучить нейронную сеть на основе результатов. Автор сценария может запускать сценарий несколько раз и собирать серию лучших оценок, которые могут помочь нейронной сети угадать ответ, работая в обратном направлении от значений, которые их выдали, но эти оценки не имеют особого значения.
Когда нейронная сеть вычисляет 64 логических значения, соответствующих букве в коде проверки, сравнивает их с заранее рассчитанным алфавитом, а затем выдает оценку за совпадение с каждой буквой. (Окончательный результат может быть аналогичным: 98% может быть буквой А, 36% может быть буквой Б и т. д.)
После того, как все три буквы проверочного кода будут обработаны, выйдет окончательный результат. Следует отметить, что этот скрипт не на 100% корректен (интересно, можно ли повысить точность подсчета очков, если буквы не конвертировать в прямоугольники в начале), но он довольно хорош, по крайней мере, для текущей цели. Скажи так. И все операции выполняются в браузере на основе стандартной клиентской технологии!
В качестве дополнения эту технологию следует рассматривать как частный случай. Эта технология может хорошо работать и на других простых кодах проверки, но для сложных кодов проверки это немного. за пределами досягаемости (особенно такого рода клиентский анализ). Я надеюсь, что этот проект вдохновит больше людей и создаст еще больше замечательных вещей, потому что его потенциал очень велик.