Blog. Just Blog

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

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Темная сторона Силы | Автор: ManHunter
Скриншот программы Sib Font Editor
Скриншот программы Sib Font Editor

Sib Font Editor - просмотрщик и редактор для растровых шрифтов в формате FNT и FON. Вы можете отредактировать готовый шрифт или создать свой собственный шрифт. Без регистрации работает только 30 запусков и постоянно показывает рекламу.

Забираем с офсайта дистрибутив, устанавливаем, смотрим. При старте появляется триальное окно с предложением потратить деньги на покупку серийника или ввести этот самый серийник.

Триальное окно
Триальное окно

С покупкой пока повременим. На ввод левых регистрационных данных программы программа реагирует следующим сообщением.

Сообщение о неправильной регистрации
Сообщение о неправильной регистрации

Исполняемый файл ничем не упакован, отправляем его в дизассемблер на разбор. Когда работа будет закончена, посмотрим на код, где эти строки появляются.
  1. CODE:004E51E9                 lea     edx, [ebp+var_20]
  2. CODE:004E51EC                 mov     eax, [ebx+2F8h]
  3. CODE:004E51F2                 call    sub_430AF8
  4. CODE:004E51F7                 mov     eax, [ebp+var_20]
  5. CODE:004E51FA                 call    sub_4E4A4C
  6. CODE:004E51FF                 test    eax, eax
  7. CODE:004E5201                 jz      short loc_4E520D
  8. CODE:004E5203                 mov     eax, offset aWrongKey_
  9. ; "Wrong key."
  10. CODE:004E5208                 call    sub_4E50D4
  11. CODE:004E520D loc_4E520D:
  12. CODE:004E520D                 mov     eax, [ebp+var_8]
  13. CODE:004E5210                 call    sub_4E4AAC
  14. CODE:004E5215                 mov     edx, [ebx+308h]
  15. CODE:004E521B                 mov     eax, [ebp+var_8]
  16. CODE:004E521E                 call    sub_4E48D8
  17. CODE:004E5223                 test    eax, eax
  18. CODE:004E5225                 jz      short loc_4E5231
  19. CODE:004E5227                 mov     eax, offset aWrongKeyForThi
  20. ; "Wrong key for this application."
  21. CODE:004E522C                 call    sub_4E50D4
  22. CODE:004E5231 loc_4E5231:
  23. CODE:004E5231                 mov     dl, 1
  24. CODE:004E5233                 mov     eax, off_463D64
  25. CODE:004E5238                 call    sub_463E64
Помимо проверки корректности email, тут присутствуют две проверки ключа. Судя по тексту сообщений, первая должна проверять корректность формата ключа, а вторая - принадлежность ключа именно этой программе. Начнем с первой.
  1. CODE:004E4A4C sub_4E4A4C      proc near
  2. CODE:004E4A4C                 push    ebp
  3. CODE:004E4A4D                 mov     ebp, esp
  4. CODE:004E4A4F                 push    ecx
  5. CODE:004E4A50                 push    ebx
  6. CODE:004E4A51                 push    esi
  7. CODE:004E4A52                 mov     [ebp+var_4], eax
  8. CODE:004E4A55                 mov     eax, [ebp+var_4]
  9. CODE:004E4A58                 call    sub_404104
  10. CODE:004E4A5D                 xor     eax, eax
  11. CODE:004E4A5F                 push    ebp
  12. CODE:004E4A60                 push    offset loc_4E4A9C
  13. CODE:004E4A65                 push    dword ptr fs:[eax]
  14. CODE:004E4A68                 mov     fs:[eax], esp
  15. ; Обнулить счетчик
  16. CODE:004E4A6B                 xor     esi, esi
  17. ; Повторить проверку 10 раз
  18. CODE:004E4A6D                 mov     ebx, 0Ah
  19. CODE:004E4A72 loc_4E4A72:
  20. CODE:004E4A72                 mov     eax, [ebp+var_4]
  21. ; Вызвать функцию проверки
  22. CODE:004E4A75                 call    sub_4E47E4
  23. ; Добавить к счетчику результат проверки
  24. CODE:004E4A7A                 add     esi, eax
  25. ; Пауза
  26. CODE:004E4A7C                 push    64h             ; dwMilliseconds
  27. CODE:004E4A7E                 call    Sleep
  28. CODE:004E4A83                 dec     ebx
  29. ; Следующая итерация
  30. CODE:004E4A84                 jnz     short loc_4E4A72
  31. CODE:004E4A86                 xor     eax, eax
  32. CODE:004E4A88                 pop     edx
  33. CODE:004E4A89                 pop     ecx
  34. CODE:004E4A8A                 pop     ecx
  35. CODE:004E4A8B                 mov     fs:[eax], edx
  36. CODE:004E4A8E                 push    offset loc_4E4AA3
  37. CODE:004E4A93 loc_4E4A93:
  38. CODE:004E4A93                 lea     eax, [ebp+var_4]
  39. CODE:004E4A96                 call    sub_403CD0
  40. CODE:004E4A9B                 retn
  41. CODE:004E4A9C ; --------------------------------------
  42. CODE:004E4A9C loc_4E4A9C:
  43. CODE:004E4A9C                 jmp     loc_4036E4
  44. CODE:004E4AA1                 jmp     short loc_4E4A93
  45. CODE:004E4AA3 loc_4E4AA3:
  46. ; Записать в EAX полученный счетчик
  47. CODE:004E4AA3                 mov     eax, esi
  48. CODE:004E4AA5                 pop     esi
  49. CODE:004E4AA6                 pop     ebx
  50. CODE:004E4AA7                 pop     ecx
  51. CODE:004E4AA8                 pop     ebp
  52. CODE:004E4AA9                 retn
  53. CODE:004E4AA9 sub_4E4A4C      endp
