0,0
рейтинг
19 января 2013 в 20:51

Разработка → Решение MintEye CAPTCHA в 23 строки кода перевод

Как заядлый читатель HAD я был заинтересован этим постом, описывающим способ взлома аудиокапчи MintEye. Графическая версия также выглядела довольно интересно, так что я подумал, что будет забавно взломать и её.

Вот один из примеров графической капчи MintEye:



Для решения нужно всего лишь подвигать слайдер и выбрать неискажённый вариант изображения. В комментариях на HAD было несколько довольно наивных на мой взгляд предложений решения капчи, основанных на поиске прямых линий. Однако, подобные варианты не сработают с примерами, подобными указанному выше (т. е. содержащим малое количество прямых линий).

После некоторых раздумий я нашёл хороший, надёжный и, на удивление, простой способ разгадывания капчи. Вот вся его реализация на Python:

import cv2
import sys
import numpy as np
import os
import matplotlib.pyplot as plt
 
if __name__ == '__main__':
 
    for dir in range(1,14):
        dir = str(dir)
 
        total_images = len(os.listdir(dir))+1
        points_sob = []
 
        for i in range(1,total_images):
            img = cv2.imread(dir+'/'+str(i)+'.jpg')
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
            sob = cv2.Sobel(gray, -1, 1, 1)
            points_sob.append(np.sum(sob))
 
        x = range(1,total_images)
        res = np.argmin(points_sob)+1
        print res
        plt.plot(res,points_sob[res-1], marker='o', color='r', ls='')
        plt.plot(x, points_sob)
 
        plt.savefig(dir+'.png')
        plt.show()


(Обратите внимание, что большая часть кода относится к открытию изображения и построению графика. Такие функции, как автоматический разбор изображений и возврат готового результата оставим спаммерам как домашнее задание).

Суть метода в следующем: чем больше изображение «скручено», тем длинее границы. Это можно заметить на картинке, представленной выше, но есть и более наглядный пример:



Обратите внимание на увеличение длины чёрного прямоугольника. Для того, чтобы использовать это, нам нужно посчитать сумму длин границ изображения. Простейший способ сделать это — взять производную изображения (в предложенной выше реализации используется оператор Собеля) и сложить результаты (рекомендуется к прочтению статья о том, как работает оператор Собеля). Затем мы просто выбираем изображение с наименьшей «длиной границ» — оно и будет верным ответом.

Результаты впечатляют, 13 из 13 мною скачанных капч были решены верно этим способом. Эти графики показывают номер изображения на оси Х и «длину границ» на оси Y. Красной точкой отмечен верный ответ.


Интересно, что зачастую абсолютно неискажённое изображение на графике отображается как пик. Это обычно значит, что мы промахнулись с верным ответом на одну картинку влево или вправо (что, впрочем, принимается MintEye как корректный ответ). Происходит это обычно потому, что неискажённое изображение кое-где выглядит чётче и границы выделяются точнее, что влияет на конечную сумму длин.

