Blog. Just Blog

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

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

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

Скачиваем дистрибутив, распаковываем его куда-нибудь. Единственный исполняемый файл ничем не упакован, поэтому сразу его отправляем на разбор в дизассемблер. С проявлениями триальности сталкиваемся сразу же после запуска: появляется окно с предложением зарегистрироваться.

Окно регистрации программы
Окно регистрации программы

Вводим любые левые данные вместо серийника и получаем сообщение, что они неправильные. Ну логично, чо.

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

Но нас в данном случае интересует текст сообщения о неправильной регистрации. Нужная нам строка легко обнаруживается в ресурсах файла:

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

Строка имеет индекс 142 в десятичной или 8Eh в шестнадцатеричной системе счисления. Поищем в дизассемблере, где это значение используется.
  1. .text:0043FD20                 mov     ecx, [ebp+var_40]
  2. .text:0043FD23                 push    eax
  3. .text:0043FD24                 push    ecx
  4. ; Вызвать функцию проверки
  5. .text:0043FD25                 call    sub_442D20
  6. .text:0043FD2A                 mov     edx, off_479E20
  7. .text:0043FD30                 add     esp, 8
  8. ; Проверить ее результат, он не должен быть равен 0
  9. .text:0043FD33                 test    al, al
  10. .text:0043FD35                 mov     eax, [edx+0Ch]
  11. .text:0043FD38                 mov     ecx, offset off_479E20
  12. ; Переход на сообщение об успешной регистрации
  13. .text:0043FD3D                 jnz     loc_43FF66
  14. .text:0043FD43                 call    eax
  15. .text:0043FD45                 lea     edi, [eax+10h]
  16. .text:0043FD48                 mov     [ebp+var_3C], edi
  17. .text:0043FD4B                 push    0               ; wLanguage
  18. .text:0043FD4D                 push    8Dh             ; int
  19. .text:0043FD52                 mov     byte ptr [ebp+var_4], 7
  20. .text:0043FD56                 call    sub_4010B0
  21. .text:0043FD5B                 add     esp, 8
  22. .text:0043FD5E                 test    eax, eax
  23. .text:0043FD60                 jz      short loc_43FD73
  24. .text:0043FD62                 push    8Dh             ; lpWideCharStr
  25. .text:0043FD67                 push    eax             ; hModule
  26. .text:0043FD68                 lea     ecx, [ebp+var_3C]
  27. .text:0043FD6B                 call    sub_402330
  28. .text:0043FD70                 mov     edi, [ebp+var_3C]
  29. .text:0043FD73 loc_43FD73:
  30. .text:0043FD73                 mov     edx, off_479E20
  31. .text:0043FD79                 mov     eax, [edx+0Ch]
  32. .text:0043FD7C                 mov     bl, 8
  33. .text:0043FD7E                 mov     ecx, offset off_479E20
  34. .text:0043FD83                 mov     byte ptr [ebp+var_4], bl
  35. .text:0043FD86                 call    eax
  36. .text:0043FD88                 lea     esi, [eax+10h]
  37. .text:0043FD8B                 mov     [ebp+var_38], esi
  38. .text:0043FD8E                 push    0               ; wLanguage
  39. ; Загрузить строку сообщения о неправильной регистрации из ресурсов
  40. .text:0043FD90                 push    8Eh             ; int
  41. .text:0043FD95                 mov     byte ptr [ebp+var_4], 9
  42. .text:0043FD99                 call    sub_4010B0
  43. .text:0043FD9E                 add     esp, 8
  44. .text:0043FDA1                 test    eax, eax
  45. .text:0043FDA3                 jz      short loc_43FDB6
  46. .text:0043FDA5                 push    8Eh             ; lpWideCharStr
  47. .text:0043FDAA                 push    eax             ; hModule
  48. .text:0043FDAB                 lea     ecx, [ebp+var_38]
  49. .text:0043FDAE                 call    sub_402330
  50. .text:0043FDB3                 mov     esi, [ebp+var_38]
  51. .text:0043FDB6 loc_43FDB6:
  52. .text:0043FDB6                 mov     ecx, [ebp+var_44]
  53. .text:0043FDB9                 mov     edx, [ecx+4]
  54. .text:0043FDBC                 push    30h             ; uType
  55. .text:0043FDBE                 push    edi             ; lpCaption
  56. .text:0043FDBF                 push    esi             ; lpText
  57. .text:0043FDC0                 push    edx             ; hWnd
  58. .text:0043FDC1                 mov     byte ptr [ebp+var_4], bl
  59. ; Вывести сообщение о неправильной регистрации
  60. .text:0043FDC4                 call    ds:MessageBoxA
  61. .text:0043FDCA                 add     esi, 0FFFFFFF0h
Пока что все понятно. Вызывается какая-то функция проверки, по ее результатам выводится сообщение о неправильной регистрации или наоборот, о правильной. Теперь посмотрим функцию проверки:
  1. .text:00442D20                 push    ebp
  2. .text:00442D21                 mov     ebp, esp
  3. .text:00442D23                 mov     eax, [ebp+arg_4]
  4. .text:00442D26                 sub     esp, 14h
  5. .text:00442D29                 push    ebx
  6. .text:00442D2A                 mov     ebx, [ebp+arg_0]
  7. .text:00442D2D                 push    eax
  8. .text:00442D2E                 push    ebx
  9. ; Вызвать еще одну функцию проверки
  10. .text:00442D2F                 call    sub_442BB0
  11. .text:00442D34                 add     esp, 8
  12. ; Если она вернула AL=0, то регистрация неправильная
  13. .text:00442D37                 test    al, al
  14. ; Переход на запись регистрационных данных в реестр
  15. .text:00442D39                 jnz     short loc_442D40
  16. .text:00442D3B                 pop     ebx
  17. .text:00442D3C                 mov     esp, ebp
  18. .text:00442D3E                 pop     ebp
  19. .text:00442D3F                 retn
  20. .text:00442D40 ; ---------------------------------------
  21. .text:00442D40 loc_442D40:
  22. .text:00442D40                 push    edi
  23. .text:00442D41                 xor     edi, edi
