Blog. Just Blog

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

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

QSetup Installation Suite - очень толковая софтина для создания инсталляторов. Огромное количество настроек, удобный и интуитивно понятный интерфейс, все действия выполняются при помощи пошаговых мастеров, а промежуточный результат создаваемого дистрибутива можно сразу же посмотреть. Короче, годная вещь. И все бы хорошо, только за полновесную профессиональную лицензию придется выложить заоблачную сумму в полторы тысячи баксов. Вспоминается анекдот: "На базаре мужик продает петуха. К нему подходит покупатель. - Почем петух? - Пятьдесят тысяч. - А что так дорого-то? - Деньги очень нужны."

Забираем с офсайта дистрибутив, устанавливаем, смотрим что и как. Кстати, инсталлятор QSetup сделан в нем же самом, так что можно считать это презентацией продукта. Беглым осмотром главного исполняемого файла выясняется, что он упакован UPX. Упаковщик самый обычный, никаких модификаций и сюрпризов, снимается он командой upx -d Composer.exe

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

Отправляем распакованный файл на дизассемблирование, параллельно посмотрим на всякую триальность и прочее. На ввод неправильного серийника программа реагирует вот таким сообщением. Код, где оно используется, легко находится:
  1. CODE:005940FD                 mov     eax, [ebp+var_4]
  2. ; Вызвать функцию проверки
  3. CODE:00594100                 call    @SvrHTTP@_16513 ; SvrHTTP::_16513
  4. CODE:00594105                 test    al, al
  5. ; Если она вернула AL=0, то серийник неправильный
  6. CODE:00594107                 jnz     short loc_59412D
  7. CODE:00594109                 push    0
  8. CODE:0059410B                 push    0
  9. CODE:0059410D                 lea     ecx, [ebp+var_1C]
  10. CODE:00594110                 mov     edx, offset _str_Illegal_Registr.Text
  11. CODE:00594115                 mov     eax, offset _str_QMain_06.Text
  12. CODE:0059411A                 call    sub_4F6118
  13. CODE:0059411F                 mov     edx, [ebp+var_1C]
  14. CODE:00594122                 xor     ecx, ecx
  15. CODE:00594124                 xor     eax, eax