В завершении хотелось бы сказать, что данная CAPTCHA по своей архитектуре не устойчива ко взлому. Простое «скручивание» изображения всегда может быть легко замечено вышеописанным методом вне зависимости от исходного изображения.
Перевод: jwandrews
Константин Богданов @thevar1able
карма
84,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (51)

  • +5
    Спросили бы «Какое изображение скручено по часовой?».
    • +29
      «Какое изображение забавнее выглядит?»
    • +17
      «Какое изображение я загадал?»
  • НЛО прилетело и опубликовало эту надпись здесь
    • +1
      А смысл подсовывать капчу ботам, если они её всё равно обойдут? Имхо, намного удобнее и действеннее ловушки ставить.
      • НЛО прилетело и опубликовало эту надпись здесь
      • НЛО прилетело и опубликовало эту надпись здесь
        • +1
          Человек не будет, а «шпана и неадекват» с деньгами, заплативший за скрипт взлома каптчи — увы, будет =).
          • НЛО прилетело и опубликовало эту надпись здесь
            • НЛО прилетело и опубликовало эту надпись здесь
              • НЛО прилетело и опубликовало эту надпись здесь
    • +1
      Можно было бы сделать такую штуку: если вы бот, то введите капчу с картинки. :)
      • +12
        Вы недооцениваете невнимательность и глупость некоторых пользователей) Потом сотнями посыпятся вопросы «ПАЧИМУ НИРАБОТАЕТ????? Я ВСЁ ПРАЛЬНО ВЫБИРАЮ, А МЕНЯ НИПУСКАЕТ!!!!» :)
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Если каптчу будут распознавать только боты, это тоже хорошо: не распознал белый текст на белом же фоне — значит, человек ты, проходи, милейший!
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Любая общая каптча очень легко ломается хотя бы одним из этих способов:
            а) Аутсорсом живым индусам/китайцам (которые только и делают, что целый день разгадывают присылаемые им каптчи за копейки)
            б) Пробросом каптч по схеме: держим какой-нибудь популярный порносайт, на котором крутим каптчу, но не свою, а с ломаемого ресурса. Живой человек ради контента разгадывает, а мы для валидации отправляем его ввод на целевой сервер. Сервер сказал: «свой, проходи» — говорим то же самое на своём ресурсе.
            Имхо эта борьба щита и меча никогда не закончится, сколь бы искусно изощрённые методы защиты ни придумывали. До сих пор нет 100% защиты от взлома реальных банковско-денежных систем (включая фальшивомонетчество), хотя что-что, а деньги защищать есть огромный стимул и имеются средства.
            Кажись, Митник ещё сказал, что если в системе есть человеческий фактор — она ломается проще простого =).
            • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    а как быть, если на картинке изначально будет что-то вроде спирали, да еще и с нечеткими линиями? :)
    • 0
      Самое страшное если оно еще и скручиваться в противоположную сторону будет.
    • 0
      В результате скручивания они станут сильно чётче и Собель их надетектит чуть более чем дофига.
      И к стати сказать далеко не только Собель, но и любой другой оператор выделения края.
    • +10
  • +2
    В демо проверил неправильный ввод.
    «No, Mr. Robot, you shall not pass!»
    Убило.
  • 0
    hashcash кажется поможет
  • 0
    Вообще, скручивание плодит края, так что задачу можно решать анализом спектра пространственных частот.
    Или использовать оператор выделения края оптимизированный вообще не находить краёв в нормальном изображении, а только когда скрутка их наплодит, и решение принимать на основании суммы всех пикселов после детектора, которую можно посчитать и в самом детекторе. Минимальное значение, суть не искаженное изображение.
  • 0
    Идея — шикарна.

    Вместо слэша при сборке пути до картинки нужно использовать os.sep
    • +5
      os.path.join лучше
      • 0
        Чем лучше? В конкретном коде.
        • +1
          os.path.join лучше, потому что:
          * умеет правильно работать с абсолютными и относительными путями
          * не добавит дублирующих слешей
          * эта функция предназначена для формирования путей

          Потренируйтесь, и напишите свою функцию которая будет работать аналогично os.path.join
          Вот примеры для тестов

          os.path.join('/home','usr')
          os.path.join('/home/','usr')
          os.path.join('/home/','/usr')
          


          • 0
            Зачем мне писать уже готовую функцию?
            Зачем рассуждать о преимуществах использования данной функции в отрыве от конкретной ситуации?

            Я предлагаю исправить код на:
            img = cv2.imread(dir + os.sep + str(i) + '.jpg')

            Вы на:
            img = cv2.imread(os.path.join(dir, str(i) + '.jpg'))

            Весь спор — не более чем мнение каждого из нас о том, что такое «pythonic way».
            Мне нравится мой вариант.

            Кто-то может и вместо оставшегося плюса в вашем варианте какой-нибудь «более правильный» способ формирования строки обосновать. Добавив этим (с моей точки зрения) нечитаемости и наколбасив символов, которые можно не колбасить.
            • 0
              Я не говорю, что вашем варианте есть изьян.

              Как и pawnhearts я утверждаю, что os.path.join — правильнее использовать как в общем так и в данном кокнретном случае. Правильнее — потому что всегда для склейки пути стоит использовать os.path.join и забыть о проблеме переносимости, дубликатов слешей, относительности путей,… Даже на секунду не надо задумываться, питоник/непитоник, больше символов/меньше, для склейки путей надо использовать os.path.join

              По поводу читабельности и «наколбасить» символов тоже не соглашусь. Код

              img = cv2.imread(os.path.join(dir, '%s.jpg'%i)) 
              

              отлично читается, тут дословно написано: «объединиться путь к файлам»

              Как только в коде вы увидите os.path.join — значит формируется путь к файлу, когда в коде используются знакомые общепринятые конктрукции — такой код всегд будет читаться лучше.
              • 0
                Мне нравится.

                Я к стыду своему думал, что минимальный код для форматирования строки:
                '%s.jpg' % (i)
  • +1
    Есть еще такой вариант решения капчи MintEye с использованием голосовых подсказок и гуглового text2speech API — gist.github.com/4520930
    Демо: www.youtube.com/watch?v=u0M7gmS5Eg0
  • 0
    Интересно, будет ли работать такой подход — покрутить на разные углы и прокоррелировать с исходным изображением? Предположительно, наиболее закрученные изображения должны давать более высокие значения корреляции при одинаковых углах поворота.
  • +1
    Просто выводить 3 разных картинки, 1 из которых не скручена.
    • +2


      Возможно, немного сложнее оригинала, но всяко проще рекапчи. Как такое разгадывать будете?)
      • НЛО прилетело и опубликовало эту надпись здесь
        • НЛО прилетело и опубликовало эту надпись здесь
        • +2
          А, извиняюсь, вижу слайдер. Хм, в любом случае, если вместо морфинга там будет даваться несколько различных изображений, одно из которых не искажено, то разгадать капчу станет сложнее.
        • 0
          А потом капчу спросит гугл.
      • 0
        Неужто нет алгоритма, который определит, что большинство линий изогнуты по одинаковому алгоритму? :) В скрученном изображении не бывает прямых, каждая линия — спиралевидна.
        • 0
          Можно использовать разные алгоритмы искажения. Например, как в эффектах Photo Booth:



          Но, как было сказано выше, даже если разместить 6 картинок с одной правильной, то при случайном тыке — будет 30% правильных распознаваний, что вполне себе нормальный результат.

          • +2
            9 картинок, 3 правильные
            • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              c(9,3)=84, все равно большая вероятность угадать
              • НЛО прилетело и опубликовало эту надпись здесь
                • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Я уже не помню комбинаторику, разве не 1/9*1/8*1/7? В любом случае этот шанс достаточно низок, чтобы при разумном количестве попыток блокировать ip на часов 6 :).
                • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    А если скручивание будет относительно нескольких центров вместо одного — сработает?
    • 0
      А вы сами-то такое решите, с несколькими слайдерами? :)

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