Blog. Just Blog

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

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

PDF Password Remover от компании VeryPDF Inc - очень нужная и полезная в компьютерном хозяйстве программа. Она позволяет снимать с PDF-файлов защиту паролем и различные ограничения, например, запрет копирования текста или печати, которые особо одаренные аффтары устанавливают для защиты своих "аффтарских прав". И все бы хорошо, но PDF Password Remover за свои услуги требует денег, а в пробном режиме запускается всего 50 раз.

Скачиваем с сайта дистрибутив (последняя версия на момент публикации 3.1), запускаем, устанавливаем. Предварительный осмотр пациента указывает, что исполняемый файл упакован обычным UPX, но после упаковки в нем были затерты названия секций и служебные данные упаковщика, так что простым "upx -d" тут дело не обойдется. Можно распаковать вручную, или же воспользоваться каким-нибудь универсальным или специализированным распаковщиком, выбор оружия оставляю за вами. Готовый распакованный файл загоняем в дизассемблер, параллельно запустим его, чтобы посмотреть на внешние проявления защиты.

Окно ввода регистрационных данных
Окно ввода регистрационных данных

Вах, "Machine ID"! Как все серьезно! :) По идее, такой способ регистрации используется, чтобы привязывать каждую копию программы к определенной уникальной машине. Расстраиваться не будем, посмотрим что нам скажет программа на ввод какого-нибудь левака. "Your registration key is wrong, please double check it and try again." Ну да, вполне ожидаемо. Теперь поищем нехорошую строку в распакованном файле.

"Нехорошая" строка найдена
"Нехорошая" строка найдена

И посмотрим код, который на нее ссылается. Тут все просто и понятно, никаких сюрпризов нет.
  1. seg000:00405375                 mov     edi, 4B94F0h
  2. seg000:0040537A                 push    4B94F0h
  3. seg000:0040537F                 push    3FBh
  4. seg000:00405384                 push    esi
  5. seg000:00405385                 rep stosd
  6. seg000:00405387                 call    ds:dword_4883FC
  7. seg000:0040538D                 push    4B94F0h
  8. ; Вызвать процедуру проверки введенных регистрационных данных
  9. seg000:00405392                 call    sub_404BF0   ; <---- Проверка
  10. seg000:00405397                 add     esp, 4
  11. ; Если она вернула EAX=0, то введенный код неправильный
  12. seg000:0040539A                 test    eax, eax
  13. seg000:0040539C                 jz      short loc_4053E2
  14. seg000:0040539E                 push    40h
  15. ; Сообщение об успешной регистрации "Thank you."
  16. seg000:004053A0                 push    offset aThankYou_
  17. ; "Thanks for purchasing the PDF Password "...
  18. seg000:004053A5                 push    offset aThanksForPurch
  19. seg000:004053AA                 push    esi
  20. seg000:004053AB                 call    ds:dword_488404
  21. seg000:004053B1                 push    ecx
  22. seg000:004053B2                 mov     ecx, esp
  23. seg000:004053B4                 mov     [esp+0E8h+var_D8], esp
  24. seg000:004053B8                 push    (offset byte_4B9418+0D8h) ; Src
  25. seg000:004053BD                 call    sub_47BC59
  26. seg000:004053C2                 call    sub_404FC0
  27. seg000:004053C7                 add     esp, 4
  28. seg000:004053CA                 mov     dword ptr ds:byte_4B9418+1A0h, 1
  29. seg000:004053D4                 push    1
  30. seg000:004053D6                 push    esi
  31. seg000:004053D7                 call    ds:dword_488400
  32. seg000:004053DD                 jmp     loc_405665
  33. seg000:004053E2 ; -------------------------------------------------------
  34. seg000:004053E2 loc_4053E2:
  35. seg000:004053E2                 push    10h
  36. seg000:004053E4                 push    0
  37. ; "Your registration key is wrong, please "...
  38. seg000:004053E6                 push    offset aYourRegistrati
  39. seg000:004053EB                 push    esi
  40. seg000:004053EC                 call    ds:dword_488404
  41. seg000:004053F2                 push    3FBh
  42. seg000:004053F7                 push    esi
