Blog. Just Blog

Исследование защиты программы PDF to EXE Converter

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

Утилита PDF to EXE Converter от ApinSoft позволяет конвертировать PDF-документы в исполняемые файлы, которые не требуют наличия дополнительных инструментов для открытия PDF. Кроме этого можно выбрать большое количество дополнительных настроек типа ограничения по времени, отображения собственного сплеш-скрина, ограничения количества печати и просмотров, регистрации с привязкой к компьютеру и еще много чего интересного. Короче, реально полезный инструмент для издателей своих материалов в PDF-формате, даже если учесть, что может обработать не все файлы. На сайте доступен дистрибутив демо-версии, доступ к полной дается только после оплаты. Лишнего зеленого полтинника у меня не завалялось, будем работать с тем, что есть.

Забираем триальный дистрибутив, устанавливаем, смотрим.

Ограничения триальной версии
Ограничения триальной версии

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

Файл ничем не упакован, беглым осмотром можно выяснить, что он написан на Дельфи. Для работы с Дельфи есть очень хороший инструмент - IDR (Interactive Delphi Reconstructor). Загружаем исполняемый файл в него и ждем, когда декомпиляция будет завершена. Затем переходим к более внимательному осмотру.

Элементы формы в ресурсах
Элементы формы в ресурсах

Даже если разблокировать поля ввода какими-нибудь внешними инструментами, поменять в них текст все равно не получится. В главной форме приложения, которая имеет название TFORMMAIN заблокированные поля ввода пароля имеют названия "Edit9" и "Edit12" соответственно. Теперь надо найти код, в котором происходит работа с этими полями.

Сохраняем проект Дельфи
Сохраняем проект Дельфи

Чтобы иметь полную картину происходящего, я обычно сохраняю весь проект, так по комментариям с названиями элементов форм, а также самих форм, можно легко найти интересующий код. Так я делал при декомпиляции файлов в DeDe, так же поступаю и в IDR. Строка обнаружится в файле описания формы FormMain.dfm и в файле _Unit94.pas, в котором содержится код.
  1. 006BC087    lea         eax,[ebp-10]
  2. 006BC08A    mov         ecx,0
  3. 006BC08F    call        @LStrFromUStr
  4. 006BC094    mov         eax,dword ptr [ebp-8]
  5. 006BC097    mov         edx,dword ptr [ebp-10]
  6. ; Сравнить какие-то строки
  7. 006BC09A    call        @LStrEqual
  8. ; Если они равны, то вычистить из интерфейса все связанное с триалом
  9. 006BC09F    je          006BC0D3
  10. ; Показать кнопку "Buy now"
  11. 006BC0A1    mov         eax,dword ptr [ebp-4]
  12. 006BC0A4    mov         eax,dword ptr [eax+7FC];TFormMain.BitBtn1:TBitBtn
  13. 006BC0AA    mov         dl,1
  14. 006BC0AC    call        TControl.SetVisible
  15. ; Установить режим "только для чтения" на два поля ввода
  16. 006BC0B1    mov         eax,dword ptr [ebp-4]
  17. 006BC0B4    mov         eax,dword ptr [eax+65C];TFormMain.Edit9:TEdit
  18. 006BC0BA    mov         dl,1
  19. 006BC0BC    call        TEdit.SetReadOnly
  20. 006BC0C1    mov         eax,dword ptr [ebp-4]
  21. 006BC0C4    mov         eax,dword ptr [eax+660];TFormMain.Edit12:TEdit
  22. 006BC0CA    mov         dl,1
  23. 006BC0CC    call        TEdit.SetReadOnly
  24. 006BC0D1    jmp         006BC143
  25. ; Очистка интерфейса
  26. 006BC0D3    mov         eax,dword ptr [ebp-4]
  27. 006BC0D6    mov         eax,dword ptr [eax+7FC];TFormMain.BitBtn1:TBitBtn
  28. 006BC0DC    xor         edx,edx
  29. ; Спрятать кнопку покупки "Buy now"
  30. 006BC0DE    call        TControl.SetVisible
  31. 006BC0E3    mov         eax,dword ptr [ebp-4]
  32. ; Удалить пункты меню о покупке и регистрации
  33. 006BC0E6    mov         eax,dword ptr [eax+844]
  34. ;TFormMain.Buynow1:TMenuItem
  35. 006BC0EC    xor         edx,edx
  36. 006BC0EE    call        TMenuItem.SetVisible
  37. 006BC0F3    mov         eax,dword ptr [ebp-4]
  38. 006BC0F6    mov         eax,dword ptr [eax+840]
  39. ;TFormMain.EnterregistrationKey1:TMenuItem
  40. 006BC0FC    xor         edx,edx
  41. 006BC0FE    call        TMenuItem.SetVisible
  42. ; Разблокировать поля ввода
  43. 006BC103    mov         eax,dword ptr [ebp-4]
  44. 006BC106    mov         eax,dword ptr [eax+65C];TFormMain.Edit9:TEdit
  45. 006BC10C    xor         edx,edx
  46. 006BC10E    call        TEdit.SetReadOnly
  47. 006BC113    mov         eax,dword ptr [ebp-4]
  48. 006BC116    mov         eax,dword ptr [eax+660];TFormMain.Edit12:TEdit
  49. 006BC11C    xor         edx,edx
  50. 006BC11E    call        TEdit.SetReadOnly