Тут, похоже, IDA слегка перестаралась, приписав внутреннюю функцию программы какой-то внешней динамической библиотеке. Ну да ладно, сути это не меняет. Вот эта функция:
  1. CODE:00517554                 push    ebp
  2. CODE:00517555                 mov     ebp, esp
  3. CODE:00517557                 push    ecx
  4. CODE:00517558                 push    ebx
  5. CODE:00517559                 mov     [ebp+var_4], eax
  6. CODE:0051755C                 mov     eax, [ebp+var_4]
  7. CODE:0051755F                 call    @System@@LStrAddRef$qqrpv
  8. CODE:00517564                 xor     eax, eax
  9. CODE:00517566                 push    ebp
  10. CODE:00517567                 push    offset loc_5175F3
  11. CODE:0051756C                 push    dword ptr fs:[eax]
  12. CODE:0051756F                 mov     fs:[eax], esp
  13. CODE:00517572                 lea     eax, [ebp+var_4]
  14. CODE:00517575                 call    sub_5161D4
  15. CODE:0051757A                 mov     eax, [ebp+var_4]
  16. CODE:0051757D                 call    unknown_libname_92
  17. ; Первая проверка - длина серийника должна быть не менее 10h (16) символов
  18. CODE:00517582                 cmp     eax, 10h
  19. CODE:00517585                 jl      short loc_51759B
  20. CODE:00517587                 mov     eax, [ebp+var_4]
  21. ; Вторая проверка - первый символ серийника должен быть "4"
  22. CODE:0051758A                 cmp     byte ptr [eax], 34h
  23. CODE:0051758D                 jnz     short loc_51759B
  24. CODE:0051758F                 mov     eax, [ebp+var_4]
  25. ; Следующий большой этап проверки
  26. CODE:00517592                 call    sub_5169D0
  27. CODE:00517597                 test    al, al
  28. CODE:00517599                 jnz     short loc_51759F
  29. CODE:0051759B loc_51759B:
  30. CODE:0051759B                 xor     ebx, ebx
  31. CODE:0051759D                 jmp     short loc_5175A1
  32. CODE:0051759F ; ----------------------------------------
  33. CODE:0051759F loc_51759F:
  34. CODE:0051759F                 mov     bl, 1
  35. CODE:005175A1 loc_5175A1:
  36. ; Серийник правильный?
  37. CODE:005175A1                 test    bl, bl
  38. CODE:005175A3                 jz      short loc_5175D5
  39. ; Дополнительно проверить тип лицензии
  40. CODE:005175A5                 mov     eax, [ebp+var_4]
  41. CODE:005175A8                 call    sub_516FC8
  42. CODE:005175AD                 test    al, al
  43. ; Тип лицензии LITE
  44. CODE:005175AF                 jnz     short loc_5175D9
  45. CODE:005175B1                 mov     eax, [ebp+var_4]
  46. CODE:005175B4                 call    sub_5170E0
  47. CODE:005175B9                 test    al, al
  48. ; Тип лицензии STUDIO
  49. CODE:005175BB                 jnz     short loc_5175D9
  50. CODE:005175BD                 mov     eax, [ebp+var_4]
  51. CODE:005175C0                 call    sub_5171F8
  52. CODE:005175C5                 test    al, al
  53. ; Тип лицензии PRO
  54. CODE:005175C7                 jnz     short loc_5175D9
  55. CODE:005175C9                 mov     eax, [ebp+var_4]
  56. ; Еще какая-то проверка, до которой дело, скорее всего, даже не дойдет
  57. CODE:005175CC                 call    sub_5173BC
  58. CODE:005175D1                 test    al, al
  59. CODE:005175D3                 jnz     short loc_5175D9
  60. CODE:005175D5 loc_5175D5:
  61. ; Введенный серийник неправильный
  62. CODE:005175D5                 xor     eax, eax
  63. CODE:005175D7                 jmp     short loc_5175DB
  64. CODE:005175D9 ; -----------------------------------------
  65. CODE:005175D9 loc_5175D9:
  66. ; Серийный номер правильный
  67. CODE:005175D9                 mov     al, 1
  68. CODE:005175DB loc_5175DB:
  69. CODE:005175DB                 mov     ebx, eax
  70. CODE:005175DD                 xor     eax, eax
  71. CODE:005175DF                 pop     edx
  72. CODE:005175E0                 pop     ecx
  73. CODE:005175E1                 pop     ecx
  74. CODE:005175E2                 mov     fs:[eax], edx
  75. CODE:005175E5                 push    offset loc_5175FA
  76. CODE:005175EA loc_5175EA:
  77. CODE:005175EA                 lea     eax, [ebp+var_4]
  78. CODE:005175ED                 call    @System@@LStrClr$qqrpv
  79. CODE:005175F2                 retn