Теперь есть два пути. Первый - просто пропатчить процедуру проверки ключа, чтобы она всегда возвращала EAX=1, или же попробовать разобрать алгоритм проверки. Плюсы есть в каждом способе. Пропатченная версия становится портабельной и замечательно работает с любых съемных носителей. Зарегистрированная версия хорошо ставится на стационарную машину и не требует никаких вмешательств в исполняемый код. Посмотрим саму процедуру проверки одновременно под отладчиком и в дизассемблере. Сразу бросается в глаза, что ей передается только введенный код, а грозный "Machine ID" вообще нигде не используется. Получается, что привязка к железу - простая пустышка для создания видимости навороченной защиты.
  1. ; Если будете патчить, то это делается здесь
  2. seg000:00404BF0                 sub     esp, 18h ; <-- MOV AL,1; RET
  3. seg000:00404BF3                 or      ecx, 0FFFFFFFFh
  4. seg000:00404BF6                 xor     eax, eax
  5. seg000:00404BF8                 push    ebx
  6. seg000:00404BF9                 push    esi
  7. seg000:00404BFA                 mov     esi, [esp+20h+arg_0]
  8. seg000:00404BFE                 push    edi
  9. seg000:00404BFF                 mov     edi, esi
  10. seg000:00404C01                 repne scasb
  11. ; Собственная функция для подсчета длины строки
  12. seg000:00404C03                 not     ecx
  13. seg000:00404C05                 dec     ecx
  14. ; Длина введенного серийника должны быть 14h (десятичное 20) символов
  15. seg000:00404C06                 cmp     ecx, 14h
  16. seg000:00404C09                 jz      short loc_404C12
  17. ; Иначе EAX=0 и на выход
  18. seg000:00404C0B                 pop     edi
  19. seg000:00404C0C                 pop     esi
  20. seg000:00404C0D                 pop     ebx
  21. seg000:00404C0E                 add     esp, 18h
  22. seg000:00404C11                 retn
Теперь мы знаем длину правильного серийного номера - ровно 20 символов.
  1. seg000:00404C12 loc_404C12:
  2. ; Взять первый и второй символ
  3. seg000:00404C12                 mov     al, [esi]
  4. seg000:00404C14                 mov     cl, [esi+1]
  5. seg000:00404C17                 lea     edx, [esp+24h+Str]
  6. seg000:00404C1B                 xor     bl, bl
  7. seg000:00404C1D                 push    edx             ; Str
  8. seg000:00404C1E                 mov     [esp+28h+var_C], al
  9. seg000:00404C22                 mov     [esp+28h+var_B], bl
  10. seg000:00404C26                 mov     [esp+28h+Str], cl
  11. seg000:00404C2A                 mov     [esp+28h+var_17], bl
  12. ; Перевести второй символ в цифру
  13. seg000:00404C2E                 call    _atoi
  14. ; Записать его в EDI
  15. seg000:00404C33                 mov     edi, eax
  16. seg000:00404C35                 lea     eax, [esp+28h+var_C]
  17. seg000:00404C39                 push    eax             ; Str
  18. ; Перевести первый символ в цифру
  19. seg000:00404C3A                 call    _atoi
  20. ; Прибавить ко второму
  21. seg000:00404C3F                 add     edi, eax
  22. seg000:00404C41                 add     esp, 8
  23. ; Результат = 10?
  24. seg000:00404C44                 cmp     edi, 0Ah
  25. ; Если да, то продолжаем
  26. seg000:00404C47                 jz      short loc_404C52
  27. ; Иначе EAX=0 и на выход
  28. seg000:00404C49                 pop     edi
  29. seg000:00404C4A                 pop     esi
  30. seg000:00404C4B                 xor     eax, eax
  31. seg000:00404C4D                 pop     ebx
  32. seg000:00404C4E                 add     esp, 18h
  33. seg000:00404C51                 retn