Листинг немного отличается от привычного выхлопа IDA, но проблем с пониманием быть не должно. Выполняется какая-то проверка, по ее результатам выполняется или не выполняется условный переход. В одной ветке условия блокируются поля ввода и становится видимой кнопка покупки. В другой ветке алгоритма из интерфейса программы вырезается все, что так или иначе относится к триалу и покупке. Подгонять условия проверки не получается, это я выяснил под отладчиком, так что просто пропатчим условный переход по адресу 006BC09F, заменив его на безусловный. Сохраняем изменения, запускаем, смотрим. Все, касающееся регистрации, работает безупречно.

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

Можно сгенерить тестовый исполняемый файл из какого-нибудь PDF, защитив его регистрацией. Указанный произвольный серийник работает. Таким образом, в программе все триальные ограничения получаются сняты. Первая цель достигнута, едем дальше. Дело в том, что собранный exe-файл при запуске и завершении работы вываливает вот такое окно.

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

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

Соберем исполняемый файл с любыми настройками, затем отправим его на декомпиляцию в IDR. И точно так же, как мы делали с основным файлом, сохраним проект. Заодно посмотрим список форм. Триальное окно в ресурсах имеет название "Form2". Запускаем поиск этой строки по файлам проекта, найдутся три файла: _Unit74.pas - обработчик триального окна, Form2.dfm с описанием формы и главный обработчик приложения - mainformUnit.pas. Он-то нас и интересует. Как мы помним, триальное окно открывается два раза. Первое вхождение:
  1. 0067AD57    mov         eax,ebx
  2. 0067AD59    call        006804AC
  3. 0067AD5E    mov         eax,[0069E0F0];gvar_0069E0F0:TForm1
  4. 0067AD63    mov         eax,dword ptr [eax+46C]
  5. 0067AD69    mov         edx,67AEA8;'2'
  6. ; Выполнить какое-то сравнение
  7. 0067AD6E    call        @UStrEqual
  8. ; Прыжок в обход триального окна
  9. 0067AD73    je          0067AD9C
  10. 0067AD75    mov         ecx,dword ptr ds:[695C8C]
  11. ;^Application:TApplication
  12. 0067AD7B    mov         ecx,dword ptr [ecx]
  13. 0067AD7D    mov         dl,1
  14. ; Создать триальное окно и отобразить его
  15. 0067AD7F    mov         eax,[0064D398];TForm2
  16. 0067AD84    call        TCustomForm.Create;TForm2.Create
  17. 0067AD89    mov         esi,eax
  18. 0067AD8B    mov         eax,esi
  19. 0067AD8D    mov         edx,dword ptr [eax]
  20. 0067AD8F    call        dword ptr [edx+168];TCustomForm.ShowModal
  21. 0067AD95    mov         eax,esi
  22. 0067AD97    call        TObject.Free
  23. 0067AD9C    mov         eax,dword ptr [ebx+834];TForm1.pMem:Pointer
  24. 0067ADA2    test        eax,eax
  25. 0067ADA4    je          0067ADAC
  26. 0067ADA6    push        eax
Второе вхождение очень похожее.
  1. 0067D5E1    call        @UStrAsg
  2. 0067D5E6    mov         eax,dword ptr [ebp-4]
  3. 0067D5E9    mov         eax,dword ptr [eax+480];TForm1.m_cc:string
  4. 0067D5EF    mov         edx,67EBF8;'1'
  5. 0067D5F4    call        @UStrEqual
  6. ; Прыжок в обход триального окна
  7. 0067D5F9    je          0067D622
  8. 0067D5FB    mov         ecx,dword ptr ds:[695C8C]
  9. ;^Application:TApplication
  10. 0067D601    mov         ecx,dword ptr [ecx]
  11. 0067D603    mov         dl,1
  12. ; Создать триальное окно и отобразить его
  13. 0067D605    mov         eax,[0064D398];TForm2
  14. 0067D60A    call        TCustomForm.Create;TForm2.Create
  15. 0067D60F    mov         ebx,eax
  16. 0067D611    mov         eax,ebx
  17. 0067D613    mov         edx,dword ptr [eax]
  18. 0067D615    call        dword ptr [edx+168];TCustomForm.ShowModal
  19. 0067D61B    mov         eax,ebx
  20. 0067D61D    call        TObject.Free
  21. 0067D622    mov         dl,1
  22. 0067D624    mov         eax,[00444334];TStringList
  23. 0067D629    call        TStringList.Create;TStringList.Create
  24. 0067D62E    mov         dword ptr [ebp-30],eax
  25. 0067D631    mov         dl,1
  26. 0067D633    mov         eax,[00447970];TMemoryStream
  27. 0067D638    call        TObject.Create;TMemoryStream.Create
  28. 0067D63D    mov         ebx,eax
Для решения проблемы надо просто заменить условные переходы по адресам 0067AD73 и 0067D5F9 на безусловные, таким образом триальные окна больше никогда не появятся. Поскольку стаб в готовых файлах всегда одинаковый, можно сделать универсальный патч для изменения байтиков по указанным выше фиксированным адресам. На этом и вторая цель достигнута.

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (11.09.2024 в 12:40):
Ну вот, век живи - век учись :) За offzip спасибо, классная утилита, не знал про такую.
pawel97 (08.09.2024 в 19:35):
Занопить переход .663246 - и стаб можно не патчить. Выйти на код можно, как по строке 21obk12, фигурирующей в стабе в проверке показывать ли стартовое окно, так и по длиннющей строке из цифр, один-в-один как в проверке реги при запуске проги. Кстати, idr не определяет последнее как код, hiew наше всё.
Но если бы безвариантно пришлось заменять стаб (тут он просто упакован zlib) - то есть удобный консольный тул offzip и его ключи -a (достать) и -a -r (упаковать обратно). Что-то на qt/qml так пролечивал: распаковать сорцы, поправить блокнотом и затолкать назад.

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

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

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