Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Исследование защиты утилиты Puffer v4.01

Обсудить статью на форуме

Массу крэкерских инструментов, видеоуроков и статей вы сможете найти на видеокурсе от нашего сайта. Подробнее здесь.

Автор: Demode <R091003@km.ru>

Puffer v4.01



Введение - Цель данной статьи изучение комбинированной защиты.

Цель - Puffer_v4.01

Программу можно найти: http://www.briggsoft.com/puffer.htm

Инструментарий:

HIEW - no comment

Wdsm10K - no comment

IDA Pro - no comment (у меня - 4.3.0.740А)

WinDBG - Windows Debugger

Прочие инструменты . . .

Оригинальная программа сообщает нам о "Trial"-версии (25 запусков) и о "Unregisterd Software".

Итак : PEiD показывает, что мы имеем дело с программой, упакованной UPX.

Предвкушая быструю и легкую викторию, распаковываем exe-ник. Метод распаковки: в ручную или автоматический роли не

играет - результат будет один и тот же :

Распакованная программа НЕ работает!

Первое сообщение об ошибке: "Приложение или библиотека C:\TEMP\PFxxxxxxxx.dll не является образом программы для

Windows NT и прочее" заставляет задуматься. . . Повторная попытка старта программы и в сообщении об ошибке

изменилось название dll-файла! Предстоит серъезная работа. . .

Первый вывод банален: прежде чем углубляться в собственно защиту и бороться с триальностью, нам придется "заставить"

функционировать распакованный вариант.


Глава Первая.

Самое время внимательно изучить содержание директории с исследуемой программой.
SWDLL1.dat - имя файла вызывает большие подозрения и поэтому привлекает к себе внимания.
Заглянем:
Содержимое никоим образом не похоже на "нормальную" dll что вкупе с упакованностью самой программы намекает, что

программа сама неким образом обрабатывает SWDLL1.dat и формирует те самые PFxxxxxxxx.dll.

Пришла пора детально ознакомиться с кодом распакованной программы.
Заметьте, что в импорте нет следов PFxxxxxxxx.dll, т.е вызов функций из PFxxxxxxxx.dll - косвенный (если он

происходит).
Но без нее не обойтись. Это как - к слову. . .

+++++++++++++++++++ IMPORTED FUNCTIONS ++++++++++++++++++
Number of Imported Modules = 20 (decimal)

Import Module 001: kernel32.dll
Import Module 002: user32.dll
Import Module 003: advapi32.dll
Import Module 004: oleaut32.dll
Import Module 005: kernel32.dll
Import Module 006: advapi32.dll
Import Module 007: kernel32.dll
Import Module 008: version.dll
Import Module 009: gdi32.dll
Import Module 010: user32.dll
Import Module 011: ole32.dll
Import Module 012: oleaut32.dll
Import Module 013: comctl32.dll
Import Module 014: winspool.drv
Import Module 015: shell32.dll
Import Module 016: shell32.dll
Import Module 017: comdlg32.dll
Import Module 018: winmm.dll
Import Module 019: gdi32.dll
Import Module 020: kernel32.dll

Рекомндую для более полного анализа пользовать и Wdsm10K и IDA Pro, они работают чуть-чуть по-разному.

Будем искать LoadLibraryA, исходя из анализа первой ошибки. Находим:

:005046BB 50 push eax

* Reference To: kernel32.LoadLibraryA, Ord:01E4h
|
:005046BC E85327F0FF Call 00406E14
:005046C1 A3480B5200 mov dword ptr [00520B48], eax
:005046C6 833D480B520000 cmp dword ptr [00520B48], 00000000
:005046CD 7440 je 0050470F
:005046CF 686C475000 push 0050476C
:005046D4 A1480B5200 mov eax, dword ptr [00520B48]
:005046D9 50 push eax

* Reference To: kernel32.GetProcAddress, Ord:0158h
|
:005046DA E89526F0FF Call 00406D74
:005046DF A3540B5200 mov dword ptr [00520B54], eax
:005046E4 6874475000 push 00504774

И несколько выше обнаружится и собственно обработка SWDLL1.dat и формирование "рабочей" dll

:005045DC E8EBFEFFFF call 005044CC
:005045E1 8D55EC lea edx, dword ptr [ebp-14]
:005045E4 A144AE5100 mov eax, dword ptr [0051AE44]
:005045E9 8B00 mov eax, dword ptr [eax]
:005045EB E818ECF4FF call 00453208
:005045F0 8B45EC mov eax, dword ptr [ebp-14]
:005045F3 8D55F0 lea edx, dword ptr [ebp-10]
:005045F6 E8F94CF0FF call 004092F4
:005045FB 8B55F0 mov edx, dword ptr [ebp-10]
:005045FE 8D45F8 lea eax, dword ptr [ebp-08]
:00504601 B944475000 mov ecx, 00504744 ; SWDLL1.dat
:00504606 E881FAEFFF call 0040408C
:0050460B 8D45F4 lea eax, dword ptr [ebp-0C]
:0050460E BA04010000 mov edx, 00000104
:00504613 E85CFDEFFF call 00404374
:00504618 8D45F4 lea eax, dword ptr [ebp-0C]
:0050461B E8F0FBEFFF call 00404210
:00504620 50 push eax ; формирование имени dll
:00504621 6804010000 push 00000104