Итак, что тут происходит? 10 раз вызывается какая-то функция, ее результат суммируется и возвращается в качестве результата первой проверки. Судя по предыдущему коду, результат суммирования должен быть нулевой. Пауза, как вы можете догадаться, нужна исключительно для придания важности, с понтом идут какие-то могучие вычисления для проверки введенного серийника. Больше тут ничего интересного нет, нужно смотреть функцию, которая тут вызывается по адресу 004E47E4. Смотреть ее мы будем под отладчиком. Загружаем программу, ставим точку останова по адресу 004E47E4, запускаем на выполнение, вводим левые регистрационные данные. Когда точка останова сработает, в пошаговом режиме смотрим, что происходит. Немного кода я пропущу, оставлю только значимую часть.
  1. CODE:004E483D                 xor     ebx, ebx
  2. CODE:004E483F                 mov     eax, [ebp+var_4]
  3. CODE:004E4842                 call    sub_403F50
  4. CODE:004E4847                 dec     eax
  5. CODE:004E4848                 sub     eax, 2
  6. CODE:004E484B                 jl      short loc_4E4861
  7. CODE:004E484D                 inc     eax
  8. CODE:004E484E                 mov     edx, 2
  9. CODE:004E4853 loc_4E4853:
  10. CODE:004E4853                 mov     ecx, [ebp+var_4]
  11. CODE:004E4856                 movzx   ecx, byte ptr [ecx+edx-1]
  12. CODE:004E485B                 xor     ebx, ecx
  13. CODE:004E485D                 inc     edx
  14. CODE:004E485E                 dec     eax
  15. CODE:004E485F                 jnz     short loc_4E4853
  16. CODE:004E4861 loc_4E4861:
  17. CODE:004E4861                 mov     eax, ebx
  18. CODE:004E4863                 mov     ecx, 1Eh
  19. CODE:004E4868                 cdq
  20. CODE:004E4869                 idiv    ecx
  21. CODE:004E486B                 inc     edx
  22. CODE:004E486C                 mov     eax, offset a2345679qwert_0
  23. ; "2345679qwertyupadfghjkzxcvbnms"
  24. CODE:004E4871                 mov     al, [eax+edx-1]
  25. CODE:004E4875                 mov     edx, [ebp+var_4]
  26. CODE:004E4878                 cmp     al, [edx+esi-1]
  27. CODE:004E487C                 jz      short loc_4E4881
  28. CODE:004E487E                 inc     [ebp+var_8]
  29. CODE:004E4881 loc_4E4881:
Экспериментируя с разными серийниками, я обратил внимание, что перед этим кодом в одной из вызываемых функций из серийника вырезаются все символы, которые не встречаются в строке "2345679qwertyupadfghjkzxcvbnms". Затем проверяется длина оставшейся строки, она должна быть не менее 7 символов. Дальше нас интересует приведенный выше код. Тут поочередно берутся символы серийника, начиная со второго по счету и заканчивая предпоследним, они XOR'ятся друг на друга, а результат затем делится на константу 1Eh. К остатку прибавляется единица и полученное значение используется для получения индекса символа из строки "2345679qwertyupadfghjkzxcvbnms". Независимо от длины серийника, этот символ должен равняться последнему символу серийника. Если это не так, то проверка считается заваленной и счетчик инкрементируется. Значение этого счетчика возвращается в качестве результата, что, в свою очередь, приводит к увеличению счетчика в первой проверке. Вот только нафига это делать 10 раз, если результат на каждой итерации всегда будет одинаковым? "Делать раз за разом одно и то же действие и ожидать от этого различного результата - это безумие". Цитата вроде приписывается Эйнштейну, сложно с этим не согласиться.

