Исследование защиты программы MD5 CrackFAST

Программа MD5 CrackFAST предназначена для взлома хэшей MD5. Взлом выполняется прямым перебором, без использования таблиц, поэтому для больших строк о положительном результате можно сразу забыть. Но и без этого в незарегистрированной версии программы есть принудительное ограничение – восстанавливаются строки не более 3 символов длиной.

По какой-то причине с офсайта были убраны все упоминания об этой программе, ссылок на закачку, соответственно, тоже нет. Удалось найти зеркала на различных FTP, но и там встречаются битые инсталляторы. Вот ссылка на правильный дистрибутив.

Главный исполняемый файл упакован обычным UPX, им же он и распаковывается. Ну или любым другим универсальным распаковщиком, если вдруг вы предпочитаете пользоваться ими. Отправляем распакованный файл в дизассемблер. Файл небольшой, поэтому процесс займет совсем немного времени. После запуска программа в окне лога сообщает, что она не зарегистрирована. При попытке ввести любые левые данные появится сообщение о неправильной регистрации:

http://s017.radikal.ru/i411/1508/6c/e07199d0560b.png
Сообщение о неправильной регистрации

Строка сообщения легко обнаруживается в исполняемом файле:

http://s57.radikal.ru/i156/1508/89/ebcf6368569c.png
Строка сообщения

Теперь посмотрим в дизассемблерном листинге на условия появления сообщений о правильной или неправильной регистрации:

Цитата:

.text:0040C20F call sub_40BA80
.text:0040C214 mov eax, [esp+6Ch+var_14]
.text:0040C218 mov [esp+6Ch+var_68], eax ; char *
.text:0040C21C mov eax, [esp+6Ch+var_18]
.text:0040C220 mov [esp+6Ch+var_6C], eax ; char *
; Проверка введенных данных
.text:0040C223 call sub_40CAA0
; EAX=1, регистрация успешна
.text:0040C228 cmp eax, 1
.text:0040C22B mov edi, eax
.text:0040C22D jz loc_40C3DB
; Регистрационные данные введены неправильно
.text:0040C233 mov eax, [esp+6Ch+var_18]
.text:0040C237 test eax, eax
.text:0040C239 jnz loc_40C5C7
.text:0040C23F mov eax, [esp+6Ch+var_14]
.text:0040C243 xor esi, esi
.text:0040C245 mov [esp+6Ch+var_18], esi
.text:0040C249 test eax, eax
.text:0040C24B jnz loc_40C5E1
.text:0040C251 loc_40C251:
.text:0040C251 xor ebx, ebx
.text:0040C253 mov [esp+6Ch+var_14], ebx
.text:0040C257 loc_40C257:
.text:0040C257 test edi, edi
.text:0040C259 jnz loc_40C2E7
.text:0040C25F mov [esp+6Ch+var_6C], offset aInvalidNameKey
; "Invalid name/key. Please try again."
.text:0040C266 call g_strdup_printf
.text:0040C26B loc_40C26B:
.text:0040C26B mov ebx, eax
.text:0040C26D call gtk_window_get_type
.text:0040C272 mov [esp+6Ch+var_68], eax
.text:0040C276 mov esi, 2
.text:0040C27B mov [esp+6Ch+var_6C], ebp
.text:0040C27E call g_type_check_instance_cast
.text:0040C283 mov [esp+6Ch+var_6C], eax
.text:0040C286 cmp edi, 1
.text:0040C289 mov edx, 1

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

Цитата:

