Исследование защиты скринсейвера Forest Lake
Скриншот скринсейвера Forest Lake
С полноценным отдыхом пока напряженка, так что остается наслаждаться виртуальными путешествиями. Скринсейвер Forest Lake переносит нас на берег лесного озера, где под приятную музыку плещется вода, летают птички и бабочки, плавают рыбки. Идиллию нарушает только необходимость выкладывать за это все деньги.
Забираем с офсайта дистрибутив, устанавливаем, смотрим. Исполняемый файл скринсейвера, который находится в системной папке, накрыт протектором ASProtect. Можно воспользоваться одним из автоматических распаковщиков, но лучше попрактикуемся в ручной распаковке, а то давно что-то этого не делали.
Для распаковки понадобится отладчик OllyDbg 1.10 с установленными плагинами ODbgScript, OllyDump и скрипт-распаковщик Aspr2.XX_unpacker от VolX. Загружаем защищенный файл в отладчик, через меню Plugins - ODbgScript - Run Script... выбираем скрипт-распаковщик. Когда он закончит работу, дампим память процесса. Меню Plugins - OllyDump - Dump debugged process. Галочку "Rebuild import" надо обязательно снять.
Делаем дамп файла
Возвращаемся к логу работы скрипта Plugins - ODbgScript - Log Window..., там будут значения, необходимые для восстановления импорта файла.
Лог работы скрипта
Запускаем вашу любимую программу для восстановления импорта, заполняем параметры для поиска импорта значениями из лога отладчика.
Загружаем импорт
Когда все функции будут успешно распознаны, надо прикрутить новую секцию импорта к сделанному ранее дампу.
Восстанавливаем дамп
Убеждаемся в работоспособности распакованного файла, после этого отправляем его на разбор в дизассемблер. Чтобы не возиться с параметрами командной строки, SCR-файл можно переименовать в EXE. При открытии настроек, а также до и после запуска скринсейвера открываются разные триальные окна. А окно настроек выглядит следующим образом.
Сообщение незарегистрированной версии
Первое, что бросается в глаза, это надпись "UNREGISTERED TRIAL VERSION". Поиском по листингу обнаруживаем вот такой код. Это не совсем то, но тут тоже используется строка о незарегистрированности.
Code (Assembler) : Убрать нумерацию
- seg000:0041A869 push eax
- seg000:0041A86A mov ecx, offset dword_4BEC60
- ; Вызвать функцию проверки
- seg000:0041A86F call sub_4031A0
- seg000:0041A874 test eax, eax
- ; Значение EAX не 0, никаких надписей не выводить
- seg000:0041A876 jnz short loc_41A88D
- seg000:0041A878 push 30h ; uType
- seg000:0041A87A push offset aWelcome ; "Welcome"
- seg000:0041A87F push offset aUnregisteredVe
- ; "UNREGISTERED VERSION. PLEASE REGISTER!"
- seg000:0041A884 push esi ; hWnd
- seg000:0041A885 call ds:MessageBoxA
- seg000:0041A88B jmp short loc_41A8EF
- seg000:0041A88D ; --------------------------------
- seg000:0041A88D loc_41A88D:
- seg000:0041A88D mov [esp+4Ch+var_14], 0Fh
- seg000:0041A895 mov [esp+4Ch+var_18], ebx
- seg000:0041A899 mov byte ptr [esp+4Ch+lpString], bl
- seg000:0041A89D push 0Fh ; Dst
- seg000:0041A89F push offset aRegisteredTo
- ; "Registered to: "
- seg000:0041A8A4 lea ecx, [esp+54h+var_2C]
- seg000:0041A8A8 mov [esp+54h+var_4], ebx
- seg000:0041A8AC call sub_4039E0
- seg000:0041A8B1 push 0FFFFFFFFh ; MaxCount
- seg000:0041A8B3 push ebx ; int
- seg000:0041A8B4 push offset dword_4A9E80 ; int
- seg000:0041A8B9 lea ecx, [esp+58h+var_2C]
- seg000:0041A8BD call sub_403800
Code (Assembler) : Убрать нумерацию
- seg000:004031A0 sub_4031A0 proc near
- seg000:004031A0 sub esp, 24h
- seg000:004031A3 mov eax, ds:dword_4ADAE8
- seg000:004031A8 xor eax, esp
- seg000:004031AA mov [esp+24h+var_4], eax
- seg000:004031AE mov edx, [esp+24h+arg_0]
- seg000:004031B2 push ebx
- seg000:004031B3 push ebp
- seg000:004031B4 push esi
- seg000:004031B5 push edi
- seg000:004031B6 lea eax, [esp+34h+var_24]
- seg000:004031BA push eax
- seg000:004031BB push edx
- seg000:004031BC call sub_403020
- seg000:004031C1 xor ebx, ebx
- seg000:004031C3 cmp ds:dword_49A004, ebx
- seg000:004031C9 jle loc_40326D
- seg000:004031CF mov edi, offset nullsub_2
- seg000:004031D4 loc_4031D4:
- seg000:004031D4 mov eax, 8
- seg000:004031D9 lea ecx, [esp+34h+var_24]
- seg000:004031DD mov edx, edi
- seg000:004031DF nop
- seg000:004031E0 loc_4031E0:
- seg000:004031E0 mov esi, [edx]
- seg000:004031E2 cmp esi, [ecx]
- seg000:004031E4 jnz short loc_4031F8
- seg000:004031E6 sub eax, 4
- seg000:004031E9 add ecx, 4
- seg000:004031EC add edx, 4
- seg000:004031EF cmp eax, 4
- seg000:004031F2 jnb short loc_4031E0
- seg000:004031F4 test eax, eax
- seg000:004031F6 jz short loc_403255
- seg000:004031F8 loc_4031F8:
- seg000:004031F8 movzx esi, byte ptr [edx]
- seg000:004031FB movzx ebp, byte ptr [ecx]
- seg000:004031FE sub esi, ebp
- seg000:00403200 jnz short loc_403247
- seg000:00403202 sub eax, 1
- seg000:00403205 add ecx, 1
- seg000:00403208 add edx, 1
- seg000:0040320B test eax, eax
- seg000:0040320D jz short loc_403255
- seg000:0040320F movzx esi, byte ptr [edx]
- seg000:00403212 movzx ebp, byte ptr [ecx]
- seg000:00403215 sub esi, ebp
- seg000:00403217 jnz short loc_403247
- seg000:00403219 sub eax, 1
- seg000:0040321C add ecx, 1
- seg000:0040321F add edx, 1
- seg000:00403222 test eax, eax
- seg000:00403224 jz short loc_403255
- seg000:00403226 movzx esi, byte ptr [edx]
- seg000:00403229 movzx ebp, byte ptr [ecx]
- seg000:0040322C sub esi, ebp
- seg000:0040322E jnz short loc_403247
- seg000:00403230 sub eax, 1
- seg000:00403233 add ecx, 1
- seg000:00403236 add edx, 1
- seg000:00403239 test eax, eax
- seg000:0040323B jz short loc_403255
- seg000:0040323D movzx esi, byte ptr [edx]
- seg000:00403240 movzx eax, byte ptr [ecx]
- seg000:00403243 sub esi, eax
- seg000:00403245 jz short loc_403255
- seg000:00403247 loc_403247:
- seg000:00403247 test esi, esi
- seg000:00403249 mov eax, 1
- seg000:0040324E jg short loc_403257
- seg000:00403250 or eax, 0FFFFFFFFh
- seg000:00403253 jmp short loc_403257
- seg000:00403255 ; --------------------------------
- seg000:00403255 loc_403255:
- seg000:00403255 xor eax, eax
- seg000:00403257 loc_403257:
- seg000:00403257 test eax, eax
- seg000:00403259 jz short loc_403284
- seg000:0040325B add ebx, 1
- seg000:0040325E add edi, 20h
- seg000:00403261 cmp ebx, ds:dword_49A004
- seg000:00403267 jl loc_4031D4
- seg000:0040326D loc_40326D:
- seg000:0040326D pop edi
- seg000:0040326E pop esi
- seg000:0040326F pop ebp
- seg000:00403270 xor eax, eax
- seg000:00403272 pop ebx
- seg000:00403273 mov ecx, [esp+24h+var_4]
- seg000:00403277 xor ecx, esp
- seg000:00403279 call sub_44DD84
- seg000:0040327E add esp, 24h
- seg000:00403281 retn 4
- seg000:00403284 ; --------------------------------
- seg000:00403284 loc_403284:
- seg000:00403284 mov ecx, [esp+34h+var_4]
- seg000:00403288 pop edi
- seg000:00403289 pop esi
- seg000:0040328A pop ebp
- seg000:0040328B pop ebx
- seg000:0040328C xor ecx, esp
- seg000:0040328E mov eax, 1
- seg000:00403293 call sub_44DD84
- seg000:00403298 add esp, 24h
- seg000:0040329B retn 4
- seg000:0040329B sub_4031A0 endp
Скринсейвер успешно "зарегистрирован"
На первый взгляд все нормально. Но если запустить скринсейвер как скринсейвер, то через несколько минут по экрану начинает летать предложение зарегистрироваться вотпрямщаз.
Водяной знак незарегистрированной версии
Это значит, что в файле должна быть как минимум еще одна проверка корректности регистрационных данных. Логично предположить, что в ней будут использоваться те же команды и функции, что и в найденной ранее функции проверки регистрации. По паттернам "dword_49A004" и "nullsub_2" обнаружится вторая функция проверки регистрации. Она находится сразу же под первой функцией проверки, так что далеко ходить не пришлось. Патчим ее начало аналогичной парой команд MOV EAX,1 и RET 4, сохраняем изменения, запускаем скринсейвер. Никаких посторонних надписей больше не появляется, цель достигнута.
Просмотров: 1393 | Комментариев: 1
Метки: исследование защиты
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Добавить комментарий
Заполните форму для добавления комментария
Пришлось там поправить,чтоб работал.