Blog. Just Blog

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

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

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

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

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

Соответствующая надпись присутствует и в окне "О программе".

Окно "О программе"
Окно "О программе"

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

Удаляем пункты меню
Удаляем пункты меню

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

Шаблон диалога "О программе"
Шаблон диалога "О программе"

Там же в ресурсах находим шаблон диалогового окна "О программе", а в нем определяем идентификаторы кнопок "Buy Now" и "Register", это 1007 и 1010 соответственно. Переведем их в шестнадцатеричные значения и поищем в листинге дизассемблера. На этот раз обнаружится следующий код:
  1. .text:00423CDE sub_423CDE      proc near
  2. .text:00423CDE                 mov     eax, offset loc_4AFD60
  3. .text:00423CE3                 call    __EH_prolog
  4. .text:00423CE8                 push    ecx
  5. .text:00423CE9                 push    ebx
  6. .text:00423CEA                 push    esi
  7. .text:00423CEB                 push    edi
  8. .text:00423CEC                 mov     edi, ecx
  9. .text:00423CEE                 mov     esi, offset unk_4DE75C
  10. .text:00423CF3                 mov     ecx, esi
  11. ; Вызвать функцию проверки
  12. .text:00423CF5                 call    sub_424399
  13. ; Манипуляции с результатом вызова
  14. .text:00423CFA                 neg     eax
  15. .text:00423CFC                 sbb     eax, eax
  16. .text:00423CFE                 mov     ecx, edi
  17. .text:00423D00                 and     al, 0FBh
  18. .text:00423D02                 add     eax, 5
  19. ; Флаг отображения элемента диалогового окна
  20. .text:00423D05                 mov     ebx, eax
  21. .text:00423D07                 push    ebx             ; nCmdShow
  22. .text:00423D08                 push    3EFh            ; nIDDlgItem
  23. ; Скрыть или отобразить кнопку
  24. .text:00423D0D                 call    sub_49C363
  25. .text:00423D12                 mov     ecx, eax
  26. .text:00423D14                 call    sub_49C5C2
  27. .text:00423D19                 push    ebx             ; nCmdShow
  28. .text:00423D1A                 push    3F2h            ; nIDDlgItem
  29. .text:00423D1F                 mov     ecx, edi
  30. ; Скрыть или отобразить кнопку
  31. .text:00423D21                 call    sub_49C363
  32. .text:00423D26                 mov     ecx, eax
  33. .text:00423D28                 call    sub_49C5C2
  34. .text:00423D2D                 lea     eax, [ebp+lpString]
  35. .text:00423D30                 mov     ecx, esi
  36. .text:00423D32                 push    eax
  37. .text:00423D33                 call    sub_424421
  38. .text:00423D38                 push    [ebp+lpString]  ; lpString
  39. .text:00423D3B                 and     [ebp+var_4], 0
  40. .text:00423D3F                 mov     ecx, edi
  41. .text:00423D41                 push    3EDh            ; nIDDlgItem
  42. .text:00423D46                 call    sub_49C3BB
  43. .text:00423D4B                 or      [ebp+var_4], 0FFFFFFFFh
  44. .text:00423D4F                 lea     ecx, [ebp+lpString]
  45. .text:00423D52                 call    sub_49CEA0
  46. .text:00423D57                 mov     ecx, [ebp+var_C]
  47. .text:00423D5A                 pop     edi
  48. .text:00423D5B                 pop     esi
  49. .text:00423D5C                 pop     ebx
  50. .text:00423D5D                 mov     large fs:0, ecx
  51. .text:00423D64                 leave
  52. .text:00423D65                 retn
  53. .text:00423D65 sub_423CDE      endp
