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

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


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

Распаковка AsProtect 2.ХХ на примере AlfaClock

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

Хорошая подборка видеоуроков, инструментов крэкера, книг и статей - здесь.

Автор: SergSh <Sergey@intersat.ru>

Здравствуйте, дорогие читатели, сегодня мы будем распаковывать AlfaClock. Упакован он AsProtect 2.ХХ. Данная программа написана на Borland Delphi 6.0 - 7.0, и упакована с VM. :)

Инструменты:
OllyDebug
ImpRec

Начнём пожалуй.

1. Запускаем Ollydbg. Открываем AlfaClock.exe. Доходим до ОЕР аналогично предыдущим версиям Аспра. Делаем поиск всех подпрограмм: Search for-All intermodular call. Поднимаемся вверх и видим много CALL 00CD0000 и один CALL 00F10004. Скажу сразу, что CALL 00F10004 на самом деле является CALL 00CD0000, отработанным один раз. Поэтому наша задача состоит в том, чтобы прервать выполненее программы до первого его срабатывания. Поэтому записывае адрес этой подпрограммы на бумажку. Он у меня 0040130С.

2. Перезапускаем программу. В окне дампа вбиваем "D 0040130С" и жмём Shift+9 до тех пор пока по этому адресу не станет CALL 00CD0000. Теперь проходим ещё 5 исключений по Shift+9 запоминая или записывая адреса ивключений. Идём пока CALL 00CD0000 не станет CALL 00F10004. Запомнили адрес предыдущего исключения и перезапускаем программу. У меня этот адрес был 00В8В4АС. Останавливаемся на этом исключении. И переходим на известное нам ОЕР. Делаем поис всех подпрограмм и видим, что все подпрограммы имеют вид CALL 00CD0000.

3. Вообщем-то программа уже распакована, необходимо только восстановить таблицу импорта и снять дамп. Стоя на ОЕР запускаем скрипт от BiT-H@ckа:

var calladdr
var aftercalladdr
var filesecend
var startscan
var endscan
var VirtualAllocAddr
var realfunction
var iatcell
var iatstart
var iatstarttemp
var temp
var endmemoryspice
var OEP
var x
var y
var endiatstart
var endiatstart1
var d
var GetProcAddressddr
var prg
gpa "VirtualAlloc", "kernel32.dll" //Получили адрес VirtualAlloc, эта функция будет юзаться для получния реального адреса
add $RESULT,17
mov VirtualAllocAddr, $RESULT
mov endmemoryspice, 00DC0000 //Область интересующих нас келлов
mov iatstart, 004CB190 //Адрес таблицы импорта
mov startscan, 00401000 //Начальная граница сканирования (секция кода, возможно не полностью)
mov endscan, 004C6000 //Конечная граница сканирования (секция кода)
mov filesecend, 004E1000 //Конец секций файла в памяти
mov endiatstart, 004CB914 //Конец IAT
mov endiatstart1, 004CB914
mov prg,00f00000
mov OEP, eip
@continue: //Главный цикл скрипта (поиск call`а, проверка на принадлежность к аспровскому)
findop startscan, #E8# //Ищем оп-код call`а
mov startscan, $RESULT //Сохранили адрес найденного байта
inc $RESULT //Если это call aspr_code, по адреу call aspr_code+1 лежит dword - смещение отнасительно следующей инструкции
mov calladdr, [$RESULT] //Получаем кол-во байт для смещения от следующей команды
add $RESULT, 4 //Адрес, от которого отчитается смещение (первый байт инструкции после call aspr_code).
mov aftercalladdr, $RESULT //Сохранили адрес следующей инструкции
add aftercalladdr, calladdr //Получили адрес aspr_code (адрес, на который переходит call)
cmp startscan, endscan
jae @endscript //Проверяем границы кода для сканирования (не выходит ли адрес анализируемого call`а за границы)
cmp calladdr, endmemoryspice
jae @continue //Проверяем, чтобы скрипт не загрёб вооще другую инструкцию в которой содержится байт E8
cmp aftercalladdr, filesecend
jae @reconstruct //call ведёт за пределы файла в памяти? Да - это проделки аспра
jmp @continue //Продолжем поиски, мы ещё должны всю вселенную обойти:) by Factor 2
@reconstruct: //В это процедуре будет происходить самое главное - востановление
cmp aftercalladdr,prg
jae @continue //call aspr
mov eip, startscan //Установили eip на call aspr_code
bp VirtualAllocAddr //Для остановки внутри функции получения адреса реальной функции, после получения адреса, будем юзать VirtualAllocEx
run //Установили eip на call aspr_code, поставили бряк на VirtualAlloc, запустили программу
bc VirtualAllocAddr //Остановились, удалили брейкпоинт
mov temp, esp
add temp, 40 //В esp+5C лежит адрес реальной функции
cmp [temp],00B86D84 //По этому адресу у меня эмулировалась GetProcAddress
je GET
pp:
mov realfunction, [temp] //Взяли адрес реальной функции
bphws startscan, "x" //Установили брейкпоинт на call aspr_code
run
bphwc startscan //Вышли из call aspr_code и попали обратно на него-же, но он уже ведёт на другой адрес
cmp eip,004334d4 //адрес последнего восстанавливаемого келла
je @endscript
//Т.к. в OllyScript плохо реализован поиск, пришлось писать свой
mov iatstarttemp, iatstart //Взяли во временную переменную адрес таблицы импорта
sub iatstarttemp, 4 //Вычли из адреса 4, т.к. цикл начинается с добавления к адресу 4, следовательно один dword не будет захвачен поисковиком
@manual_find: //Цикл поиска
add iatstarttemp, 4 //Сместили указатель на DWORD
mov iatcell, [iatstarttemp] //Получили адрес
cmp iatstarttemp, endiatstart
je @NOV
cmp iatcell, realfunction //Проверили, не совподают ли значения реальной функции и полученной из IAT
jne @manual_find //Нет? Продолжаем искать
//Сейчас будем востанавливать call aspr_code, заменяя на call
[IAT_cell]:
mov [eip], #FF25# //FF15 - опкод call [XXXXXXXX]
add eip,2 //Сместили указатель на 2, тут надо будет писать адрес, по которому лежит адрес для перехода
mov [eip], iatstarttemp //Записали адрес ячейки таблицы импорта (call [Iat_cell])
cmp eip,004334d4
je @endscript
jmp @continue //Продолжаем поиск, востановление и т.д.
@endscript:
mov eip, OEP //Устанавливаем eip на адрес, которму равнялся eip до начала выполнения скрипта, обычно это ОЕР или очень близкий к ОЕР код
ret //Вышли из скрипта
@NOV:
mov iatstarttemp, endiatstart1 //Взяли во временную переменную адрес таблицы импорта
add iatstarttemp, 4 //Вычли из адреса 4, т.к. цикл начинается с добавления к адресу 4, следовательно один dword не будет захвачен //поисковиком
mov [iatstarttemp], 00000000
add iatstarttemp, 4
mov [iatstarttemp], realfunction
mov endiatstart1,iatstarttemp
mov endiatstart,endiatstart1
jmp [IAT_cell]
GET:
gpa "GetProcAddress", "kernel32.dll" //Получили адрес GetProcAddress, эта функция будет юзаться для получния реального адреса
mov GetProcAddressddr, $RESULT
mov [temp],GetProcAddressddr
jmp pp