Запускаем программу под отладчиком, ставим точку останова на начало функции проверки, отпускаем программу на выполнение и повторяем регистрацию с какими-нибудь левыми данными. Когда сработает точка останова, начинаем пошаговую трассировку. К моменту проверки длины серийник приходит очищенный от всех символов, которые не являются цифрами. Длина оставшихся данных должна быть 10h символов, то есть 16 в привычной нам десятичной системе. Это первая проверка. На второй проверке начальный символ серийного номера сравнивается с символом "4". Остальная часть колдунства происходит в следующей функции sub_5169D0. В комментариях к коду вы можете видеть что-то про проверку типа лицензии, об этом я расскажу чуть позже. Пока посмотрим, как выполняется проверка.
  1. CODE:005169D0                 push    ebp
  2. CODE:005169D1                 mov     ebp, esp
  3. CODE:005169D3                 xor     ecx, ecx
  4. CODE:005169D5                 push    ecx
  5. CODE:005169D6                 push    ecx
  6. CODE:005169D7                 push    ecx
  7. CODE:005169D8                 push    ecx
  8. CODE:005169D9                 push    ebx
  9. CODE:005169DA                 push    esi
  10. CODE:005169DB                 mov     [ebp+var_4], eax
  11. CODE:005169DE                 mov     eax, [ebp+var_4]
  12. CODE:005169E1                 call    @System@@LStrAddRef$qqrpv
  13. CODE:005169E6                 xor     eax, eax
  14. CODE:005169E8                 push    ebp
  15. CODE:005169E9                 push    offset loc_516A6D
  16. CODE:005169EE                 push    dword ptr fs:[eax]
  17. CODE:005169F1                 mov     fs:[eax], esp
  18. CODE:005169F4                 lea     eax, [ebp+var_4]
  19. CODE:005169F7                 call    sub_5161D4
  20. CODE:005169FC                 xor     ebx, ebx
  21. CODE:005169FE                 mov     eax, [ebp+var_4]
  22. CODE:00516A01                 call    unknown_libname_92
  23. CODE:00516A06                 mov     esi, eax
  24. CODE:00516A08                 cmp     esi, 4
  25. CODE:00516A0B                 jle     short loc_516A52
  26. CODE:00516A0D                 lea     eax, [ebp+var_8]
  27. CODE:00516A10                 push    eax
  28. CODE:00516A11                 mov     ecx, esi
  29. CODE:00516A13                 sub     ecx, 4
  30. CODE:00516A16                 mov     edx, 1
  31. CODE:00516A1B                 mov     eax, [ebp+var_4]
  32. CODE:00516A1E                 call    @System@@LStrCopy$qqrv
  33. CODE:00516A23                 lea     eax, [ebp+var_C]
  34. CODE:00516A26                 push    eax
  35. CODE:00516A27                 mov     edx, esi
  36. CODE:00516A29                 sub     edx, 3
  37. CODE:00516A2C                 mov     ecx, 4
  38. CODE:00516A31                 mov     eax, [ebp+var_4]
  39. CODE:00516A34                 call    @System@@LStrCopy$qqrv
  40. CODE:00516A39                 lea     edx, [ebp+var_10]
  41. CODE:00516A3C                 mov     eax, [ebp+var_8]
  42. ; Вызвать функцию подсчета контрольного значения
  43. CODE:00516A3F                 call    sub_516910
  44. CODE:00516A44                 mov     edx, [ebp+var_10]
  45. CODE:00516A47                 mov     eax, [ebp+var_C]
  46. ; Сравнить контрольную строку с последними 4 символами серийника
  47. CODE:00516A4A                 call    @System@@LStrCmp$qqrv
  48. ; Установить результат сравнения в BL
  49. CODE:00516A4F                 setz    bl
  50. CODE:00516A52 loc_516A52:
  51. CODE:00516A52                 xor     eax, eax
  52. CODE:00516A54                 pop     edx
  53. CODE:00516A55                 pop     ecx
  54. CODE:00516A56                 pop     ecx
  55. CODE:00516A57                 mov     fs:[eax], edx
  56. CODE:00516A5A                 push    offset loc_516A74
  57. CODE:00516A5F loc_516A5F:
  58. CODE:00516A5F                 lea     eax, [ebp+var_10]
  59. CODE:00516A62                 mov     edx, 4
  60. CODE:00516A67                 call    @System@@LStrArrayClr$qqrpvi
  61. CODE:00516A6C                 retn
  62. CODE:00516A6D loc_516A6D:
  63. CODE:00516A6D                 jmp     unknown_libname_76
  64. CODE:00516A72                 jmp     short loc_516A5F
  65. CODE:00516A74 ; -----------------------------------------------
  66. CODE:00516A74 loc_516A74:
  67. CODE:00516A74                 mov     eax, ebx
  68. CODE:00516A76                 pop     esi
  69. CODE:00516A77                 pop     ebx
  70. CODE:00516A78                 mov     esp, ebp
  71. CODE:00516A7A                 pop     ebp
  72. CODE:00516A7B                 retn