Как можно выяснить из кода функции проверки, она возвращает либо EAX=1, либо нулевое значение. Из математических и логических инструкций видно, что для получения EBX=0, то есть для скрытия элементов, из функции проверки должно вернуться EAX=1. Впечатываем в начало функции по адресу 00424399 пару команд MOV EAX,1 и RET, сохраняем изменения. Проверяем, теперь у нас в меню красота и в окне "О программе" нет лишних кнопок. Но осталась надпись об окончании триального срока, поэтому возвращаемся в дизассемблер. Поиском по строке выходим на следующий код:
  1. .text:00420400                 dec     eax
  2. .text:00420401                 mov     byte ptr [ebp+var_4], 3
  3. .text:00420405                 jz      loc_4204AD
  4. .text:0042040B                 dec     eax
  5. .text:0042040C                 jz      short loc_42045B
  6. .text:0042040E                 dec     eax
  7. .text:0042040F                 dec     eax
  8. .text:00420410                 jnz     loc_420502
  9. .text:00420416                 cmp     [ebp+arg_A], 0Ah
  10. .text:0042041B                 jz      short loc_420454
  11. .text:0042041D                 cmp     [ebp+arg_C], 0Ah
  12. .text:00420421                 jz      short loc_42043B
  13. .text:00420423                 cmp     [ebp+arg_C], 0Bh
  14. .text:00420427                 jz      short loc_42043B
  15. .text:00420429                 push    offset aYourFreeTrialH
  16. ; "Your free trial has expired!"
  17. .text:0042042E loc_42042E:
  18. .text:0042042E                 lea     ecx, [ebp+var_10]
  19. .text:00420431                 call    ??4CString@@QAEABV0@PBG@Z
  20. .text:00420436                 jmp     loc_420502
  21. .text:0042043B ; ---------------------------------------
  22. .text:0042043B loc_42043B:
  23. .text:0042043B                 push    [ebp+arg_10]    ; int
  24. .text:0042043E                 push    offset aYourFreeDDayTr
  25. ; "Your free %d-day trial has expired!"
  26. .text:00420443 loc_420443:
  27. .text:00420443                 lea     eax, [ebp+var_10]
  28. .text:00420446                 push    eax             ; int
  29. .text:00420447                 call    sub_49679D
  30. .text:0042044C                 add     esp, 0Ch
  31. .text:0042044F                 jmp     loc_420502
  32. .text:00420454 ; ---------------------------------------
  33. .text:00420454 loc_420454:
  34. .text:00420454                 push    offset aThisLicenseDoe
  35. ; "This license doesn't work with the curr"...
  36. .text:00420459                 jmp     short loc_42042E
  37. .text:0042045B ; ---------------------------------------
  38. .text:0042045B loc_42045B:
  39. .text:0042045B                 movzx   eax, [ebp+arg_A]
  40. .text:0042045F                 sub     eax, 0
  41. .text:00420462                 jz      short loc_42047D
  42. .text:00420464                 dec     eax
  43. .text:00420465                 jnz     loc_420502
  44. .text:0042046B                 mov     eax, [ebp+arg_1C]
  45. .text:0042046E                 push    dword ptr [eax+8]
  46. .text:00420471                 push    dword ptr [eax+4]
  47. .text:00420474                 push    dword ptr [eax]
  48. .text:00420476                 push    offset aYourLicenseH_0
  49. ; "Your license has expired!\r\n[Expiration "...
  50. .text:0042047B                 jmp     short loc_4204F6
  51. .text:0042047D ; ---------------------------------------
  52. .text:0042047D loc_42047D:
  53. .text:0042047D                 mov     eax, [ebp+arg_1C]
  54. .text:00420480                 mov     ecx, [eax]
  55. .text:00420482                 test    ecx, ecx
  56. .text:00420484                 jle     short loc_4204A3
  57. .text:00420486                 push    dword ptr [eax+8]
  58. .text:00420489                 push    dword ptr [eax+4]
  59. .text:0042048C                 lea     eax, [ebp+var_10]
  60. .text:0042048F                 push    ecx
  61. .text:00420490                 push    [ebp+arg_18]    ; int
  62. .text:00420493                 push    offset aThisProductIsL
  63. ; "This product is licensed to:\r\n%s\r\n[Expi"...
  64. .text:00420498                 push    eax             ; int
  65. .text:00420499                 call    sub_49679D
  66. .text:0042049E                 add     esp, 18h
  67. .text:004204A1                 jmp     short loc_420502
  68. .text:004204A3 ; ---------------------------------------
  69. .text:004204A3 loc_4204A3:
  70. .text:004204A3                 push    [ebp+arg_18]
  71. .text:004204A6                 push    offset aThisProductI_0
  72. ; "This product is licensed to:\r\n%s"
  73. .text:004204AB                 jmp     short loc_420443
  74. .text:004204AD ; ---------------------------------------
  75. .text:004204AD loc_4204AD:
  76. .text:004204AD                 movzx   eax, [ebp+arg_A]
  77. .text:004204B1                 sub     eax, 0
  78. .text:004204B4                 jz      short loc_4204CE
  79. .text:004204B6                 dec     eax