Первая проверка: берутся первый и второй символ серийника, затем преобразуются в цифры и складываются. В сумме должно получиться 10.
  1. seg000:00404C52 loc_404C52:
  2. ; Взять последний и предпоследний символы
  3. seg000:00404C52                 mov     cl, [esi+12h]
  4. seg000:00404C55                 mov     dl, [esi+13h]
  5. seg000:00404C58                 lea     eax, [esp+24h+Str]
  6. seg000:00404C5C                 mov     [esp+24h+var_C], cl
  7. seg000:00404C60                 push    eax             ; Str
  8. seg000:00404C61                 mov     [esp+28h+var_B], bl
  9. seg000:00404C65                 mov     [esp+28h+Str], dl
  10. seg000:00404C69                 mov     [esp+28h+var_17], bl
  11. ; Преобразовать последний символ в цифру
  12. seg000:00404C6D                 call    _atoi
  13. seg000:00404C72                 lea     ecx, [esp+28h+var_C]
  14. seg000:00404C76                 mov     edi, eax
  15. ; Преобразовать предпоследний символ в цифру
  16. seg000:00404C78                 push    ecx             ; Str
  17. seg000:00404C79                 call    _atoi
  18. seg000:00404C7E                 add     edi, eax
  19. seg000:00404C80                 add     esp, 8
  20. ; Сумма цифр = 12?
  21. seg000:00404C83                 cmp     edi, 0Ch
  22. ; Если да, то продолжаем
  23. seg000:00404C86                 jz      short loc_404C91
  24. ; Иначе EAX=0 и на выход
  25. seg000:00404C88                 pop     edi
  26. seg000:00404C89                 pop     esi
  27. seg000:00404C8A                 xor     eax, eax
  28. seg000:00404C8C                 pop     ebx
  29. seg000:00404C8D                 add     esp, 18h
  30. seg000:00404C90                 retn
Вторая проверка: последний и предпоследний символ переводятся в числовое значение, их сумма должна быть равна 12.
  1. seg000:00404C91 loc_404C91:
  2. ; Взять 6-й и 14-й символ (здесь нумерация символов идет с 1)
  3. seg000:00404C91                 mov     dl, [esi+5]
  4. seg000:00404C94                 mov     al, [esi+0Dh]
  5. seg000:00404C97                 lea     ecx, [esp+24h+Str]
  6. seg000:00404C9B                 mov     [esp+24h+var_C], dl
  7. seg000:00404C9F                 push    ecx             ; Str
  8. seg000:00404CA0                 mov     [esp+28h+var_B], bl
  9. seg000:00404CA4                 mov     [esp+28h+Str], al
  10. seg000:00404CA8                 mov     [esp+28h+var_17], bl
  11. seg000:00404CAC                 call    _atoi
  12. seg000:00404CB1                 lea     edx, [esp+28h+var_C]
  13. seg000:00404CB5                 mov     edi, eax
  14. seg000:00404CB7                 push    edx             ; Str
  15. seg000:00404CB8                 call    _atoi
  16. seg000:00404CBD                 add     edi, eax
  17. seg000:00404CBF                 add     esp, 8
  18. ; Их сумма должна быть равна 11
  19. seg000:00404CC2                 cmp     edi, 0Bh
  20. ; Если да, то продолжаем
  21. seg000:00404CC5                 jz      short loc_404CD0
  22. seg000:00404CC7                 pop     edi
  23. seg000:00404CC8                 pop     esi
  24. seg000:00404CC9                 xor     eax, eax
  25. seg000:00404CCB                 pop     ebx
  26. seg000:00404CCC                 add     esp, 18h
  27. seg000:00404CCF                 retn
