Blog. Just Blog

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

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

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

Забираем с офсайта последний на сегодняшний день дистрибутив, устанавливаем, запускаем. После выбора языка нам сразу предлагают зарегистрироваться. Логично, ведь это платная версия и никакого пробного использования она не предполагает. На ввод левых данных реагирует следующим сообщением:

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

Так, исходные данные у нас есть. Исполняемый файл ничем не накрыт, отправляем его в дизассемблер. Затем поиском по всем файлам в папке с установленной программой ищем эту строчку. Она обнаружится в файле Resources\Scribe.lr8

Строка сообщения в языковом файле
Строка сообщения в языковом файле

Раз она там есть, значит каким-то образом программа должна эту строчку загружать. Если посмотреть внимательно, то выяснится, что у каждой строки в языковом файле есть уникальный идентификатор "Cid". Для интересующей нас строки он имеет значение 1090. Переведем десятичное число в шестнадцатеричное и поищем в коде место, где этот индекс используется.
  1. .text:005D80C3                 mov     ecx, [ebp+var_114]
  2. .text:005D80C9                 sub     ecx, 20h
  3. .text:005D80CC                 call    sub_40E880
  4. .text:005D80D1                 push    eax
  5. ; Вызвать функцию проверки
  6. .text:005D80D2                 call    sub_5D8680
  7. .text:005D80D7                 add     esp, 10h
  8. .text:005D80DA                 movzx   eax, al
  9. ; Если она вернула AL!=0, то регистрационные данные правильные
  10. .text:005D80DD                 test    eax, eax
  11. .text:005D80DF                 jnz     short loc_5D810B
  12. .text:005D80E1                 push    0
  13. .text:005D80E3                 mov     ecx, off_8037AC
  14. .text:005D80E9                 push    ecx
  15. ; Значение строки по умолчанию, если в ресурсах ее не найдено
  16. .text:005D80EA                 push    offset aThatNameAndKey
  17. ; "That name and key don't match."
  18. .text:005D80EF                 push    442h
  19. ; Загрузить строку с индексом 1090 (442h)
  20. .text:005D80F4                 call    ds:LgiLoadString
  21. .text:005D80FA                 add     esp, 8
  22. .text:005D80FD                 push    eax
  23. .text:005D80FE                 push    0
  24. ; Вывести сообщение о неправильной регистрации
  25. .text:005D8100                 call    ds:LgiMsg
  26. .text:005D8106                 add     esp, 10h
Вроде все понятно, вызывается функция проверки, по ее результатам или выводится сообщение о неправильной регистрации, или выполняется условный переход дальше по тексту. Как работает функция проверки лучше всего посмотреть под отладчиком. Ставим точку останова по адресу 005D8680, запускаем, повторяем регистрацию левыми данными.
  1. .text:005D869A                 cmp     [ebp+arg_0], 0
  2. .text:005D869E                 jz      loc_5D879A
  3. .text:005D86A4                 mov     eax, [ebp+arg_4]
  4. .text:005D86A7                 cmp     dword ptr [eax], 6
  5. .text:005D86AA                 jnz     loc_5D879A
  6. .text:005D86B0                 mov     ecx, [ebp+arg_4]
  7. .text:005D86B3                 cmp     dword ptr [ecx+8], 10h
  8. .text:005D86B7                 jnz     loc_5D879A
Проверяется регистрационное имя, чтобы оно не было пустым, затем проверяется длина неких двоичных данных, она должна быть 16 байт (10h). Что это за данные мы пока не знаем, поэтому пошагово трассируем до условного перехода и затем меняем флаг ZF на противоположный, чтобы условие не выполнилось. После этого мы попадаем на проверку забаненных ключей, но там ничего нужного нам нет. А вот дальше начинается самое интересное.
  1. .text:005D8721                 mov     eax, [ebp+arg_8]
  2. .text:005D8724                 push    eax
  3. .text:005D8725                 mov     ecx, [ebp+arg_0]
  4. .text:005D8728                 push    ecx
  5. .text:005D8729                 push    offset aSS_24   ; "%s%s"
  6. .text:005D872E                 push    100h            ; SizeInBytes
  7. .text:005D8733                 lea     edx, [ebp+DstBuf]
  8. .text:005D8739                 push    edx             ; DstBuf
  9. ; Сформировать строку из регистрационного имени и "соли"
  10. .text:005D873A                 call    ds:sprintf_s
  11. .text:005D8740                 add     esp, 14h
  12. .text:005D8743                 push    0FFFFFFFFh
  13. .text:005D8745                 lea     eax, [ebp+DstBuf]
  14. .text:005D874B                 push    eax
  15. .text:005D874C                 lea     ecx, [ebp+Buf1]
  16. .text:005D874F                 push    ecx
  17. ; Посчитать MD5 от полученной строки
  18. .text:005D8750                 call    ds:MDStringToDigest
  19. .text:005D8756                 add     esp, 0Ch
  20. .text:005D8759                 mov     edx, [ebp+arg_4]
  21. .text:005D875C                 mov     eax, [edx+8]
  22. .text:005D875F                 push    eax             ; Size
  23. .text:005D8760                 mov     ecx, [ebp+arg_4]
  24. .text:005D8763                 mov     edx, [ecx+0Ch]
  25. .text:005D8766                 push    edx             ; Buf2
  26. .text:005D8767                 lea     eax, [ebp+Buf1]
  27. .text:005D876A                 push    eax             ; Buf1
  28. ; Сравнить полученный хэш с переданными в функцию двоичными данными
  29. .text:005D876B                 call    ds:memcmp
  30. .text:005D8771                 add     esp, 0Ch
  31. .text:005D8774                 test    eax, eax
  32. .text:005D8776                 jnz     short loc_5D8784
  33. .text:005D8778                 mov     [ebp+var_120], 1
  34. .text:005D8782                 jmp     short loc_5D878E