Чо-то тут автор явно перегнул с триальностью. Свободная триальная версия закончилась, сколькотодневная триальная закончилась, лицензия закончилась, еще что-то. Облегчим работу себе и программе, заменим условный переход по адресу 00420405 на безусловный JMP loc_4204A3, чтобы сразу выводилась строка о регистрации. Первой командой push там заносится в стек адрес строки с регистрационным именем, можете использовать это для наведения дополнительной красоты. Сохраняем изменения, смотрим.

Окно "О программе"
Окно "О программе"

Красота, да и только. Теперь переходим к триальному окну, которое появляется при запуске, а также к снятию ограничения по функционалу. В ресурсах находим шаблон триального окна, который имеет индекс 528 или 210h, если в шестнадцатеричной системе.

Шаблон триального окна
Шаблон триального окна

Вновь возвращаемся в дизассемблер и ищем код, где используется этот индекс, причем желательно недалеко от какой-нибудь функции работы с окнами. Обнаружится единственная процедура, где создается диалог с нужным нам индексом:
  1. .text:0041CBDE sub_41CBDE      proc near
  2. .text:0041CBDE                 mov     eax, offset loc_4AF1D1
  3. .text:0041CBE3                 call    __EH_prolog
  4. .text:0041CBE8                 push    ecx
  5. .text:0041CBE9                 push    esi
  6. .text:0041CBEA                 push    edi
  7. .text:0041CBEB                 mov     edi, ecx
  8. .text:0041CBED                 mov     [ebp+var_10], edi
  9. .text:0041CBF0                 push    [ebp+arg_8C]
  10. .text:0041CBF6                 and     [ebp+var_4], 0
  11. ; Создать диалоговое окно из шаблона
  12. .text:0041CBFA                 push    210h
  13. .text:0041CBFF                 call    ??0CDialog@@QAE@IPAVCWnd@@@Z
  14. ; CDialog::CDialog(uint,CWnd *)
  15. .text:0041CC04                 lea     esi, [edi+5Ch]
  16. .text:0041CC07                 mov     byte ptr [ebp+var_4], 1
  17. .text:0041CC0B                 mov     ecx, esi
  18. ...
  19. ...
Никаких условных переходов тут нет, просто открытие окна со всей необходимой кодовой обвязкой. По перекрестной ссылке переходим к единственному адресу, откуда эта процедура вызывается. Это процедура, в которой активно вызываются функции работы с таймером и системным временем, дергаются какие-то строки с характерными названиями "LastLicenseCheck", с достаточным количеством условных пререходов, а главное, что она вызывается ровно из двух мест. Логично предположить, что это один раз при запуске и один раз при попытке воспроизведения GIF-файла. Но если посмотреть еще на уровень выше, то обнаружится, что оба вызова никак не связаны с условными переходами, они, скорее, завязаны на обработчики событий типа нажатий на кнопки. Значит можно смело впечатывать в самое начало этой процедуры по адресу 0041E137 команду RET. Теперь надоедливое окно ни при каких условиях не появится. Сохраняем изменения, проверяем работоспособность программы.

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

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

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

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

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

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

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