Отлично, набор символов для серийника мы выяснили, длину серийника тоже, первую проверку узнали. Переходим ко второй проверке, которая отвечает за принадлежность серийника программе. Часть кода я тоже пропущу, там уже знакомые действия по очистке серийника от невалидных символов и проверка его длины. Дальше делается следующее:
  1. CODE:004E4941                 xor     ebx, ebx
  2. CODE:004E4943                 mov     eax, [ebp+var_8]
  3. CODE:004E4946                 call    sub_403F50
  4. CODE:004E494B                 dec     eax
  5. CODE:004E494C                 test    eax, eax
  6. CODE:004E494E                 jle     short loc_4E4963
  7. CODE:004E4950                 mov     edx, 1
  8. CODE:004E4955 loc_4E4955:
  9. CODE:004E4955                 mov     ecx, [ebp+var_8]
  10. CODE:004E4958                 movzx   ecx, byte ptr [ecx+edx-1]
  11. CODE:004E495D                 add     ebx, ecx
  12. CODE:004E495F                 inc     edx
  13. CODE:004E4960                 dec     eax
  14. CODE:004E4961                 jnz     short loc_4E4955
  15. CODE:004E4963 loc_4E4963:
  16. CODE:004E4963                 mov     eax, ebx
  17. CODE:004E4965                 mov     ecx, 1Eh
  18. CODE:004E496A                 cdq
  19. CODE:004E496B                 idiv    ecx
  20. CODE:004E496D                 inc     edx
  21. CODE:004E496E                 mov     eax, offset a2345679qwert_1
  22. ; "2345679qwertyupadfghjkzxcvbnms"
  23. CODE:004E4973                 mov     al, [eax+edx-1]
  24. CODE:004E4977                 mov     edx, [ebp+var_4]
  25. CODE:004E497A                 cmp     al, [edx+1]
  26. CODE:004E497D                 jz      short loc_4E4980
Код очень похожий, но только символы не XOR'ятся, а суммируются. Под отладчиком выясняется, что это действие выполняется не с серийником, а со строкой "Sib Font Editor". То есть на выходе гарантированно получается константа, равная "m". Она сравнивается со вторым по счету символом серийника. Едем дальше. А дальше строка "Sib Font Editor" переводится в нижний регистр, от нее берется первый символ "s" и записывается в начало серийника заменяя первый символ. Зачем то все??? Если откинуть все пляски, то вторая проверка сводится к сравнению первых двух символов серийника со строкой "sm".

Придумываем серийник, например, "sm2manhunter2pcl2x". Вторую проверку он гарантированно проходит, надо только выяснить последний символ. Перезапускаем программу под отладчиком, повторяем регистрацию, чтобы сработала точка останова на первой проверке. В шаговом режиме выясняем, что неправильный символ "x" сравнивается с правильным символом "4". Таким образом, правильный серийный номер будет иметь вид "sm2manhunter2pcl24". Закрываем отладчик, запускаем программу в обычном режиме, повторяем регистрацию с найденным серийником.

Сообщение о корректной регистрации
Сообщение о корректной регистрации

После перезапуска программы никакие триальные окна больше не появляются, реклама тоже пропала.

Программа успешно зарегистрирована
Программа успешно зарегистрирована

Цель достигнута. Генератор ключей вы можете теперь написать самостоятельно. Похожим способом решаются вопросы и с остальными программами этого разработчика.

Поделиться ссылкой ВКонтакте
Просмотров: 1404 | Комментариев: 3

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
fury (12.02.2021 в 11:54):
Selfiless Patch
Wrong key for this application
74 - EB
ManHunter (10.02.2021 в 20:47):
Тут вообще можно обойтись без патчей и кейгенов. В отладчике поменять в нужных местах флаги на условных переходах, чтобы левый серийник прошел валидацию, программа запишет ветку реестра со своей регистрацией, попросит перезапустить себя и потом будет работать как ни в чем не бывало с этой левой регой. То есть валидность проверяется только при вводе серийника, а потом просто проверяется _наличие_ соответствующих ключей в реестре. Там же в реестре удаляется отсчет количества триальных запусков, если религия не дает в открытую пользоваться варезом.

REGEDIT4
[HKEY_CURRENT_USER\Software\SibCode\FontEditor\Registered]
"Key"="333333333333"
"UserName"="ManHunter / PCL"
"Email"="222222222"
doz.me (08.02.2021 в 20:42):
я бы не разбирался с больной фантазией автора, стандартно либо nop/jmp, либо в функции mov al,1 ret.
за это и ценим твои кейген-туториалы Дмитрий, не пожалел времени, спасибо ;)

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

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

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