* Reference To: kernel32.GetTempPathA, Ord:0183h
|
:00504626 E86927F0FF Call 00406D94 ; xxxxxxxx
:0050462B 8BD0 mov edx, eax
:0050462D 8D45F4 lea eax, dword ptr [ebp-0C]
:00504630 E83FFDEFFF call 00404374
:00504635 FF75F4 push [ebp-0C]
:00504638 6858475000 push 00504758 ; PF

* Reference To: kernel32.GetTickCount, Ord:018Bh
|
:0050463D E86227F0FF Call 00406DA4
:00504642 33D2 xor edx, edx
:00504644 52 push edx
:00504645 50 push eax
:00504646 8D55E8 lea edx, dword ptr [ebp-18]
:00504649 B808000000 mov eax, 00000008
:0050464E E80D48F0FF call 00408E60
:00504653 FF75E8 push [ebp-18]
:00504656 6864475000 push 00504764 ; .dll
:0050465B B8500B5200 mov eax, 00520B50
:00504660 BA04000000 mov edx, 00000004

Итак, нам предстоит каким-то образом получить работоспособный экземпляр dll и "заставить" программу использовать ее.

Не забыли текст сообщения об ошибке? Запустим оригинальную программу и заглянем в системную TEMP-овскую папку (об

этом говорит kernel32.GetTempPathA) и просто скопируем PFxxxxxxxx.dll в папку с программой.

Хочу заметить, что оригинальная программа при выходе сама удаляет из системной TEMP-овской папки созданную dll-ку, а

это значит, что если мы не хотим восстанавливать dll, что мы "подсунем" программе, после каждого запуска программы,

нам придется заняться и этой проблемой.

Поиск DeleteFileA (одна из импортируемых функций kernel32.dll) приводит наc к:

* Reference To: kernel32.FreeLibrary, Ord:00C8h
|
:0050478A E84D25F0FF Call 00406CDC ; FreeLibrary
:0050478F A1500B5200 mov eax, dword ptr [00520B50]
:00504794 E80B4AF0FF call 004091A4 ; удаление файла
:00504799 C3 ret

здесь режем "по-живому" :0050478F C3 ret


Теперь предстоит инъекция "лекарства".

:005046B6 E90BFA0000 *** jmp 005140C6

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005140F2(U)
|
:005046BB 50 push eax

* Reference To: kernel32.LoadLibraryA, Ord:01E4h
|
:005046BC E85327F0FF Call 00406E14


Найдем свободное место по адресу 005140С6 (см. pps) и напишем следующий код:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005046B6(U)
|
:005140C6 E83901EFFF call 00404204 ; не забудем выполнить
:005140CB 50 push eax
:005140CC E8D350EFFF call 004091A4 ; удалим созданную dll
:005140D1 58 pop eax
:005140D2 BB50756666 mov ebx, 66667550
:005140D7 895803 mov dword ptr [eax+03], ebx ; Puff
:005140DA BB65725C00 mov ebx, 005C7265
:005140DF 895807 mov dword ptr [eax+07], ebx ; er\
:005140E2 BB5046302E mov ebx, 2E304650
:005140E7 89580A mov dword ptr [eax+0A], ebx ; PF0.
:005140EA BB646C6C00 mov ebx, 006C6C64
:005140EF 89580E mov dword ptr [eax+0E], ebx ; dll
:005140F2 E9C405FFFF jmp 005046BB


Т.е мы удалили созданную программой dll и "подложили" по адресу [EAX] путь и имя работоспособной dll. Разумеется, не

забудем переименовать скопированную dll в PF0.dll и САМОЕ ГЛАВНОЕ - создадим директорию C:\Puffer и скопируем туда

программу со всеми файлами.

Первая часть задачи решена: распакованная программа ПОЛНОСТЬЮ работает!


Глава Вторая.