Под отладчиком видно, что от серийника отрезаются четыре последние символа, затем с оставшейся частью выполняются какие-то операции в функции sub_516910, а потом ее результат сравнивается с сохраненными ранее четырьмя последними символами. Если строки равны, то серийник считается правильным. Таким образом можно без труда подсмотреть правильное контрольное значение для любого серийного номера. Так, например, эту проверку пройдет серийник вида "4000 0000 0000 2926". Давайте посмотрим, как формируется контрольное число.
  1. CODE:00516910                 push    ebp
  2. CODE:00516911                 mov     ebp, esp
  3. CODE:00516913                 push    ecx
  4. CODE:00516914                 push    ebx
  5. CODE:00516915                 push    esi
  6. CODE:00516916                 mov     esi, edx
  7. CODE:00516918                 mov     [ebp+var_4], eax
  8. CODE:0051691B                 mov     eax, [ebp+var_4]
  9. CODE:0051691E                 call    @System@@LStrAddRef$qqrpv
  10. CODE:00516923                 xor     eax, eax
  11. CODE:00516925                 push    ebp
  12. CODE:00516926                 push    offset loc_5169C1
  13. CODE:0051692B                 push    dword ptr fs:[eax]
  14. CODE:0051692E                 mov     fs:[eax], esp
  15. CODE:00516931                 lea     eax, [ebp+var_4]
  16. CODE:00516934                 call    sub_5161D4
  17. CODE:00516939                 mov     eax, [ebp+var_4]
  18. CODE:0051693C                 call    unknown_libname_92
  19. CODE:00516941                 mov     ebx, 1
  20. CODE:00516946                 cmp     eax, 1
  21. CODE:00516949                 jl      short loc_51695F
  22. ; Получить число из символов серийника
  23. CODE:0051694B loc_51694B:
  24. CODE:0051694B                 mov     edx, [ebp+var_4]
  25. CODE:0051694E                 movzx   edx, byte ptr [edx+eax-1]
  26. CODE:00516953                 imul    edx, ebx
  27. CODE:00516956                 add     edx, eax
  28. CODE:00516958                 mov     ebx, edx
  29. CODE:0051695A                 dec     eax
  30. CODE:0051695B                 test    eax, eax
  31. CODE:0051695D                 jnz     short loc_51694B
  32. ; Привести число к четырехсимвольному значению
  33. CODE:0051695F loc_51695F:
  34. CODE:0051695F                 mov     eax, ebx
  35. CODE:00516961                 cdq
  36. CODE:00516962                 xor     eax, edx
  37. CODE:00516964                 sub     eax, edx
  38. CODE:00516966                 mov     ebx, eax
  39. CODE:00516968                 cmp     ebx, 1869Fh
  40. CODE:0051696E                 jge     short loc_516981
  41. CODE:00516970 loc_516970:
  42. CODE:00516970                 mov     eax, ebx
  43. CODE:00516972                 shl     eax, 4
  44. CODE:00516975                 add     eax, ebx
  45. CODE:00516977                 mov     ebx, eax
  46. CODE:00516979                 cmp     ebx, 1869Fh
  47. CODE:0051697F                 jl      short loc_516970
  48. CODE:00516981 loc_516981:
  49. CODE:00516981                 cmp     ebx, 270Fh
  50. CODE:00516987                 jle     short loc_51699D
  51. CODE:00516989 loc_516989:
  52. CODE:00516989                 mov     eax, ebx
  53. CODE:0051698B                 mov     ecx, 9
  54. CODE:00516990                 cdq
  55. CODE:00516991                 idiv    ecx
  56. CODE:00516993                 mov     ebx, eax
  57. CODE:00516995                 cmp     ebx, 270Fh
  58. CODE:0051699B                 jg      short loc_516989
  59. CODE:0051699D loc_51699D:
  60. CODE:0051699D                 mov     ecx, esi
  61. CODE:0051699F                 mov     edx, 4
  62. CODE:005169A4                 mov     eax, ebx
  63. ; Преобразовать число в строку
  64. CODE:005169A6                 call    sub_516134
  65. CODE:005169AB                 xor     eax, eax
  66. CODE:005169AD                 pop     edx
  67. CODE:005169AE                 pop     ecx
  68. CODE:005169AF                 pop     ecx
  69. CODE:005169B0                 mov     fs:[eax], edx
  70. CODE:005169B3                 push    offset loc_5169C8
  71. CODE:005169B8 loc_5169B8:
  72. CODE:005169B8                 lea     eax, [ebp+var_4]
  73. CODE:005169BB                 call    @System@@LStrClr$qqrpv
  74. CODE:005169C0                 retn
  75. CODE:005169C1 loc_5169C1:
  76. CODE:005169C1                 jmp     unknown_libname_76
  77. CODE:005169C6                 jmp     short loc_5169B8
  78. CODE:005169C8 loc_5169C8:
  79. CODE:005169C8                 pop     esi
  80. CODE:005169C9                 pop     ebx
  81. CODE:005169CA                 pop     ecx
  82. CODE:005169CB                 pop     ebp
  83. CODE:005169CC                 retn
Алгоритм очень простой, можно копировать в кейген практически без серьезных корректировок. Берется строка серийника от начала до 12-го символа, из нее поочередно извлекаются символы, начиная с конца. Коды этих символов в цикле перемножаются, результат складывается с текущей позицией строки, это все хорошо видно в отладчике. Полученное значение путем нескольких циклических делений и битовых операций приводится к четырехзначному числу. Все преобразования несложные для понимания и извлечения. Затем итоговое число преобразуется в строку, которая, в свою очередь, будет участвовать в сравнении.

