Blog. Just Blog

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

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

Restorator - один из самых известных редакторов ресурсов для Windows. Основная фишка, которая мне в нем нравилась больше всего - это возможность создания автономных патчей ресурсов, например, для русификации программ. Но этим, конечно же, список его достоинств не ограничивается. К недостаткам могу отнести, пожалуй, весьма специфический интерфейс для работы с файлами и необходимость выкладывать деньги за лицензию. Много лет этот редактор не обновлялся, а тут вдруг разработчики решили допилить его под современные реалии. Так что эта статья посвящается возвращению легенды.

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

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

Ладно, файл ничем не упакован, отправляем его в дизассемблер. А пока давайте поищем в файле что-нибудь, относящееся к этому окну, например, заголовок. В ресурсах обнаружится следующая строчка.

Строка в ресурсах
Строка в ресурсах

Ее индекс 64778 в десятичной или 0FD0Ah в шестнадцатеричной системе счисления. Поищем индекс в листинге.
  1. .text:0054B094 off_54B094      dd offset hModule
  2. .text:0054B098                 dd 0FD0Ah
Знакомая конструкция - указатель на указатель. По перекрестной ссылке выходим на код, где этот указатель используется.
  1. .text:0054B09C sub_54B09C      proc near               ; CODE XREF: sub_54B110+5 p
  2. .text:0054B09C var_4           = dword ptr -4
  3. .text:0054B09C                 push    ebp
  4. .text:0054B09D                 mov     ebp, esp
  5. .text:0054B09F                 push    0
  6. .text:0054B0A1                 push    ebx
  7. .text:0054B0A2                 mov     ebx, eax
  8. .text:0054B0A4                 xor     eax, eax
  9. .text:0054B0A6                 push    ebp
  10. .text:0054B0A7                 push    offset loc_54B102
  11. .text:0054B0AC                 push    dword ptr fs:[eax]
  12. .text:0054B0AF                 mov     fs:[eax], esp
  13. .text:0054B0B2                 lea     edx, [ebp+var_4]
  14. .text:0054B0B5                 mov     eax, offset off_54B094
  15. .text:0054B0BA                 call    @System@LoadResString
  16. .text:0054B0BF                 mov     edx, [ebp+var_4]
  17. .text:0054B0C2                 mov     eax, ebx
  18. .text:0054B0C4                 call    @Controls@TControl
  19. .text:0054B0C9                 xor     edx, edx
  20. .text:0054B0CB                 mov     eax, [ebx+368h]
  21. .text:0054B0D1                 call    @Extctrls@TNotebook
  22. .text:0054B0D6                 mov     eax, [ebx+360h]
  23. .text:0054B0DC                 mov     [eax+114h], ebx
  24. ...
Тут только загрузка строк и подготовка формы. Идем выше к месту, откуда эта функция вызывается.
  1. .text:0054B110 sub_54B110      proc near
  2. .text:0054B110                 push    ebx
  3. .text:0054B111                 mov     ebx, eax
  4. .text:0054B113                 mov     eax, ebx
  5. .text:0054B115                 call    sub_54B09C
  6. .text:0054B11A                 mov     eax, ebx
  7. .text:0054B11C                 mov     edx, [eax]
  8. .text:0054B11E                 call    dword ptr [edx+0FCh]
  9. .text:0054B124                 pop     ebx
  10. .text:0054B125                 retn
  11. .text:0054B125 sub_54B110      endp
Тоже ничего интересного. Тут подготовленная форма выводится на экран. Дальше.
  1. .text:005754AD                 mov     eax, off_599548
  2. .text:005754B2                 mov     eax, [eax]
  3. .text:005754B4                 call    sub_4DB038
  4. ; Указатель на блок параметров
  5. .text:005754B9                 mov     eax, off_599548
  6. .text:005754BE                 mov     eax, [eax]
  7. ; Байт по смещению 15h должен быть ненулевым, иначе вывести окно регистрации
  8. .text:005754C0                 cmp     byte ptr [eax+15h], 0
  9. .text:005754C4                 jnz     short loc_57550C
  10. .text:005754C6                 mov     ecx, off_5999DC
  11. .text:005754CC                 mov     ecx, [ecx]
  12. .text:005754CE                 mov     dl, 1
  13. .text:005754D0                 mov     eax, ds:off_54A858
  14. .text:005754D5                 call    @Forms@TCustomForm
  15. .text:005754DA                 mov     edx, off_5997D8
  16. .text:005754E0                 mov     [edx], eax
  17. .text:005754E2                 mov     eax, off_5997D8
  18. .text:005754E7                 mov     eax, [eax]
  19. .text:005754E9                 call    sub_54B110
  20. .text:005754EE                 mov     eax, off_599548
  21. .text:005754F3                 mov     eax, [eax]
  22. .text:005754F5                 cmp     byte ptr [eax+15h], 0
  23. .text:005754F9                 jnz     short loc_57550C
  24. .text:005754FB                 mov     eax, off_5999DC
  25. .text:00575500                 mov     eax, [eax]
  26. .text:00575502                 call    @Forms@TApplication@Terminate
  27. .text:00575507                 jmp     loc_575645
  28. .text:0057550C ; ---------------------------------------------
  29. .text:0057550C loc_57550C:
  30. .text:0057550C                 cmp     byte_5992FC, 0
  31. .text:00575513                 jz      short loc_575534
  32. .text:00575515                 mov     eax, off_5999DC
