В последнее время активно участвую в жизни Я.ру: присоединяюсь к клубам по Delphi, делюсь новостями, ссылками и пр. И вот сегодня натолкнулся на “интереснейшую” статью про распознавание слабых каптч в Delphi. Думаю, что те, кто уже давно со мной и читали мои статьи ещё будучи на intercasher.info прекрасно помнят эту же статью только под моим авторством… ' '
Я вообще не склонен делать какие-либо опрометчивые выводы о воровстве контента, но здесь просто наглейший способ выдать желаемое за действительное. В статье 99% мои слова, но только от женского лица. Спрашивается “какого дьявола?”. Я не против того, чтобы мои статьи или программы вывешивали на других ресурсах, более того я рад, когда человек пишет, что поделился моей статьей или программой на своем сайте – без проблем, я не жадный.
НО ОСТАВЛЯЙТЕ ОБРАТНУЮ ССЫЛКУ НА ИСТОЧНИК И НЕ КОВЕРКАЙТЕ ТЕКСТ!
Эта статья была опубликована на старом блоге не далее, чем , тогда же была сделана пометка с анонсом статьи.
Теперь я немного продолжу рассмотрение этой интереснейшей на мой взгляд темы и расскажу второй способ подбора верного кода каптчи.
В прошлый раз мы остановились на таблице соответствия “код в URL картинки –> пяти-значный код Captcha”. В общем виде таблица выглядела следующим образом:
| 7 | 9 | 5 | 0 |
| 1101112 | 1110012 | 1101012 | 1100002 |
| 8 | 6 | 7 | 5 |
| 1110002 | 1101102 | 1101012 | 1101012 |
| 2 | 4 | 5 | 6 |
| 1100102 | 1101002 | 1101012 | 1101102 |
Процедура, определяющая код Captcha была построена вот так:
function Captcha(URL: string):string; var aURL: TURLComponents; ParamStr: string; //строка, содержащая код каптчи code: string; //7-ми значнй код из каптчи i,j:integer; begin //разбиваем УРЛ на составляющие Result:=URL; fillchar(aurl, sizeof(turlcomponents), 0); with aurl do begin lpszscheme := nil; dwschemelength := internet_max_scheme_length; lpszhostname := nil; dwhostnamelength := internet_max_host_name_length; lpszusername := nil; dwusernamelength := internet_max_user_name_length; lpszpassword := nil; dwpasswordlength := internet_max_password_length; lpszurlpath := nil; dwurlpathlength := internet_max_path_length; lpszextrainfo := nil; dwextrainfolength := internet_max_path_length; dwstructsize := sizeof(aurl); end; if internetcrackurl(pchar(Result), length(Result), 0, aurl) then begin ParamStr:=copy(aurl.lpszExtraInfo,5, length(aurl.lpszExtraInfo)-4); //выдираем 7-ми значный код и подбираем ему число Result:=''; for I:=1 to 5 do //всего 35 цифр по 7 цифр на знак begin code:=copy(ParamStr,i+7*(i-1)-(i-1),7); for j := 0 to High(MCat_Captcha) do if code=Cat_Captcha[j] then Result:=Result+IntToStr(j); end; end; ShowMessage('Код Captcha '+Result) end; |
И первое, что хочется сказать по поводу этой процедуры – она просто так не заработает. Для того, чтобы разобрать любой URL на составляющие его компоненты необходимо подключать в uses модуль WinInet в котором и содержится процедура internetcrackurl.
Теперь пройдем немного дальше. Взгляните ещё раз на таблицу соответствия. Как Вы можете заметить – она содержит расшифровку не всех цифр. Так, в таблице отсутствуют цифры: 1 и 3. Я не буду повторяться и дописывать недостающие элементы, а предложу Вам более красивый с точки зрения программистов вариант расшифровки.
Берем любое число и соответствующий ему код Captchaб например:
7 –> 1101112
Те, кто знаком с двоичной формой счисления, могут с первого взгляда определить, что в коде Captcha содержится число 7. Смотрите:
7 –> 11+0111+2
Открываем калькулятор, жмем кнопочку Bin, забиваем 0111, жмем кнопочку Dec и, о чудо, на табло высвечивается цифра 7!
Можете проверить всю таблицу таким образом – результат попадания в цель будет 100%. Теперь можно смело сократить код для расшифровки с семи до 4-х символов, т.е. отсечь первые 2 цифры – они всегда 11 и последнюю – она всегда 2. Теперь, ради спортивного интереса, можно получить семизначный код для недостающих элементов таблицы:
1 –> 1100012
3 –> 1100112
Теперь осталось написать функцию по переводу двоичного представления числа в десятеричную.
function BIN2DEC(BIN: string): LONGINT; var J: LONGINT; Error: BOOLEAN; DEC: LONGINT; begin DEC := 0; Error := False; for J := 1 to Length(BIN) do begin if (BIN[J] < > '0') and (BIN[J] < > '1') then Error := True; if BIN[J] = '1' then DEC := DEC + (1 shl (Length(BIN) - J)); { (1 SHL (Length(BIN) - J)) = 2^(Length(BIN)- J) } end; if Error then BIN2DEC := 0 else BIN2DEC := DEC; end; |
Весь секрет работы с двоичной системой заключается в теории, которую я, кстати почерпнул из книги “Нестандартные приемы программирования на Delphi”.
Теперь переписываем основную процедуру распознавания Captcha,используя полученные знания (в листинге представлена часть измененной процедуры):
function Captcha(URL: string):string; var aURL: TURLComponents; ParamStr: string; //строка, содержащая код каптчи code: string; //7-ми значнй код из каптчи i,j:integer; begin ... for I:=1 to 5 do //всего 35 цифр по 7 цифр на знак begin {получили 4-х значный код - двоичное представление числа} code:=copy(copy(ParamStr,i+7*(i-1)-(i-1),7), 3, 4); Result:=Result+BIN2DEC(Code); //вычислили число Captcha end ... end; |
Вот и весь секрет слабой Captcha. И последнее, что хотелось бы сказать – это то, что врядли Вы когда-то встретите теперь в Интернете подобную систему защиты. Судя по тому, что из 50 каталогов сайтов, использующих эту систему защиты 50 мёртвых или переделанных, можно сделать однозначный вывод – время халявы кончилось :) Теперь Captcha стала на порядок сложнее для взлома, но, тем не менее, варианты есть, например, для блога можно организовать грамотный кросспостинг – почитайте об этом подробнее. Думаю, что использование кросспостинга окажет сейчас больший эффект для блога, чем регистрация в каталогах.
Мой блог находят по следующим фразам
- представление формат даты hex
- delphi alphatools
- delphi DOM
- Перечень объектов,для которых применяются текущиен индексы
- delphi таймер в компоненте
- from xml to treeview winapi
Related posts:










