Blog. Just Blog

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

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Темная сторона Силы | Автор: ManHunter
Скриншот программы 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 в шестнадцатеричной системе счисления. Поищем эту строчку в листинге дизассемблера. Стандартный дельфийский бутерброд из последовательных указателей:
  1. .text:004E8354 off_4E8354      dd offset hModule
  2. .text:004E8358                 dd 0FEB5h
  1. .data:00656A8C off_656A8C      dd offset off_4E8354
Третьей перекрестной ссылкой попадаем на код вывода на экран искомого сообщения об ошибке
  1. .text:0061CD8D                 push    30h             ; uType
  2. .text:0061CD8F                 lea     edx, [ebp+var_2C]
  3. .text:0061CD92                 mov     eax, off_656AD8
  4. .text:0061CD97                 call    @System@LoadResString
  5. ; System::LoadResString(System::TResStringRec *)
  6. .text:0061CD9C                 mov     eax, [ebp+var_2C]
  7. .text:0061CD9F                 call    @System@@LStrToPChar
  8. ; System::__linkproc__ LStrToPChar(System::AnsiString)
  9. .text:0061CDA4                 push    eax             ; lpCaption
  10. .text:0061CDA5                 lea     edx, [ebp+var_30]
  11. ; Загрузить строку сообщения из ресурсов
  12. .text:0061CDA8                 mov     eax, off_656A8C
  13. .text:0061CDAD                 call    @System@LoadResString
  14. ; System::LoadResString(System::TResStringRec *)
  15. .text:0061CDB2                 mov     eax, [ebp+var_30]
  16. .text:0061CDB5                 call    @System@@LStrToPChar
  17. ; System::__linkproc__ LStrToPChar(System::AnsiString)
  18. .text:0061CDBA                 push    eax             ; lpText
  19. .text:0061CDBB                 push    ebx             ; hWnd
  20. ; Вывести сообщение на экран
  21. .text:0061CDBC                 call    MessageBoxA
Чуть выше находится код, с которого выполняется условный переход на сообщение об ошибке:
  1. ; Вызвать какую-то функцию проверки
  2. .text:0061CD4A                 call    sub_61C38C
  3. ; Если она вернула EAX!=9, то вывести сообщение об ошибке
  4. .text:0061CD4F                 cmp     eax, 9
  5. .text:0061CD52                 jnz     short loc_61CD8D
  6. ; Иначе поблагодарить за регистрацию
Сперва некрасивый, но эффективный вариант решения. В начало функции проверки по адресу 0061C38C записываем команды MOV EAX,9 / RET и сохраняем изменения. После этого программа работает вообще без регистрации. Все настройки программы хранятся в файле %APPDATA%\SuperUtils.com\ExifCleaner\ExifClnr.ini и если его перенести в папку с установленной программой, то очень похоже, что она становится портативной. Также, если сперва ввести корректное с точки зрения программы регистрационное имя и неправильный серийный номер, то он все равно будет сохранен в этом файле. Поэтому если вы хотите наблюдать свое имя в окне "О программе", то сперва "зарегистрируйте" ее, а потом пропатчьте. Или сперва пропатчьте, а потом добавьте в конец файла ExifClnr.ini строчки типа:

Licensee=ManHunter (License to Kill)
RegCode=123123123123

Теперь разберем алгоритм проверки серийного номера. Адрес функции проверки мы знаем, это 0061C38C, пройдем его под отладчиком в пошаговом режиме. Параллельно с этим я буду комментировать процесс.
  1. ; Часть кода пропущена для удобства восприятия
  2. ...
  3. .text:0061C3C3                 push    0
  4. .text:0061C3C5                 lea     eax, [ebp+var_4]
  5. .text:0061C3C8                 push    eax
  6. ; Прочитать из ini-файла регистрационный номер и имя
  7. .text:0061C3C9                 mov     ecx, offset _str_Licensee.Text
  8. .text:0061C3CE                 mov     edx, offset _str_Preferences_5.Text
  9. .text:0061C3D3                 mov     eax, ebx
  10. .text:0061C3D5                 mov     esi, [eax]
  11. .text:0061C3D7                 call    dword ptr [esi]
  12. .text:0061C3D9                 push    0
  13. .text:0061C3DB                 lea     eax, [ebp+var_8]
  14. .text:0061C3DE                 push    eax
  15. .text:0061C3DF                 mov     edx, offset _str_Preferences_5.Text
  16. .text:0061C3E4                 mov     ecx, offset _str_RegCode.Text
  17. .text:0061C3E9                 mov     eax, ebx
  18. .text:0061C3EB                 mov     esi, [eax]
  19. .text:0061C3ED                 call    dword ptr [esi]
  20. .text:0061C3EF                 mov     eax, ebx
  21. .text:0061C3F1                 call    @System@TObject@Free$qqrv
  22. .text:0061C3F6                 lea     edx, [ebp+var_C]
  23. ; Указатель на строку регистрационного имени
  24. .text:0061C3F9                 mov     eax, [ebp+var_4]
  25. ; Посчитать хеш MD5 от строки регистрационного имени
  26. .text:0061C3FC                 call    sub_61C250
  27. .text:0061C401                 xor     eax, eax
  28. .text:0061C403                 mov     [ebp+var_10], eax
  29. .text:0061C406                 mov     eax, [ebp+var_8]
  30. .text:0061C409                 test    eax, eax
  31. ; Длина серийного номера
  32. .text:0061C40B                 jz      short loc_61C412
  33. .text:0061C40D                 sub     eax, 4
  34. .text:0061C410                 mov     eax, [eax]
  35. .text:0061C412 loc_61C412:
  36. ; Первая проверка - длина должна быть 12 символов
  37. .text:0061C412                 cmp     eax, 0Ch
  38. .text:0061C415                 jnz     short loc_61C48F
  39. .text:0061C417                 push    ebp
  40. ; Проверка хеша регистрационного имени на его нахождение в "черном списке"
  41. .text:0061C418                 call    sub_61C2A0
  42. .text:0061C41D                 pop     ecx
  43. .text:0061C41E                 test    al, al
  44. .text:0061C420                 jnz     short loc_61C48F