Тут тоже вроде все понятно. Вызывается следующая функция проверки, в зависимости от ее результатов возвращается AL=0 (неправильная регистрация) или введенные данные сохраняются в реестр. Идем дальше в следующую функцию проверки. Визуально там разбираться проблематично, поэтому пройдем ее в пошаговом режиме под отладчиком. И вот на этом участке кода
  1. .text:00442C76                 push    edx
  2. .text:00442C77                 push    eax
  3. .text:00442C78                 call    sub_401450
  4. .text:00442C7D                 add     esp, 0Ch
  5. .text:00442C80                 cmp     eax, ebx
на стеке обнаруживаются такие интересные значения:

Сравнение серийников на стеке
Сравнение серийников на стеке

Интуиция мне подсказывает, что это функция сравнения правильного серийного номера, который был подсчитан из введенного регистрационного имени, и левого серийника, введенного вручную. Сохраняем значение 4V8B-48M7-PP6U-3M9Q где-нибудь в сухом прохладном месте и закрываем отладчик. Теперь запускаем программу в обычном режиме и пробуем повторить регистрацию с тем же именем, но в качестве серийника уже возьмем найденную в отладчике строку.

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

На этот раз программа приняла серийник и поблагодарила за регистрацию.

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

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

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

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

Комментарии

Отзывы посетителей сайта о статье
xussr (30.01.2018 в 09:30):
Это точно старая версия OllyDbg 1.10 рулит без косяков
xussr
"APQA-BF8D-7HYD-DX8S"
ManHunter (19.08.2015 в 23:10):
Видимо зашкаливающая сырость, поддержка не всех плагинов и отсутствие нормальных модов?
hatmaster (19.08.2015 в 23:07):
ManHunter,
ЦитатаOllyDbg 1.10
- а с 2.01 что не так?
ManHunter (14.08.2015 в 00:36):
32-битная система, OllyDbg 1.10, IDA Pro, HIEW. Этого вполне достаточно для исследований.
SHREEF (25.07.2015 в 19:00):
Видемо вы все сидите на win32 а у меня win64 ? и что-то отловить правильный серийник не выходит в стеке только тот что я ввожу
user (21.07.2015 в 08:17):
ЦитатаПотому что проверка серийника при вводе и при запуске программы выполняется в разных местах.

Часто проверка при вводе рег.данных вообще ни при чём - программа вежливо благодарит за ввод любых регистрационных данных и говорит, что они будут учтены при следующем запуске. Главная проверка в другом месте, которое отловить сложнее, так как никаких сообщений при той проверке не выдаётся.
ManHunter (21.07.2015 в 00:39):
Потому что проверка серийника при вводе и при запуске программы выполняется в разных местах.
DagalProject (21.07.2015 в 00:36):
Интересно, а почему патч mov AL, 1 и Ret в начале функции проверки не меняет ситуации в лучшую сторону. Регистрирует, но .......
user (20.07.2015 в 20:42):
.. и тогда адо отрезать оверлей и обнулить сумму в PE-хидере.
Воизбежание
user (20.07.2015 в 20:26):
Цитатанадо патчить проверку серийника при запуске программы и можно будет вообще сделать ее портативной.

А можно втулить короткий прыжок по адресу .00411B35 , поправить два байта -
- тогда 30 дней понадоедает с регистрацией, а потом, поняв, что всё зря, предлагать перестанет.
ManHunter (20.07.2015 в 08:31):
SergVic, надо патчить проверку серийника при запуске программы и можно будет вообще сделать ее портативной.
SergVic (20.07.2015 в 02:13):
ps Рано радуюсь не доделал
SergVic (20.07.2015 в 01:54):
Спасибо за ваши уроки Вот, что я сделал
00401465 cmp eax[ecx] меняем на cmp eax[edx]
00442c76 push edx меняем на push eax
и программа принимает любой серийник и имя
SHREEF (19.07.2015 в 22:58):
а какими программами работали для это программы?
ManHunter (19.07.2015 в 17:52):
Тогда надо упомянуть и Color quantizer, тоже с палитрами и оптимизацией всякие чудеса творит. Понимает JPEG, PNG, GIF, BMP, ICO и тоже бесплатная.
http://x128.ho.ua/color-quantizer.html

Но цель статьи была немного в другом :)
unreal666 (19.07.2015 в 17:48):
>Anonymous

технически PNGOUTWin и так юзают внешнюю утилиту, только внутренне. Она юзает движок от OptiPNG.
Anonymous (19.07.2015 в 15:52):
Интересно было бы сравнить её со свободной RIOT - http://luci.criosweb.ro/riot/

которая не только сжимает/оптимизирует палитру, но и позволяет дополнительно пропустить результат через один из 3 внешних утилит для оптимизации (их нужно качать отдельно и подсунуть программе).

вдобавок, умеет еще jpeg и gif

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

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

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