.text:0040CAA0 sub_40CAA0 proc near
.text:0040CAA0 sub esp, 1Ch
.text:0040CAA3 mov [esp+1Ch+var_10], ebx
.text:0040CAA7 mov ebx, [esp+1Ch+arg_0]
.text:0040CAAB mov [esp+1Ch+var_C], esi
.text:0040CAAF mov esi, [esp+1Ch+arg_4]
.text:0040CAB3 test ebx, ebx
.text:0040CAB5 mov [esp+1Ch+var_8], edi
.text:0040CAB9 mov [esp+1Ch+var_4], ebp
.text:0040CABD jz short loc_40CACC
.text:0040CABF mov [esp+1Ch+var_1C], esi ; char *
; Получить длину серийного номера
.text:0040CAC2 call strlen
; Длина должна быть больше 17h, то есть 24 символа и больше
.text:0040CAC7 cmp eax, 17h
.text:0040CACA ja short loc_40CAE4
.text:0040CACC loc_40CACC:
.text:0040CACC xor edx, edx
.text:0040CACE loc_40CACE:
; Выйти из функции с кодом неправильной регистрации
.text:0040CACE mov ebx, [esp+1Ch+var_10]
.text:0040CAD2 mov eax, edx
.text:0040CAD4 mov esi, [esp+1Ch+var_C]
.text:0040CAD8 mov edi, [esp+1Ch+var_8]
.text:0040CADC mov ebp, [esp+1Ch+var_4]
.text:0040CAE0 add esp, 1Ch
.text:0040CAE3 retn
.text:0040CAE4 ; ————————————
.text:0040CAE4 loc_40CAE4:
; Указатель на регистрационное имя
.text:0040CAE4 mov [esp+1Ch+var_1C], ebx
; Проверить наличие имени в "черном списке"
.text:0040CAE7 call sub_40C800
.text:0040CAEC test eax, eax
.text:0040CAEE jnz short loc_40CACC
.text:0040CAF0 mov [esp+1Ch+var_1C], esi
.text:0040CAF3 call sub_40C850
.text:0040CAF8 test eax, eax
.text:0040CAFA jnz short loc_40CACC
.text:0040CAFC mov [esp+1Ch+var_1C], 0 ; char *
.text:0040CB03 mov eax, 6
.text:0040CB08 mov [esp+1Ch+var_14], eax ; size_t
.text:0040CB0C lea eax, [esi+11h]
.text:0040CB0F mov [esp+1Ch+var_18], eax ; char *
.text:0040CB13 call sub_401A20
.text:0040CB18 mov [esp+1Ch+var_1C], ebx ; char *
.text:0040CB1B mov ebp, eax
.text:0040CB1D call sub_401D70
.text:0040CB22 mov [esp+1Ch+var_1C], eax ; char *
.text:0040CB25 mov [esp+1Ch+var_18], ebp ; char *
.text:0040CB29 call sub_401B20
.text:0040CB2E test ebp, ebp
.text:0040CB30 mov edi, eax
.text:0040CB32 jz short loc_40CB3C
.text:0040CB34 mov [esp+1Ch+var_1C], ebp ; void *
.text:0040CB37 call free
.text:0040CB3C loc_40CB3C:
.text:0040CB3C mov [esp+1Ch+var_1C], edi ; char *
.text:0040CB3F call sub_40C9A0
.text:0040CB44 test edi, edi
.text:0040CB46 mov ebp, eax
.text:0040CB48 jz short loc_40CB52
.text:0040CB4A mov [esp+1Ch+var_1C], edi ; void *
.text:0040CB4D call free
.text:0040CB52 loc_40CB52:
; Функция сравнения двух строк
.text:0040CB52 mov [esp+1Ch+var_18], esi ; char *
.text:0040CB56 mov [esp+1Ch+var_1C], ebp ; char *
.text:0040CB59 call _stricmp
.text:0040CB5E test eax, eax
; По результатам сравнения установить значение регистра AL
.text:0040CB60 setz al
.text:0040CB63 test ebp, ebp
.text:0040CB65 movzx edi, al
.text:0040CB68 jz short loc_40CB72
.text:0040CB6A mov [esp+1Ch+var_1C], ebp ; void *
.text:0040CB6D call free
.text:0040CB72 loc_40CB72:
.text:0040CB72 mov [esp+1Ch+var_1C], ebx
.text:0040CB75 call sub_40C800
.text:0040CB7A test eax, eax
.text:0040CB7C jnz loc_40CACC
.text:0040CB82 mov [esp+1Ch+var_1C], esi
.text:0040CB85 call sub_40C850
.text:0040CB8A test eax, eax
.text:0040CB8C mov edx, edi
.text:0040CB8E jz loc_40CACE
.text:0040CB94 jmp loc_40CACC
.text:0040CB94 sub_40CAA0 endp

Первое, что мы узнаем из функции проверки, это длина серийника – не менее 24 символов. Отлично. Снова перезапустим программу под отладчиком и попробуем зарегистрировать с парой "ManHunter / PCL" и левым серийником подходящей длины, например, что-то типа "123456789012345678901234". В пошаговом режиме проходим проверку длины, но по адресу 0040CAE7 вызывается следующая функция проверки, которой передается регистрационное имя, и по ее результатам отладчик сразу же перебрасывает на выход с кодом неправильной регистрации. В чем же дело? Трассировкой заходим в нее и обнаруживаем сравнение введенного регистрационного имени с внутренним "черным списком". И, как легко убедиться, на первом месте этого списка красуется "ManHunter / PCL". Дело в том, что несколько лет назад я уже релизил эту программу на паблик.

http://i004.radikal.ru/1508/87/5544154a104f.png
Список забаненных имен

Следующим номером в списке идет название отечественной команды "REVENGE CREW", которая тоже выкладывала свой релиз MD5 CrackFAST. "Черный список" – вполне закономерная реакция аффтара на варез, но никакого практического смысла в нем нет. Я не гордый, не обломлюсь зарегистрировать на другое имя

Снова перезапускам программу, повторяем регистрацию с левым серийником, но на этот раз в качестве регистрационного имени будем использовать "Perm Crack Laboratory". В пошаговом режиме доходим до функции сравнения строк по адресу 0040CB59, и перед ее выполнением в регистрах наблюдаем следующую картину:

http://s018.radikal.ru/i517/1508/4e/ea559ae06e79.png
Сравнение серийников

Это введенный левый серийник и строка той же длины, с которой он сравнивается. Как вы уже догадались, это и есть правильный серийник. Сохраняем его куда-нибудь в блокнотик, снова перезапускаем программу и в очередной раз открываем окно регистрации. На этот раз в качестве регистрационной пары будет "Perm Crack Laboratory" и "8RBX4T5S8CCYC9DA4890123A".

http://s016.radikal.ru/i337/1508/d1/a25ad8b184e8.png
Программа успешно зарегистрирована

Программа благодарит за покупку (ха-ха три раза), значит регистрационные данные оказались правильными. Для верности перезапустим программу и попробуем восстановить какой-нибудь простенький хэш, например, от строки длиной 4 символа.

http://s018.radikal.ru/i512/1508/dc/5d22f29bb962.png
Ограничения в программе сняты

В незарегистрированной версии такая строка не прокатила бы, а тут ничего, все нашлось, причем достаточно быстро, меньше чем за секунду. Таким образом защита оказалась нейтрализована. Ну а за "черный список" аффтару спасибо, я посмеялся от души.

• Author: ManHunter
• Source: manhunter.ru

Оставьте комментарий