Первый этап проверки. Из ini-файла читаются серийный номер и регистрационное имя, после чего от имени считается хеш и переводится в верхний регистр. Что это за хеш, нам любезно подскажет KANAL (плагин для анализатора PEiD):

Результат проверки криптоанализатора
Результат проверки криптоанализатора

Это самый обычный MD5. На этом же этапе проверяется длина серийного номера (она должна быть 12 символов, 3 группы по 4 символа без учета разделителей) и наличие регистрационного имени во внутреннем "черном списке". Дальше идут два цикла проверки:
  1. ; Первый цикл проверки
  2. .text:0061C422                 mov     edx, 1
  3. .text:0061C427                 mov     eax, offset unk_6567C0
  4. .text:0061C42C loc_61C42C:
  5. .text:0061C42C                 mov     ecx, [eax]
  6. .text:0061C42E                 test    ecx, ecx
  7. .text:0061C430                 jz      short loc_61C446
  8. .text:0061C432                 mov     ebx, [ebp+var_8]
  9. .text:0061C435                 movzx   ebx, byte ptr [ebx+edx-1]
  10. .text:0061C43A                 mov     esi, [ebp+var_C]
  11. ; Сравнить символ серийника из BL с символом из хеша
  12. .text:0061C43D                 cmp     bl, [esi+ecx-1]
  13. .text:0061C441                 jnz     short loc_61C446
  14. .text:0061C443                 inc     [ebp+var_10]
  15. .text:0061C446 loc_61C446:
  16. .text:0061C446                 inc     edx
  17. .text:0061C447                 add     eax, 4
  18. .text:0061C44A                 cmp     edx, 6
  19. .text:0061C44D                 jnz     short loc_61C42C
  20. ...
  21. ; Второй цикл проверки
  22. .text:0061C463                 mov     edx, 6
  23. .text:0061C468                 mov     eax, offset unk_6567D4
  24. .text:0061C46D loc_61C46D:
  25. .text:0061C46D                 cmp     dword ptr [eax], 0
  26. .text:0061C470                 jz      short loc_61C488
  27. .text:0061C472                 mov     ebx, [ebp+var_8]
  28. .text:0061C475                 movzx   ebx, byte ptr [ebx+edx-1]
  29. .text:0061C47A                 mov     esi, [ebp+var_C]
  30. .text:0061C47D                 mov     edi, [eax]
  31. ; Сравнить символ серийника из BL с символом из хеша
  32. .text:0061C47F                 cmp     bl, [esi+edi-1]
  33. .text:0061C483                 jnz     short loc_61C488
  34. ; Увеличить счетчик совпавших символов
  35. .text:0061C485                 inc     [ebp+var_10]
  36. .text:0061C488 loc_61C488:
  37. .text:0061C488                 inc     edx
  38. .text:0061C489                 add     eax, 4
  39. .text:0061C48C                 dec     ecx
  40. .text:0061C48D                 jnz     short loc_61C46D
  41. ...
  42. ; Записать в EAX количество совпавших символов
  43. .text:0061C4B1                 mov     eax, [ebp+var_10]
  44. .text:0061C4B4                 pop     edi
  45. .text:0061C4B5                 pop     esi
  46. .text:0061C4B6                 pop     ebx
  47. .text:0061C4B7                 mov     esp, ebp
  48. .text:0061C4B9                 pop     ebp
  49. .text:0061C4BA                 retn
В циклах проверки делается следующее. Сперва обнуляется некий счетчик, затем в каждом цикле последовательно проверяется совпадение символов из серийного номера и хеша. Если совпадают, то счетчик увеличивается. На выходе функция возвращает количество совпавших символов. Если помните, то оно сравнивается с 9, то есть из 12 символов серийного номера значение имеют только 9, а остальные могут быть любыми. Осталось выяснить какие символы проверяются, это легко сделать под отладчиком, места сравнений каждого цикла я прокомментировал. В итоге получается такая таблица соответствия (нумерация символов в обеих строках начинается с 0):

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 рассматриваемых прог почти в половине такая реализация проверки :) Для тех кто патчит - вообще идеальный вариант)

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0077 сек.) / Память: 4.5 Mb
Наверх