Под отладчиком отлично видно, что берется введенное регистрационное имя, к нему через пробел дописывается строка "345dsdkhm3$%#S", а затем от этой строки считается MD5. Затем результат хэширования сравнивается с переданными в функцию данными и выносится вердикт о правильности или неправильности регистрационных данных. Но тут есть одна особенность, данные сравниваются не строками, а в двоичном виде, то есть где-то текстовый серийник должен быть преобразован в "сырые" байты. Вернемся в отладчик, поставим точку останова по адресу 005D7FB6, это начало блока, где вызываются функция проверки. В пошаговой трассировке выясняем, что введенный серийник используется здесь:
  1. .text:005D8053                 mov     edx, [eax+164h]
  2. .text:005D8059                 call    edx
  3. .text:005D805B                 push    eax             ; Str
  4. .text:005D805C                 lea     eax, [ebp+var_168]
  5. ; Адрес строки с введенным серийником
  6. .text:005D8062                 push    eax             ; int
  7. .text:005D8063                 call    sub_5D87B0
  8. .text:005D8068                 add     esp, 8
  9. .text:005D806B                 mov     [ebp+var_12C], eax
  10. .text:005D8071                 mov     ecx, [ebp+var_12C]
Осталось посмотреть, что происходит с введенным серийником в функции по адресу 005D87B0. Заглядываем в дизассемблер и видим следующее:
  1. .text:005D87FE                 mov     eax, [ebp+Str]
  2. .text:005D8801                 push    eax             ; Str
  3. .text:005D8802                 call    ds:strlen
  4. .text:005D8808                 add     esp, 4
  5. .text:005D880B                 push    eax
  6. .text:005D880C                 mov     ecx, [ebp+Str]
  7. .text:005D880F                 push    ecx
  8. .text:005D8810                 push    100h
  9. .text:005D8815                 lea     edx, [ebp+var_110]
  10. .text:005D881B                 push    edx
  11. .text:005D881C                 call    ds:ConvertBase64ToBinary
  12. .text:005D8822                 add     esp, 10h
  13. .text:005D8825                 mov     [ebp+var_118], eax
  14. .text:005D882B                 cmp     [ebp+var_118], 0
Вот и все, что требовалось узнать. Значит серийный номер должен быть в виде хэша MD5, сконвертированного в строку по алгоритму base64. Итоговый алгоритм генерации будет следующим. Берется регистрационное имя, например, "ManHunter / PCL", к нему через пробел дописывается строка "345dsdkhm3$%#S", получается "ManHunter / PCL 345dsdkhm3$%#S". От этой строки считается хэш MD5, в этом случае он будет a8f972c973575a9c945b8ad2d3a4a5ed. 16 байт двоичных данных хэша конвертируются в строку функцией base64. Полученная строка "qPlyyXNXWpyUW4rS06Sl7Q==" и будет правильным серийным номером.

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

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

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

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

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

Комментарии

Отзывы посетителей сайта о статье
doz.me (16.01.2021 в 20:05):
MaCTeP, в одну строку в batch/sh-файле можно уложиться, а тут 517 килобайт. "Это какой-то позор" (с)
ManHunter (26.11.2019 в 10:49):
Поменял ссылку, спасибо
0110 (26.11.2019 в 06:35):
в таком случае, нет ссылки для скачки inScribe. Там где "Забираем с офсайта последний на сегодняшний день дистрибутив" качается i.Scribe. На офсайте ссылки для inScribe тоже не увидел..
ManHunter (25.11.2019 в 19:42):
Так там и было две версии, бесплатная i.Scribe и платная inScribe
Василий (25.11.2019 в 19:34):
Дистрибутив поменяли на платную и бесплатную версии
0110 (25.11.2019 в 18:10):
не получилось ни вылечить, ни заюзать. При установке портабельной версии и выборе русского языка окна регистрации нет (может, дистрибутив поменяли или регистрация для всех языков кроме русского?). При настройке почты (с яндекса) необходим протокол SSL, который требует дополнительного софта в системе.., т.е. уже портабельной программы не получится..
MaCTeP (24.11.2019 в 18:14):
ManHunter (24.11.2019 в 16:49):
MaCTeP, работает, только размер какой-то монстрячий :)
MaCTeP (23.11.2019 в 23:38):
Нарисовал кейген к данному софту. Прошу проверить результат на валидность.

https://mega.nz/#!iLxHQYCA!3S7...rMo750o88meA

Доброй ночи...

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

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

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