Небольшое лирическое отступление. Вот так выглядит функция очистки серийника от всех не-цифр. Интересный код, ни разу такого не встречал.
  1. CODE:005161D4                 push    ebx
  2. CODE:005161D5                 push    esi
  3. CODE:005161D6                 mov     esi, eax
  4. CODE:005161D8                 mov     eax, [esi]
  5. CODE:005161DA                 call    unknown_libname_92
  6. CODE:005161DF                 mov     ebx, eax
  7. CODE:005161E1                 cmp     ebx, 1
  8. CODE:005161E4                 jl      short loc_516205
  9. CODE:005161E6 loc_5161E6:
  10. CODE:005161E6                 mov     eax, [esi]
  11. CODE:005161E8                 mov     al, [eax+ebx-1]
  12. CODE:005161EC                 add     al, 0D0h
  13. CODE:005161EE                 sub     al, 0Ah
  14. CODE:005161F0                 jb      short loc_516200
  15. CODE:005161F2                 mov     eax, esi
  16. CODE:005161F4                 mov     ecx, 1
  17. CODE:005161F9                 mov     edx, ebx
  18. CODE:005161FB                 call    @System@@LStrDelete$qqrv
  19. CODE:00516200 loc_516200:
  20. CODE:00516200                 dec     ebx
  21. CODE:00516201                 test    ebx, ebx
  22. CODE:00516203                 jnz     short loc_5161E6
  23. CODE:00516205 loc_516205:
  24. CODE:00516205                 pop     esi
  25. CODE:00516206                 pop     ebx
  26. CODE:00516207                 retn
Если убрать всю чешую, то останется небольшая и очень удобная функция для фильтрации строки, чтобы в ней остались символы только из заданного интервала. Надо будет перенести ее в полезные Ассемблерные функции.
  1.         mov     esi,szString   ; Исходная строка
  2.         mov     edi,szFiltered ; Отфильтрованная строка
  3. @@:
  4.         lodsb
  5.         or      al,al
  6.         jz      @f
  7.         mov     ah,al
  8.         add     ah,(256-'0')   ; Начальный символ интервала
  9.         sub     ah,10          ; Длина интервала
  10.         jnb     @b
  11.         stosb
  12.         jmp     @b
  13. @@:
  14.         stosb
Возвращаемся к исследованию. Проверка контрольного значения пройдена, теперь проверяется тип лицензии. Их может быть три вида - LITE, STUDIO и PRO. Если посмотреть обозначенные в первом блоке кода функции, то за каждый тип отвечает своя проверка. Она сводится к сравнению предпоследних четырех символов серийника со строками "1112", "2112" и "3112" для лицензии LITE, со строками "1212", "2212" и "3212" для лицензии STUDIO и строками "1312", "1412", "2312", "2412", "3312", "3412" для лицензии PRO. Выберите нужный вам тип лицензии. Но раз изменилась часть серийника, то изменится и его контрольное число, то есть последние 4 символа. Возвращаемся на шаг назад, вновь проходим в отладчике проверку контрольного числа. Теперь оно будет "1114", а серийник, соответственно, приобретет вид "4000 0000 3412 1114". Остальные символы значения не имеют и могут быть любыми. Кроме того, серийник может включать в себя любые буквенные символы, они все равно будут отфильтрованы. Так что итоговый серийный номер будет "4000-0000-MANHUNTER-PCL-3412-1114". Закрываем отладчик, запускаем программу в обычном режиме и проверяем регистрацию с найденным серийником:

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

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

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

Программа зарегистрирована на PRO-лицензию, все ограничения сняты. При желании можно написать кейген, после разбора тут уже ничего сложного. Но будьте предельно аккуратны! После успешного ввода серийного номера программа открывает браузер, куда передает имя компьютера, серийник, дату регистрации и прочую персональную информацию. Ни в коем случае нельзя ей позволять этого делать.

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

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (01.06.2022 в 21:09):
coldun, это примерно как рассказывать музыканту, что одну песню о любви уже написали :)
coldun (01.06.2022 в 18:36):
<При желании можно написать кейген, ...>
Так давно уж есть, с 16-го года как... ;)

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

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

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