Исследование защиты программы ExifCleaner
Скриншот программы ExifCleaner
ExifCleaner - программа для удаления EXIF-данных из цифровых фотографий и других графических файлов. Это позволяет уменьшить размер файлов при пересылке их по электронной почте или при публикации на сайтах. Существует немало бесплатных аналогов ExifCleaner, так что ограничивать себя в выборе инструмента для этих целей не придется. А вот скоротать часок-другой, ковыряясь в коде, будет интересно.
Скачиваем дистрибутив, устанавливаем, смотрим. Главный исполняемый файл упакован UPX, который снимается им же самим через upx -d. Тут никаких сюрпризов от автора нет. Запускаем распакованный файл и видим наг-окно с предложением отстегнуть бабла или ввести код регистрации. На ввод левых данных программа реагирует достаточно интересно:
Окно регистрации программы
То есть регистрационное имя должно содержать строчку типа "(Unlimited License)", "(Single User License)" или что-то около того. Теперь, если в регистрационное имя добавить строку "License", например, "ManHunter (License to Kill)", то сообщение об ошибке изменится на "The Licensee and Registration Code strings are not valid. Please verify that you inputted them correctly" (орфография автора сохранена). Вот так, не открывая ни отладчика, ни дизассемблера, только благодаря подсказке от разработчика, мы знаем формат регистрационного имени. Спасибо, чо.
Строка сообщения в ресурсах
Строка сообщения находится в ресурсах под номером 65205 или 0FEB5h в шестнадцатеричной системе счисления. Поищем эту строчку в листинге дизассемблера. Стандартный дельфийский бутерброд из последовательных указателей:
Code (Assembler) : Убрать нумерацию
- .text:004E8354 off_4E8354 dd offset hModule
- .text:004E8358 dd 0FEB5h
Code (Assembler) : Убрать нумерацию
- .data:00656A8C off_656A8C dd offset off_4E8354
Code (Assembler) : Убрать нумерацию
- .text:0061CD8D push 30h ; uType
- .text:0061CD8F lea edx, [ebp+var_2C]
- .text:0061CD92 mov eax, off_656AD8
- .text:0061CD97 call @System@LoadResString
- ; System::LoadResString(System::TResStringRec *)
- .text:0061CD9C mov eax, [ebp+var_2C]
- .text:0061CD9F call @System@@LStrToPChar
- ; System::__linkproc__ LStrToPChar(System::AnsiString)
- .text:0061CDA4 push eax ; lpCaption
- .text:0061CDA5 lea edx, [ebp+var_30]
- ; Загрузить строку сообщения из ресурсов
- .text:0061CDA8 mov eax, off_656A8C
- .text:0061CDAD call @System@LoadResString
- ; System::LoadResString(System::TResStringRec *)
- .text:0061CDB2 mov eax, [ebp+var_30]
- .text:0061CDB5 call @System@@LStrToPChar
- ; System::__linkproc__ LStrToPChar(System::AnsiString)
- .text:0061CDBA push eax ; lpText
- .text:0061CDBB push ebx ; hWnd
- ; Вывести сообщение на экран
- .text:0061CDBC call MessageBoxA
Code (Assembler) : Убрать нумерацию
- ; Вызвать какую-то функцию проверки
- .text:0061CD4A call sub_61C38C
- ; Если она вернула EAX!=9, то вывести сообщение об ошибке
- .text:0061CD4F cmp eax, 9
- .text:0061CD52 jnz short loc_61CD8D
- ; Иначе поблагодарить за регистрацию
Licensee=ManHunter (License to Kill)
RegCode=123123123123
Теперь разберем алгоритм проверки серийного номера. Адрес функции проверки мы знаем, это 0061C38C, пройдем его под отладчиком в пошаговом режиме. Параллельно с этим я буду комментировать процесс.
Code (Assembler) : Убрать нумерацию
- ; Часть кода пропущена для удобства восприятия
- ...
- .text:0061C3C3 push 0
- .text:0061C3C5 lea eax, [ebp+var_4]
- .text:0061C3C8 push eax
- ; Прочитать из ini-файла регистрационный номер и имя
- .text:0061C3C9 mov ecx, offset _str_Licensee.Text
- .text:0061C3CE mov edx, offset _str_Preferences_5.Text
- .text:0061C3D3 mov eax, ebx
- .text:0061C3D5 mov esi, [eax]
- .text:0061C3D7 call dword ptr [esi]
- .text:0061C3D9 push 0
- .text:0061C3DB lea eax, [ebp+var_8]
- .text:0061C3DE push eax
- .text:0061C3DF mov edx, offset _str_Preferences_5.Text
- .text:0061C3E4 mov ecx, offset _str_RegCode.Text
- .text:0061C3E9 mov eax, ebx
- .text:0061C3EB mov esi, [eax]
- .text:0061C3ED call dword ptr [esi]
- .text:0061C3EF mov eax, ebx
- .text:0061C3F1 call @System@TObject@Free$qqrv
- .text:0061C3F6 lea edx, [ebp+var_C]
- ; Указатель на строку регистрационного имени
- .text:0061C3F9 mov eax, [ebp+var_4]
- ; Посчитать хеш MD5 от строки регистрационного имени
- .text:0061C3FC call sub_61C250
- .text:0061C401 xor eax, eax
- .text:0061C403 mov [ebp+var_10], eax
- .text:0061C406 mov eax, [ebp+var_8]
- .text:0061C409 test eax, eax
- ; Длина серийного номера
- .text:0061C40B jz short loc_61C412
- .text:0061C40D sub eax, 4
- .text:0061C410 mov eax, [eax]
- .text:0061C412 loc_61C412:
- ; Первая проверка - длина должна быть 12 символов
- .text:0061C412 cmp eax, 0Ch
- .text:0061C415 jnz short loc_61C48F
- .text:0061C417 push ebp
- ; Проверка хеша регистрационного имени на его нахождение в "черном списке"
- .text:0061C418 call sub_61C2A0
- .text:0061C41D pop ecx
- .text:0061C41E test al, al
- .text:0061C420 jnz short loc_61C48F
Результат проверки криптоанализатора
Это самый обычный MD5. На этом же этапе проверяется длина серийного номера (она должна быть 12 символов, 3 группы по 4 символа без учета разделителей) и наличие регистрационного имени во внутреннем "черном списке". Дальше идут два цикла проверки:
Code (Assembler) : Убрать нумерацию
- ; Первый цикл проверки
- .text:0061C422 mov edx, 1
- .text:0061C427 mov eax, offset unk_6567C0
- .text:0061C42C loc_61C42C:
- .text:0061C42C mov ecx, [eax]
- .text:0061C42E test ecx, ecx
- .text:0061C430 jz short loc_61C446
- .text:0061C432 mov ebx, [ebp+var_8]
- .text:0061C435 movzx ebx, byte ptr [ebx+edx-1]
- .text:0061C43A mov esi, [ebp+var_C]
- ; Сравнить символ серийника из BL с символом из хеша
- .text:0061C43D cmp bl, [esi+ecx-1]
- .text:0061C441 jnz short loc_61C446
- .text:0061C443 inc [ebp+var_10]
- .text:0061C446 loc_61C446:
- .text:0061C446 inc edx
- .text:0061C447 add eax, 4
- .text:0061C44A cmp edx, 6
- .text:0061C44D jnz short loc_61C42C
- ...
- ; Второй цикл проверки
- .text:0061C463 mov edx, 6
- .text:0061C468 mov eax, offset unk_6567D4
- .text:0061C46D loc_61C46D:
- .text:0061C46D cmp dword ptr [eax], 0
- .text:0061C470 jz short loc_61C488
- .text:0061C472 mov ebx, [ebp+var_8]
- .text:0061C475 movzx ebx, byte ptr [ebx+edx-1]
- .text:0061C47A mov esi, [ebp+var_C]
- .text:0061C47D mov edi, [eax]
- ; Сравнить символ серийника из BL с символом из хеша
- .text:0061C47F cmp bl, [esi+edi-1]
- .text:0061C483 jnz short loc_61C488
- ; Увеличить счетчик совпавших символов
- .text:0061C485 inc [ebp+var_10]
- .text:0061C488 loc_61C488:
- .text:0061C488 inc edx
- .text:0061C489 add eax, 4
- .text:0061C48C dec ecx
- .text:0061C48D jnz short loc_61C46D
- ...
- ; Записать в EAX количество совпавших символов
- .text:0061C4B1 mov eax, [ebp+var_10]
- .text:0061C4B4 pop edi
- .text:0061C4B5 pop esi
- .text:0061C4B6 pop ebx
- .text:0061C4B7 mov esp, ebp
- .text:0061C4B9 pop ebp
- .text:0061C4BA retn
serial[00h] = md5[03h]
serial[01h] = md5[06h]
serial[02h] = md5[01h]
serial[03h] = любой
serial[04h] = md5[0Dh]
serial[05h] = md5[12h]
serial[06h] = md5[02h]
serial[07h] = md5[19h]
serial[08h] = любой
serial[09h] = любой
serial[0Ah] = md5[18h]
serial[0Bh] = md5[06h]
Так, для строки хеша "C2DF1E7DF12519AB4DF0D7C8D7183DCD", то есть для MD5 от строки "ManHunter (License to Kill)", по приведенной выше таблице соответствия серийный номер будет "F72P 9FD7 CLD7". Попробуем с его помощью зарегистрировать программу:
Программа успешно зарегистрирована
Регистрация прошла успешно, все ограничения сняты. Алгоритм оказался несложным, и рабочий кейген теперь вы можете написать самостоятельно.
Просмотров: 6770 | Комментариев: 8
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Сергей Севастополь
(05.11.2018 в 02:31):
СПАСИБО! Я тоже Ничего не делал, и не правил, ввел ManHunter (License to Kill) ключ F72P 9FD7 CLD7 и заработало...
ManHunter
(16.10.2014 в 10:29):
Только программа ущербная, уже есть на поядок мощнее
Диман
(15.10.2014 в 00:12):
До сих пор работает
ManHunter
(10.05.2012 в 23:18):
andrik004, ну так это и есть правильная регистрационная пара
andrik004
(10.05.2012 в 22:44):
Ничего не делал, и не правил, ввел ManHunter (License to Kill) ключ F72P 9FD7 CLD7 и заработало...
ManHunter
(29.04.2012 в 20:46):
Ну еще Windows 8 Metro Interface Disabler, наверное, пригодится в недалеком будущем. Но она фриварная.
AyTkACT
(29.04.2012 в 20:24):
ExifCleaner, имхо, самое ценное (полезное в прикладных целях) что создано этими разрабами (SuperUtils.com).
DimitarSerg
(26.04.2012 в 17:30):
Как всегда все аккуратненько и красиво. А конструкция вида
CALL ...
CMP ...
JNZ ...
уже как-то приелась (из последних 20-30 рассматриваемых прог почти в половине такая реализация проверки :) Для тех кто патчит - вообще идеальный вариант)
CALL ...
CMP ...
JNZ ...
уже как-то приелась (из последних 20-30 рассматриваемых прог почти в половине такая реализация проверки :) Для тех кто патчит - вообще идеальный вариант)
Добавить комментарий
Заполните форму для добавления комментария