Скрипт успешно отработал. Но снимать дамр не спешим. Сначало делаем поис команд в Ollydbg: "Search for-Сommand-CALL 00CD0000". Видим, что скрипт невосстановил две подпрограммы по адресам 00401264 и 00406Е6С. Восстановим их ручками, за одно и узнаете мой метод восстановления IAT. Для этого в соммандной строке окна дампа пишем "? VirtualAlloc". Видим "НЕХ 77Е7АС72". Переходим по адресу 77Е7АС72 и стим F2 на перый же находящийся ниже RET. Теперь переходим на адрес 00401264 жмём "Nev origin here", затем устанавливаем точку останова на секцию "code" в окне памяти прграммы: "Set memory breakpoint on acess-code". Заппускаем программу по "Shift+F9" 2 раза. Сработала точка останова на "RET" в "VirtualAlloc". Смотрим в окне стека по адресу ESP+40 запись "kernel32 GetFileTipe", это и есть искомая нами функция. Открываем в окне дампа нашу IAT и в конце восстановленных адресов функций, через 00000000 вбиваем найденный нами адрес функции "GetFileTipe". Затем жмём "Shift+F9" 3 раза и попадаем сного на 00401264, но CALL ужу изменился. Теперь И зменяем его на "JMP [адрес найденной функции в IAT]". Аналогично восстанавливаем второй адрес. Всё импорт восстановлен, переходим на ОЕР и делаем дамп.

4. Открываем ImportREC, выбираем нашу программу, вбиваем ОЕР=С5444. Размер IAT лучше взять полностью, т.е. RVA=000CB000, SIZE=00003000. Далее GetImports-ShovInvalid-TraceLevel1(Disasm)-PluginTracerc-ASProtect1,22 и наконец GutThunk(s). ImportREC не надолго задумается, минуты на 3, но всё сделает правильно. Далее FixDump и прикручиваем импорт к нашему дампу.

5. Осталось пара косяков, которые будем устранять трассируя наш дамп. Загружаем исправленный дамп в Ollydbg и трассируем его по F8. Дамп упадёт на CALL 004BD5E8, там по адресу 004BD608 команда MOV EAV,[004C7D6C]. Ниже CALL LoadLibraryA, не трудно догадаться, что по адресе 004C7D6C должно быть название dll. Закрываем дамп, запускаем оригинальную программу, доходим до ОЕР, устанавливаем F2 на 004BD608 и запускаем программу на выполнение. Программа выдала НАГ и затем остановилась на 004BD608, смотрим в 004C7D6C лежит 00Е00000, а в нём TrayClock.dll. Копируем TrayClock.dll в наш дамп на адрес 00584000. Вместо MOV EAV,[004C7D6C] пишем MOV EAV,00584000. Сохраняем изменения. Но дамп всё равно не работает. Скорее всего эта уже защита самой программы, а не Аспра. Здесь всё оказалось до смешного просто. Программа вызывает функцию GetFileSize и на оснавании полученного значения в EAX производит дальнейшую распаковку. GetFileSize находится по адресу 004DВFF0. Следовательно по адресу 004DВFF0 вбиваем MOV EAX,0EFC00 и нопим предыдущиеся два пуша. Значение 0EFC00 подсмотрели в оригинальной программе

6. Запускаем наш дамп всё работает. Спасибо ВСЕМ.

Обсуждение статьи: Распаковка AsProtect 2.ХХ на примере AlfaClock >>>


Комментарии к статье: Распаковка AsProtect 2.ХХ на примере AlfaClock

MoonShiner 02.10.2005 09:01:37
Не смотрел аспр второй версии. Но \"подпрограммы\" вместо функций и процедур режут слух (глаз?=) А по поводу \"дальнейшей распаковки\" сильно сомневаюсь, думаю, к распаковке, дальнейшие действия не имеют отношения. Может и не прав=)
---
BiT-H@ck 03.10.2005 15:39:46
Уворовали статью:) Точнее скрипт, а скрипт главное:)
---
John Freeman 04.10.2005 12:48:26
GetFileTipe это уже точно 2...
---

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



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


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