Бинго! В регистр EAX загружается указатель на некий блок данных, как мне кажется, что-то типа настроек программы, один байт из которых отвечает за то, чтобы показывать при запуске форму регистрации или нет. Есть предложение помочь программе с этим :) Для этого команду cmp byte ptr [eax+15h], 0 по адресу 005754C0 надо заменить на равную ей по размеру команду mov byte ptr [eax+15h], 1, а следующий за ней условный переход на безусловный. Тем самым мы взведем флаг зарегистрированности, который будет использоваться в дальнейшем, а также сразу перепрыгнем форму регистрации. Сохраняем изменения, запускаем, ииии.....

Собщение о поврежденном файле
Собщение о поврежденном файле

Где-то выполняется проверка целостности исполняемого файла. Мы его пропатчили, стало быть, целостность нарушена. Давайте поищем, где находится строка этого сообщения.

Строка сообщения в ресурсах
Строка сообщения в ресурсах

Вот, строка найдена в ресурсах. Ее индекс 64581 в десятичной или 0FC45h в шестнадцатеричной системе счисления. Поищем индекс в листинге.
  1. .text:0057512C off_57512C      dd offset hModule
  2. .text:00575130                 dd 0FC45h
По перекрестным ссылкам выходим на следующий код:
  1. .text:0058204B                 call    sub_5076E0
  2. .text:00582050                 test    al, al
  3. .text:00582052                 jnz     short loc_582075
  4. .text:00582054                 lea     edx, [ebp+var_C]
  5. .text:00582057                 mov     eax, offset off_57512C
  6. .text:0058205C                 call    @System@LoadResString
  7. .text:00582061                 mov     ecx, [ebp+var_C]
  8. .text:00582064                 mov     dl, 1
  9. .text:00582066                 mov     eax, ds:off_408858
  10. .text:0058206B                 call    unknown_libname_157
  11. .text:00582070                 call    @System@@RaiseExcept$qqrv
Все понятно. Выполняется проверка, если ее результат программу не удовлетворил, то выводится сообщение и бросается исключение, приводящее к завершению программы. Патчим условный переход по адресу 00582052 на безусловный, сохраняем изменения, запускаем. Отлично, теперь программа работает в полноценном режиме, все функции доступны, никаких ограничений нет.

Остался еще один момент. Хоть все функциональные ограничения сняты и программа запускается, в окне "О программе" и сплеш-окне, которое появляется при старте, все равно наблюдается надпись "Trial Version":

Триальная надпись
Триальная надпись

Оно вроде и не мешается, и вообще, сплеш-окно можно отключить в настройках, но хочется, чтобы все было красиво.

Строка в ресурсах
Строка в ресурсах

Находим строку в ресурсах, по индексу находим указатель на указатель.
  1. .text:00573440 off_573440      dd offset hModule
  2. .text:00573444                 dd 0FC64h
В листинге находим следующий код.
  1. ; Сравнить переменную с нулевым значением
  2. .text:005735FE                 cmp     [ebp+var_11], 0
  3. .text:00573602                 jz      short loc_573641
  4. ; Если она не равна 0, то вывести строку "Licended to.."
  5. .text:00573604                 lea     eax, [ebp+var_24]
  6. .text:00573607                 push    eax
  7. .text:00573608                 lea     edx, [ebp+var_28]
  8. .text:0057360B                 mov     eax, offset off_573448
  9. .text:00573610                 call    @System@LoadResString
  10. .text:00573615                 mov     eax, [ebp+var_28]
  11. .text:00573618                 push    eax
  12. .text:00573619                 mov     eax, [ebp+var_4]
  13. .text:0057361C                 mov     [ebp+var_30], eax
  14. .text:0057361F                 mov     [ebp+var_2C], 0Bh
  15. .text:00573623                 lea     edx, [ebp+var_30]
  16. .text:00573626                 xor     ecx, ecx
  17. .text:00573628                 pop     eax
  18. .text:00573629                 call    unknown_libname_127
  19. .text:0057362E                 mov     edx, [ebp+var_24]
  20. .text:00573631                 mov     eax, [ebp+var_8]
  21. .text:00573634                 mov     eax, [eax+37Ch]
  22. .text:0057363A                 call    @Controls@TControl@SetText
  23. .text:0057363F                 jmp     short loc_57365F
  24. .text:00573641 ; ---------------------------------------
  25. .text:00573641 loc_573641:
  26. ; Если 0, то строка будет "Trial version"
  27. .text:00573641                 lea     edx, [ebp+var_34]
  28. .text:00573644                 mov     eax, offset off_573440
  29. .text:00573649                 call    @System@LoadResString
  30. .text:0057364E                 mov     edx, [ebp+var_34]
  31. .text:00573651                 mov     eax, [ebp+var_8]
  32. .text:00573654                 mov     eax, [eax+37Ch]
  33. .text:0057365A                 call    @Controls@TControl