24 Aug 2009 в 4:17 pm
С переездом вас, раньше постоянно читал intercasher.info Скажите вы планируете публикацию материала с прошлого сайта? Если нет, может можно как нибудь просмотреть статьи на другом сайте, если у вас они случайно есть прошу поделиться . Спасибо зарание.
24 Aug 2009 в 4:36 pm
Вообще переезд был задуман после того как больше 50% всех статей странным образом исковеркалась…просто в каждом посте осталось по 5-10 строк текста. Хостер дал невнятный ответ по поводу глюков БД и пр. В общем переехал и начал всё с нуля. Можете просто напомнить, какие из статей/тем Вас больше всего интересовали? Я покопаюсь в локальных черновиках и блог-клиенте – вполне возможно, что часть интересующих Вас статей там сохранилась
24 Aug 2009 в 5:07 pm
Интересует заполнение форм на сайтах, хочу написать сабмитер для регистрации в RSS лентах
24 Aug 2009 в 5:17 pm
Без проблем. В ближайшее время опубликую пару/тройку статей на эту тему. Вполне возможно, что не пожадничаю и с исходниками, но только на D2009. Кстати сабмиттер RSS есть у Марии
27 Aug 2009 в 8:09 pm
Ну, если вы так нервничаете из-за этого, то я уберу вашу статью с сайта. Я все равно переделываю сайт в персональную страницу. Хорошо, когда на сайт заходит человек 5 в день, но когда 40-50 для меня это уже слишком.
27 Aug 2009 в 8:55 pm
Я не нервничаю, а злюсь. Злюсь на то, что статья была нагло сворована. Одно дело когда статью копируют и вставляют ссылку на источник и совсем другое, когда ту же статью копируют, потом переделывают “под себя”.
29 Mar 2010 в 8:59 am
Который раз захожу и читаю ваш блог… Спасибо за то, что вы есть, – хоть кто-то умеет нормальным языком всё объяснять!