Третья проверка: 6-й и 14-й символ в сумме должны давать 11.
  1. seg000:00404CD0 loc_404CD0:
  2. ; 13-й символ должен быть = 'K'
  3. seg000:00404CD0                 cmp     byte ptr [esi+0Ch], 4Bh
  4. seg000:00404CD4                 jz      short loc_404CDF
  5. seg000:00404CD6                 pop     edi
  6. seg000:00404CD7                 pop     esi
  7. seg000:00404CD8                 xor     eax, eax
  8. seg000:00404CDA                 pop     ebx
  9. seg000:00404CDB                 add     esp, 18h
  10. seg000:00404CDE                 retn
  11. seg000:00404C12 ; ------------------------------------------------------
  12. seg000:00404CDF loc_404CDF:
  13. ; 15-й символ должен быть = '3'
  14. seg000:00404CDF                 cmp     byte ptr [esi+0Eh], 33h
  15. seg000:00404CE3                 jz      short loc_404CEE
  16. seg000:00404CE5                 pop     edi
  17. seg000:00404CE6                 pop     esi
  18. seg000:00404CE7                 xor     eax, eax
  19. seg000:00404CE9                 pop     ebx
  20. seg000:00404CEA                 add     esp, 18h
  21. seg000:00404CED                 retn
  22. seg000:00404C12 ; ------------------------------------------------------
  23. seg000:00404CEE loc_404CEE:
  24. ; 16-й символ должен быть = '1'
  25. seg000:00404CEE                 mov     cl, [esi+0Fh]
  26. seg000:00404CF1                 xor     eax, eax
  27. seg000:00404CF3                 cmp     cl, 31h
  28. seg000:00404CF6                 pop     edi
  29. seg000:00404CF7                 pop     esi
  30. seg000:00404CF8                 pop     ebx
  31. seg000:00404CF9                 setz    al
  32. seg000:00404CFC                 add     esp, 18h
  33. seg000:00404CFF                 retn
Теперь у нас есть алгоритм генерации правильного серийного номера. Первый и второй символы в сумме должны давать 10, последний и предпоследний - 12, 6-й и 14-й символ в сумме 11, 13-й символ должен быть 'K', 15-й и 16-й символы, соответственно, '3' и '1'. Остальные символы серийного номера вообще нигде не учитываются и могут заполняться как вам нравится. Готовый серийник может быть, например, таким: 55PCL5RULEZ!K631MH66.

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

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

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

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

Комментарии

Отзывы посетителей сайта о статье
Ingvar (16.12.2011 в 10:42):
Спасибо! Познавательно.
Санек (31.01.2011 в 19:34):
Отлично 5+!!!
ManHunter (25.11.2009 в 12:21):
Взаимно рад видеть :)
Я эту прогу релизю не кейгенами, а "cracked exe", так надежнее. А тут разобрал больше для спортивного интереса.
Isaev (24.11.2009 в 23:42):
Знакомые все лица!
Приветствую, ManHunter!
Прикольно, как раз недавно ковырял эту прогу...
они даже защиту меняют иногда!
отличия в v3.0
13='R'
16='0'
Станислав Шмелев (24.11.2009 в 19:09):
Да, Дмитрий, Вы не перестаёте удивлять! Спасибо за науку!
SereGi4 (23.11.2009 в 07:43):
Отличная статья, буду рад еще почитать чтото подобное !!! )))
Вова (21.11.2009 в 21:52):
Спасибо огромное !
Также почитал статью про popcap игры - офигеть , как всё легко !
Сделайте пожалуйста подобные статьи и на игры других производителей - майл ру, алавар , рефлексив !!!
Поклонник таланта (21.11.2009 в 10:04):
ManHunter, спасибо
ManHunter (20.11.2009 в 11:18):
Я не занимаюсь хаспами. Это делают другие люди, и в основном за деньги.
Рекомендую http://rus.dongla.net
Поклонник таланта (20.11.2009 в 11:17):
если есть время, просветите нас по способам отвязки от защиты типа HASP, используемой в программах 1с бухгвлтерия, Стройконсультант и т.д.

в любом случае спасибо за просветительскую работу!
INC (20.11.2009 в 10:06):
Спасибо за статью
Cтанислав (20.11.2009 в 08:56):
ManHunter, Скромничаете :)
ManHunter (20.11.2009 в 08:36):
Конечно есть, дофига и больше. Эта защита для уровня начинающих.
Cтанислав (20.11.2009 в 00:22):
Очень познавательно. Интересно есть что то такое, что вы не можете обойти? )))

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

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

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