Надо выяснить, где инициализируется переменная, которая участвует в этой проверке. Листаем выше:
  1. .text:00573555                 push    [ebp+var_20]
  2. .text:00573558                 push    offset stru_573898.Text
  3. .text:0057355D                 push    offset _str_Registration_0.Text
  4. .text:00573562                 lea     eax, [ebp+var_1C]
  5. .text:00573565                 mov     edx, 3
  6. .text:0057356A                 call    @System@@LStrCatN$qqrv
  7. .text:0057356F                 mov     edx, [ebp+var_1C]
  8. .text:00573572                 xor     ecx, ecx
  9. .text:00573574                 mov     eax, [ebp+var_18]
  10. .text:00573577                 call    @Registry@TRegistry@OpenKey
  11. .text:0057357C                 test    al, al
  12. .text:0057357E                 jz      short loc_5735A2
  13. .text:00573580                 mov     edx, offset _str_Name_2.Text
  14. .text:00573585                 mov     eax, [ebp+var_18]
  15. .text:00573588                 call    @Registry@TRegistry@ValueExists
  16. .text:0057358D                 test    al, al
  17. .text:0057358F                 jz      short loc_5735A2
  18. .text:00573591                 mov     edx, offset _str_Password_0.Text
  19. .text:00573596                 mov     eax, [ebp+var_18]
  20. .text:00573599                 call    @Registry@TRegistry@ValueExists
  21. .text:0057359E                 test    al, al
  22. .text:005735A0                 jnz     short loc_5735A6
  23. .text:005735A2 loc_5735A2:
  24. .text:005735A2                 xor     eax, eax
  25. .text:005735A4                 jmp     short loc_5735A8
  26. .text:005735A6 ; ---------------------------------------
  27. .text:005735A6 loc_5735A6:
  28. .text:005735A6                 mov     al, 1
  29. .text:005735A8 loc_5735A8:
  30. .text:005735A8                 mov     [ebp+var_11], al
По виду ничего сложного. Проверяется наличие определенных ключей реестра, если хоть одного не обнаружится, то выводится триальная строка. С помощью любого монитора реестра или под отладчиком выясням, какие именно ветки реестра задействуются. Это будет ключ HKEY_CURRENT_USER\Software\Bome Software\Restorator\Registration и параметры "Name" и "Password". Нетрудно понять, что в параметре "Name" хранится регистрационное имя, а в параметре "Password" что-то типа серийного номера.

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

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Bome Software\Restorator\Registration]
"Name"="ManHunter / PCL"
"Password"="Fuck Shareware"

Последняя контрольная проверка - все работает.

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

Вот и все, программа работает, в реестре прописано правильное регистрационное имя, а жизнь прекрасна. Цель достигнута. Хотя, как мне кажется, подобные программы должны быть портативными "из коробки".

Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 937 | Комментариев: 9

Комментарии

Отзывы посетителей сайта о статье
ManHunter (17.09.2018 в 08:33):
С таким уровнем рановато браться за взломы. Подтяни теорию, через пару лет возвращайся.
Сергей (17.09.2018 в 05:54):
Здравствуйте
Можно несколько вопросов от новичка?
Как определили что индекс 64581 в десятичной в шестнадцатеричной системе будет 0FC45h
Что такое листинг и как в нем искать
Как патчить условный переход по адресу 00582052 на безусловный

Спасибо
pawel97 (08.08.2018 в 17:39):
p.s. Не, crc всё равно патчить. Первый раз при изменении 5754C0 в памяти (не в файле) вылезло сообщение, а 4db44d нет, может глюк... Не важно, будет 2-й вариант.
pawel97 (08.08.2018 в 16:55):
Как вариант - этот кусок под проверку целостности не попал, и выполняется чуть раньше, и патчить чуть меньше:
004DB44D      FE40 15       inc byte ptr ds:[eax+15]
Вышел хардварным бряком на нужный байт.
Styx (07.08.2018 в 15:11):
Спасибо за еще одно руководство к действию! :)
Прошел немного дальше и записал данные регистрации в исполняемом файле, чтобы не вносить их каждый раз в реестр.
xussr (06.08.2018 в 12:37):
Классика!!!!(какие дрова)
Спасибо за прекрасный урок
Владимир (06.08.2018 в 11:26):
в процессе исследования столкнулись с отслеживанием, ведь программа могла быть не знаю как правильно сказать оболочкой для драйвера, просто есть прога, которая общается с драйвером, а процмон нифига не показывает
ManHunter (06.08.2018 в 10:53):
Process Monitor. Только какое отношение это имеет к статье?
Владимир (06.08.2018 в 08:59):
Спасибо! А если к реестру обращается драйвер, уже никак не отследить?

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

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

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