Перед нами три-единая задача:
1. Преодолеть trial`ный лимит запусков
2. Облагородить [Trial xx of 25]
3. Благообразить информацию в меню "About"

Будем решать проблемы по мере поступления.

Поиск в Hiew текста "Trial" покажет несколько интересных messages и одно будет нас очень интересовать:
"[Trial period experied]", который приведет нас к Proc_504970, где происходит анализ количества триальных запусков:

с сокращениями:

:00504992 E825FCFFFF call 005045BC
:00504997 84C0 test al, al
:00504999 7412 je 005049AD ; если запас исчерпан
:0050499B 68244C5000 push 00504C24
:005049A0 FF15540B5200 call dword ptr [00520B54]
:005049A6 A34C0B5200 mov dword ptr [00520B4C], eax
:005049AB EB0A jmp 005049B7

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00504999(C)
|
:005049AD C7054C0B5200FFFFFFFF mov dword ptr [00520B4C], FFFFFFFF

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005049AB(U)
|
:005049B7 833D4C0B520000 cmp dword ptr [00520B4C], 00000000
:005049BE 7D1A jge 005049DA
:005049C0 6A00 push 00000000
:005049C2 668B0D2C4C5000 mov cx, word ptr [00504C2C]
:005049C9 B201 mov dl, 01
:005049CB B8384C5000 mov eax, 00504C38 ; Error occurred in ..
:005049D0 E86B51F5FF call 00459B40
:005049D5 E9E4000000 jmp 00504ABE

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005049BE(C)
|
:005049DA 833D4C0B520000 cmp dword ptr [00520B4C], 00000000
:005049E1 751C jne 005049FF
:005049E3 8D45F0 lea eax, dword ptr [ebp-10]
:005049E6 BA684C5000 mov edx, 00504C68 ; [Trial period experied]
:005049EB E868F4EFFF call 00403E58
:005049F0 8D45EC lea eax, dword ptr [ebp-14]
:005049F3 BA8C4C5000 mov edx, 00504C8C
:005049F8 E85BF4EFFF call 00403E58
:005049FD EB5A jmp 00504A59

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005049E1(C)
|
:005049FF 68E04C5000 push 00504CE0 ; если мы здесь, то все Ок!
:00504A04 8D55E8 lea edx, dword ptr [ebp-18]

Здесь все ясно: :005049A6 A34C0B5200 mov dword ptr [00520B4C], eax
что означает : кол-во оставшихся запусков пересылается из EAX в [00520B4C] для анализа.

Кстати, сие есть еще один наглядный пример как не надо строить защиты!
Все прозрачно, четко и логично!

Придется сделать еще одну "инъекцию":

прыгаем :005049A6 E94CF70000 jmp 005140F7

и далее:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005049A6(U)
|
:005140F7 B218 mov dl, 18
:005140F9 88154C0B5200 mov byte ptr [00520B4C], dl ; текущий запуск -> 1A - 18 = 2
:005140FF E9A708FFFF jmp 005049AB

Т.е программа считает, что текущий это "второй" запуск, но в реестре хранится правильный порядковый номер запуска и

он модифицируертся при каждом использовании программы. Это следствие банального недостатка свободного места для

"идеальной" инъекции:
:005140F7 mov eax, 18
mov [00520bc4],eax
jmp 005049ab

Что бы Убрать [Trial x of 25] из шапки окна программы, в Hiew по адресу 00504CE1 пишем "00", это означает что

фактически выводится только один символ "20h" - пробел.

Меню "About" - на собственный вкус.


Выводы.

Если читатель не знаком с этой утилитой, отсылаю к обзорам, ей посвященным. Это к тому, что основатель

компании Briggs Softworks господин Кент Бриггз занимается криптографией - т.е защитой информации и не дилетантском

уровне. Его имя достаточно известно в сфере криптографии. . .

Примененая защита, построенная на двойной распаковке: и самой программы и рабочей dll, неординарна и весьма

интересна. Постоянное изменение имени распакованной dll заслуживает аплодисментов!
И еще одно: место хранения пути к dll (содержимое EAX см.:005046B6) при ее создании регулярно меняется.

Но реализация собственно trial`а - дилетантское в расчете на трудности преодоления двойной распаковки и проблем с

рабочей dll.

ps. В этом примере нам пришлось "жестко" определить директорию программы ( C:\Puffer ) и имя dll.
Причина уже была указана: недостаток места для творчества.

pps. Еще одна "мина" в программе: если любопытствующий суъект попытается добавить какой-либо код и будет искать

какое-то количество "20h",то, конечно, найдет.
НО не все они "пустышки"! и messag`и об ошибках гарантированы.
Мы же имеем дело с криптографической программой и структура рабочих полей - лес темный и непролазный.

ppps. Какое-то время тому назад автору уже приходилось сталкиваться с этой утилитой и о ветви реестра:

[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings] параметр "PF"

было известо. . .

Успехов в Ваших делах!

Demode
R091003@km.ru


Обсуждение статьи: Исследование защиты утилиты Puffer v4.01 >>>


Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS