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

ВИДЕОКУРС ВЗЛОМ
выпущен 2 июля!


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


Распаковка ASProtect 2.3 SKE, часть 1




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

ASProtect 2.3 SKE


Программа

Reactive MYCOP Cleaner v1.2

Download

Приложена к туториалу

Описание

Учебная программа для распаковки ASProtect v2.3 SKE build 06.26 Beta

Инструменты

OllyDbg 1.10, PhantOm v0.60, PEiD v0.94, PE Tools v1.8.800.2006 RC7, Hex Workshop v4.23, Plugin OdbgScript v1.64.3, Import REConstructor v1.6 F

Сложность

Для опытных crackers

Пакер/Компилятор

ASProtect v2.3 SKE build 06.26 Beta

Защита

ASProtect v2.3 SKE build 06.26 Beta

Цель

Распаковка

Cracker

vnekrilov

Туториал №




0. Введение


Недавно, на форуме CRACKL@B, я выложил статью “Распаковка ASProtect v1.35 build 06.26”, в которой описал процесс распаковки программы, упакованной пакером ASProtect v1.35 build 06.26. Мне хочется завершить цикл статей по распаковке ASProtect всех последних версий, и продолжить подготовку статей по распаковке ExeCryptor. Для распаковки программ, упакованных разными пакерами, имеется ряд распаковщиков, которые справляются со многими пакерами. Однако, распакованные с помощью распаковщиков программы, не всегда запускаются, и приходиться вручную дорабатывать эти распакованные программы, чтобы они могли работать. Кроме того, все время появляются новые пакеры, для распаковки которых еще не созданы распаковщики. Такие программы приходится распаковывать вручную, для чего крайне необходим опыт распаковки программ, который можно приобрести только практическим путем, имея, в качестве “путеводителя” набор статей по распаковке разных пакеров. В этой статье, на примере программы Reactive MYCOP Cleaner v1.2, которую мне любезно предоставил Gideon Vi, я подробно опишу процесс распаковки пакера ASProtect v2.3 SKE build 06.26 Beta. В этой статье, я буду подробно описывать процесс распаковки этой программы, повторяя практически все то, что я писал в предыдущей статье. По своему личному опыту знаю, как сложно искать ссылки по многим источникам, и намного лучше все иметь в одном месте. Поэтому я прошу извинения у тех читателей, которые считают, что нет смысла повторять все то, что написано в предыдущих материалах. Новички, которые будут читать эту статью, в одной месте найдут всю необходимую для них информацию.


Перед началом работы, проанализируем программу в Peid:


ASProtect 2.3 SKE распаковка, первая часть



Программа упакована ASProtect 1.2x - 1.3x [Registered]. Попробуем уточнить версию пакера, для чего применим plugin VerA 0.15:


ASProtect 2.3 SKE распаковка, первая часть


Программа упакована ASProtect 2.3 SKE build 06.26 Beta [Extract].

Теперь посмотрим на эту программу в DiE v0.64:



ASProtect 2.3 SKE распаковка, первая часть


Здесь мы видим, что программа скомпилирована на Delphi.


1. Запуск файла в OllyDbg



Как всегда, попытаемся запустить программу в отладчике, чтобы проверить наличие анти-отладочных ловушек. Загружаем программу в отладчик, и получаем сообщение об ошибке:


ASProtect 2.3 SKE распаковка, первая часть


Посмотрим на карту памяти программы:


ASProtect 2.3 SKE распаковка, первая часть


Памяти по адресу 07000000 - НЕТ!




Программа еще не остановилась на Entry Point, а мы уже получили сообщение об ошибке.

Хорошо, в таких случаях рекомендуется останавливать в отладчике не Entry Point программы, а на системной BreakPoint. Делаем соответствующие изменения на вкладке отладчика “События”:


ASProtect 2.3 SKE распаковка, первая часть


Перезагружаем программу, и останавливаемся здесь:


ASProtect 2.3 SKE распаковка, первая часть


Мы остановились на системной BreakPoint.


Хорошо, давайте посмотрим на вкладку Directory Editor нашего файла, поскольку, как мы определили, программа написана на Delphi, а этот язык программирования часто использует такой параметр, как TLS Directory. Открываем программу в PE Tools v1.8.800.2006 RC7, переходим на вкладку Directory Editor, и там мы видим адрес TLS Directory - 0009CBDC. Если мы щелкнем по кнопке “…”, то увидим данные TLS Directory:


ASProtect 2.3 SKE распаковка, первая часть


Нас, естественно, интересует адрес 00485010. Поскольку программа остановлена на системной BreakPoint, то переходим в окно дампа, и там видим:


ASProtect 2.3 SKE распаковка, первая часть


Т.е., мы видим адрес 07000000, по которому у нас произошла ошибка при загрузке программы в OllyDbg.


Распаковывая многие программы, упакованные ASProtect, можно увидеть, что адрес, который показан в окне “Address of callbacks”, содержит 0. Например, если мы посмотрим на программу RAR Recovery Toolbox, которую я использовал при написании статьи по Inline patching ASProtect 2.1xSKE, то по адресу callback - 004AD010, видим:


ASProtect 2.3 SKE распаковка, первая часть


Значит, в нашем файле, вместо значения 07000000, которое записано по адресу 00485010, мы должны записать 0. Давайте проверим эту идею. Загружаем программу в отладчик, останавливаемся на системной BreakPoint, проходим на адрес 00485010, и заменяем значение 00485010 на 0:


ASProtect 2.3 SKE распаковка, первая часть


Нажимаем клавишу F9, и программа останавливается на Entry Point:


ASProtect 2.3 SKE распаковка, первая часть


Это - обычное начало программ, защищенных протектором ASProtect.


Пытаемся запустить программу, нажав клавишу F9, и программа нормально запускается:


ASProtect 2.3 SKE распаковка, первая часть


Возникает соблазн сохранить измененное значение по адресу 00485010. Однако нам это не разрешает сделать пакер Asprotect. При запуске программы с измененным значением по адресу 00485010, показывается следующая заставка:




ASProtect 2.3 SKE распаковка, первая часть


Эта ошибка говорит о том, что протектор где-то выполнил проверку CRC, а поскольку мы изменили файл, откорректировав значение по адресу 00485010, то, естественно, пакер обнаружил это изменение, и показывает нам сообщение о повреждении файла.


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


ASProtect 2.3 SKE распаковка, первая часть


Эта заставка нам сообщает, что отладчик пытался установить BreakPoint по адресу 07000000, но не нашел этот адрес, и удалил breakpoint. В этом случае, нужно нажать кнопку ОК, и программа остановится на системной BreakPoint.


2. Поиск оригинальной точки входа (OEP)


В этой версии Asprotect, автор протектора Алексей Солодовников, убрал генерацию исключений, которые можно было бы использовать при прохождении на OEP (этот метод очень неплохо описан в статье PE_Kill “Распаковка ASProtect 2.xx (Декомпиляция VM)”.


При запуске же нашей программы, если мы посмотрим в окно LOG, исключения не генерируются:


ASProtect 2.3 SKE распаковка, первая часть


Мы видим ошибку чтения памяти в отлаживаемом процессе по адресу 07000000, которую мы исправляем после остановки программы на системной BreakPoint, после чего программа нормально запускается, и не видим ни одного исключения, которое помогло бы нам пройти на OEP.



Итак, появилась первая проблема, нам нужно что-то придумать, чтобы пройти на OEP. Давайте вспомним работу ASProtect. Сначала протектор раскриптовывает код в секции кода, а затем, в последнюю очередь, он восстанавливает Таблицу IAT. Поэтому, нам нужно посмотреть, где находится Таблица IAT. Поскольку программа у нас запущена, то мы переходим в секцию кода (адрес 00401000), и выполняем бинарный поиск опкода FF 25 (выше мы определили, что программа написана на Delphi):


ASProtect 2.3 SKE распаковка, первая часть


В окне дампа выбираем режим отображения Long → Address; и мы нашли первую API CloseHandle, которая находится по адресу 004811F4 таблицы IAT.


ASProtect 2.3 SKE распаковка, первая часть


Значит, таблица IAT находится здесь (в секции 00481000, которая имеет размер 3000 байтов):


ASProtect 2.3 SKE распаковка, первая часть


Перезагружаем программу в отладчике, исправляем значение 07000000 по адресу 00485010 на 0, и устанавливаем BPM on write на эту область памяти:



ASProtect 2.3 SKE распаковка, первая часть


Запускаем программу, нажав клавишу F9, и попадаем в цикл, который нам не нужен:


ASProtect 2.3 SKE распаковка, первая часть


Устанавливаем BP (F2) после прыжка JNZ, который выполняется на начало цикла, и удаляем BPM on write. Нажимаем клавишу F9, чтобы пройти этот цикл, удаляем установленную BP, и снова устанавливаем BPM on write на секцию IAT. Такие действия нам придется повторить несколько раз, поскольку идет раскриптовка и запись кода в секцию .code. И, наконец, мы приходим сюда:


ASProtect 2.3 SKE распаковка, первая часть


Здесь началась запись адресов API в таблицу IAT. Удаляем BPM on write с секции IAT, и устанавливаем BPM on access на секцию кода программы:


ASProtect 2.3 SKE распаковка, первая часть


Нажимаем клавишу F9, и останавливаемся здесь:


ASProtect 2.3 SKE распаковка, первая часть


Попадаем на цикл записи; поэтому, устанавливаем BP на выходе из этого цикла (после прыжка JA), удаляем BPM on access, и нажимаем клавишу F9. Удаляем BP и снова устанавливаем BPM on access на область кода. Такие действия нам придется сделать несколько раз, и мы попадаем сюда:


ASProtect 2.3 SKE распаковка, первая часть


Мы пришли на OEP, но - это ложная OEP. Это утверждение можно проверить еще и следующим образом. Щелкаем правой кнопкой мыши по инструкции CALL 01BA0000, и выбираем команду:


ASProtect 2.3 SKE распаковка, первая часть


В окне ссылок (кнопка R) видим много ссылок на эту инструкцию:


ASProtect 2.3 SKE распаковка, первая часть


Очевидно, что мы имеем дело с Виртуальной Машиной (VM), в которой должна выполняться реальная OEP.


Итак, мы находимся на ложной OEP, и теперь нам надо найти реальную OEP. Как правило, при остановке программы на ложной OEP, адрес реальной OEP должен быть записан в одном из регистров:


ASProtect 2.3 SKE распаковка, первая часть


Реальная OEP должна находиться по адресу 01B802A0. Давайте посмотрим, что там имеется:


ASProtect 2.3 SKE распаковка, первая часть


Здесь мы видим инструкцию PUSH EBP, и, целую кучу мусорного кода. С инструкции PUSH EBP начинается Entry Point программа, написанных на Delphi. Если мы прокрутим немного вниз окно кода, то увидим много инструкций CALL 01C30000:


ASProtect 2.3 SKE распаковка, первая часть


В предыдущем туториале по распаковке ASProtect v1.35 build 06.26, достаточно было установить Hardware BP on access на начало подпрограммы CALL XXXXXXXX, и в одном из регистров всегда можно увидеть адрес OEP. Давайте попытаемся сделать тоже самое и в этой программе. Щелкаем мышкой по CALL 01C30000, нажмем клавишу Enter, и устанавливаем Hardware BP on access на начало подпрограммы CALL 01C30000:



ASProtect 2.3 SKE распаковка, первая часть


Перезагружаем программу, и нажимаем клавишу F9, и, программа останавливается на Hardware BP on access:


ASProtect 2.3 SKE распаковка, первая часть


Хотя программа остановилась на адресе 01C30000, однако этот адрес не является началом инструкции CALL 01C30000. Приходится нажимать клавишу F9 примерно 30 раз, пока программа не остановится на начале инструкции CALL 01C30000:


ASProtect 2.3 SKE распаковка, первая часть


Смотрим в окно регистров:

ASProtect 2.3 SKE распаковка, первая часть


В регистре EDX мы видим адрес реальной OEP - 01B802A0; но поскольку эта OEP находится в виртуальной машине, то мы назовем ее - виртуальной OEP (VOEP).


Примечание: Адрес VOEP не обязательно может быть записан в регистре EDX. У меня, при каждой перезагрузке программы, этот адрес записывался также в регистры ESI и EDI.


Здесь я показал, как вручную можно найти VOEP. Умение ручного нахождения OEP очень важно для любого cracker’s программ. Найдя вручную OEP, можно написать скрипт для прохождения на OEP, поскольку, при распаковке программ, эту процедуру приходится выполнять много раз. REVENGE Crew написал скрипт, который успешно выполняет эту работу, и очень мне нравится в работе. Но этот скрипт не работает на ASProtect v2.3 SKE build 06.26 Beta, потому что в этой версии пакера не совпадает одна “реперная” точка - это проверка цепочки байтов 5B5E5F5D. Вместо этой цепочки байтов, пакер ASProtect v2.3 SKE build 06.26 Beta имеет другую цепочку байтов - C35B5E5F, которую нужно использовать в данном скрипте. Поэтому я немного доработал этот скрипт, который теперь выглядит следующим образом:



  // ASProtect v2.3 SKE build 06.26 Beta  OEP Finder по  
  // REVENGE Crew, модифицирован - vnekrilov
  // Установить флажки на все исключения отладчика
  // Удалить все установленные breakpoints
  // Тестировался только на WinXP
 
var x // Объявляем переменные var y var is_DLL
mov x,esp // В переменную Х копируем значение регистра ESP sub x,48 // Из значения Х вычитаем число 48 bphws x,"r" // Устанавливаем Hardware breakpoint on read на полученном // адресе, чтобы остановить программу на инструкции PUSHAD mov y,[eip] // В переменную Y записываем байты кода регистра EIP and y,000000FF // Выполняем логическую операцию AND cmp y,60 // Сравниваем полученное число с опкодом инструкции PUSH (60) jne zzz // Если это не инструкция PUSH, прыгаем на метку ZZZ: mov is_DLL,1
zzz: run // Запускаем программу mov y,[eip] // Записываем в переменную Y байты кода регистра EIP cmp y,01B80875 // Сравниваем полученное значение с опкодом 01B80875 (мы должны // попасть в область памяти Asprotect 009E000 jne zzz // Если не равно, прыгаем на метку ZZZ: bphwc x // Удаляем Hardware breakpoint on read find edi,#83C404010424C3# // Ищем цепочку байтов (реперная точка Asprotect) mov x,$RESULT // Результат поиска записываем в переменную Х add x,6 // Прибавляем число 6, чтобы получить адрес инструкции RETN bp x // Устанавливаем BP на инструкции RETN run // Запускаем программу bc x // Удаляем BP на инструкции RETN sto // Выполняем F8 mov x,eip // Записываем в переменную Х значение регистра EIP
findcall: // Поиск CALL, который приводит нас на OEP dec x // Уменьшаем адрес в переменной Х на 1 mov y,[x] // Записываем в переменную Y содержимое полученного значения cmp y,C35B5E5F // Сравниваем полученную цепочку байтов с цепочкой C35B5E5F jne findcall // Если не равно, продолжаем поиск

sub x,8 // Из полученного значения переменной Х вычитаем число 8, чтобы // пройти на нужный CALL go x // Выполняем программу до нужного нам CALL sti // Входим в CALL по F7 rtr // Выполняем код этого CALL до инструкции RETN sto // Выходим из CALL по F8, и мы должны оказаться на OEP mov x,eip // Записываем в переменную Х значение регистра EIP (OEP) and x,0000FFFF // Выполняем логическое действие AND cmp x,0 // Если результат не равен 0, переходим на метку VM_on_OEP:, // если он равен 0, прыгаем на метку no_VM_on_OEP: je no_VM_on_OEP // Если код OEP не украден, прыгаем на метку no_VM_on_OEP:
VM_on_OEP: // Приходим сюда, если код OEP - украден (VOEP) msg "OEP найден! OEP украден." // Показываем сообщение о VOEP jmp pause // Прыгаем на закрытие скрипта
no_VM_on_OEP: // Прыгаем сюда, если код OEP - не украден (реальная OEP) mov x,esp // Записываем в переменную Х адрес регистра ESP cmp is_DLL,1 // Проверяем, это файл DLL или EXE jne is_exe // Если не равно 1, прыгаем на метку is_exe: add x,10 // Для DLL к значению в переменной X добавляем 10 jmp label_9 // И прыгаем на метку label_9
is_exe: // Сюда мы попадаем, если работаем с файлом EXE add x,8 // Для файла EXE к значению в переменной X добавляем 8
label_9: bphws x,"r" // Устанавливаем Hardware breakpoint on read на полученном // адресе run // Запускаем программу mov y,eip // В переменную Y записываем значение регистра EIP dec y // Уменьшаем адрес в переменной Y на 1 mov y,[y] // Записываем в переменную Y байты полученного адреса and y,000000FF // Выполняем логическую операции AND с FF cmp y,5C // Проверяем полученное значение со значением 5С jne label_9 // Если полученное значение не равно 5C, повторяем цикл bphwc x // Удаляем Hardware breakpoint on read cmp is_DLL,1 // Проверяем файл на его принадлежность к DLL jne is_exe2 // Если это не файл DLL, прыгаем на метку is_exe2:
find eip,#8944241C61FFE0# // Ищем цепочку байтов add $RESULT,5 // К полученному адресу добавляем число 5 bp $RESULT // Устанавливаем на полученный адрес BP run // Запускаем программу bc $RESULT // Удаляем установленную BP sto // Выполняем F8 jmp msg // Прыгаем на метку msg:
is_exe2: // Сюда мы попадаем, если работаем с файлом EXE mov x,eax // Копируем в переменную X значение регистра EAX go x // Выполняем программу до адреса, указанного в X
msg: // Показываем сообщение msg "OEP найден! OEP не украден."
pause: pause // Останавливаем работу скрипта


3. Восстановление INIT: Таблица инициализации.


Таблица инициализации INIT имеется только в программах, скомпилированных на Delphi, и, поскольку наша программа скомпилирована тем же самым компилятором, то нашу работу, после прохождения на VOEP, надо начинать с восстановления Таблицы инициализации INIT.




Чтобы немного разобраться, как работает эта таблица, давайте посмотрим на какую-либо неупакованную программу, скомпилированную на Delphi. У меня установлена такая программа -Resource Hacker v3.3.4.75, которая хорошо известна всем cracker’s. Давайте на ней и рассмотрим формат Init Table:

Загружаем эту программу в отладчик, и она останавливается на Entry Point - 004AB1FC:


ASProtect 2.3 SKE распаковка, первая часть


Здесь мы видим OEP (или, точнее Entry Point), поэтому перейдем на эту OEP в Dump, и, чтобы сделать ее более наглядной, выбираем режим отображения Long → Address.


ASProtect 2.3 SKE распаковка, первая часть


Давайте немного прокрутим вверх, и находим начало таблицы INIT:


ASProtect 2.3 SKE распаковка, первая часть


Собираем необходимую информацию:


004AB02C: Число вызываемых адресов (39h адресов).

004AB030: Начало таблицы INIT.




ASProtect 2.3 SKE распаковка, первая часть


004AB1F8: Конец таблицы INIT.

004AB1FC: OEP.


И, обратите внимание на разделительные нули перед последним адресом таблицы INIT.


Вот такую таблицу мы и должны восстановить на нашей программе Reactive MYCOP Cleaner. Каким образом это можно сделать?


Загружаем программу в OllyDbg, и когда она остановилась на Entry Point, нажимаем клавиши ALT+M, и устанавливаем BPM on write на секцию кода:


ASProtect 2.3 SKE распаковка, первая часть


Нажимаем клавишу F9, и программа останавливается здесь:


ASProtect 2.3 SKE распаковка, первая часть


Эта область памяти нас не интересует, поэтому несколько раз нажимаем клавишу F9, пока не окажемся здесь:


ASProtect 2.3 SKE распаковка, первая часть


Примечание: Мы должны остановиться на области памяти, созданную пакером ASProtect, базовым адресом которой является адрес 009E70000.


Устанавливаем BP (F2) после прыжка JNZ, удаляем BPM on write, нажимаем клавишу F9, и останавливаемся на BP. Удаляем эту BP, и снова устанавливаем BPM on write на секции .code, как это делали ранее. Нажимаем клавишу F9, и останавливаемся здесь:


ASProtect 2.3 SKE распаковка, первая часть



Примечание: Снова обратите внимание на эту область памяти, потому что она реализует действия с таблицей инициализации. Мы видим, что адрес 00987A24 находится внутри области памяти 009E0000.


Устанавливаем BP после прыжка JA, и удаляем BPM on write. Нажимаем клавишу F9, и останавливаемся на BP. Удаляем эту BP, и снова устанавливаем BPM on write на секции .code, как это делали ранее. Нажимаем клавишу F9, и останавливаемся здесь:




ASProtect 2.3 SKE распаковка, первая часть


И снова устанавливаем BP после прыжка, удаляем BPM on write, запускаем программу с F9, и останавливаемся на BP; опять удаляем BP и устанавливаем BPM on write на секцию .code, запускаем программу, и останавливаемся здесь:


ASProtect 2.3 SKE распаковка, первая часть

ASProtect 2.3 SKE распаковка, первая часть


Как писал в своей статье Rain, в регистр EDX - записываются первый и второй вызовы процедур раскриптовки Таблицы инициализации INIT, а в регистр ECX - записываются адреса расположения процедур раскриптовки таблицы инициализации INIT. При выполнении первой инструкции MOV DWORD PTR DS:[EDX],ECX, по адресу, записанному в регистр EDX, записывается адрес первой процедуры раскриптовки таблицы инициализации. Когда нажимаем еще раз клавишу F9, то останавливаемся на второй инструкции MOV DWORD PTR DS:[EDX],ECX, где, по адресу, записанному в регистр EDX, будет записан адрес второй процедуры раскриптовки таблицы инициализации, который хранится в регистре ECX. Поэтому, мы сначала будем работать с первой процедурой раскриптовки таблицы инициализации, которая находится по адресу 00A1E188, а затем, со второй процедурой раскриптовки таблицы инициализации, которая находится по адресу 00A1E1B4. Кстати, обращаем внимание на то, что адрес, записанный в регистре EDX (0047D280), находится недалеко от конца секции .code, где обычно, в большинстве программ, написанных на Delphi, хранится INIT TABLE.


Итак, у нас уже имеется первая информация. Давайте эту информацию поместим в таблицу, которая не позволит нам запутаться (такую таблицу предложил Ulaterck). В левой части таблицы будем записывать данные формата INIT, а в правой части таблицы - небольшое описание того, что мы будем находить при восстановлении INIT.



Поэтому, записываем значение регистра EDX как адрес первого вызова Таблицы инициализации, потому что по этому адресу записывается адрес первой процедуры раскриптовки таблицы инициализации.

Таблица Nº1: INIT

Адрес

Значение

Комментарии

0047D280


- Адрес хранения первого вызова процедуры раскриптовки таблицы INIT



- Адрес хранения второго вызова процедуры раскриптовки таблицы INIT



- Число вызываемых адресов



- Адрес вызова первой процедуры раскриптовки таблицы инициализации



- Начало выполнения процедуры раскриптовки таблицы инициализации (Первое восстанавливаемое значение в script1)



- Завершение выполнения процедуры раскриптовки таблицы инициализации (Первое восстанавливаемое значение в script2)



- Это будет наша новая OEP


Перезагружаем программу, записываем 0 по адресу 00485010, удаляем все установленные BP и Hardware BP, и запускаем script для поиска VOEP. Нам нужно остановить программу VOEP, адрес которой мы уже нашли - 01B802A0:


ASProtect 2.3 SKE распаковка, первая часть


Находясь на VOEP, проходим в окне dump на первый адрес, который мы нашли в регистре EDX, т.е. на адрес 0047D280. По этому адресу записан адрес расположения первой процедуры раскриптовки таблицы INIT:


ASProtect 2.3 SKE распаковка, первая часть


Здесь мы видим два адреса, которые расположены рядом. Первый адрес содержит адрес вызова первой процедуры раскриптовки таблицы INIT - 00A1E188, а второй адрес содержит адрес вызова второй процедуры раскриптовки таблицы INIT - 00A1E1B4. Давайте запишем эти адреса в нашу таблицу:



Таблица Nº1: INIT

Адрес

Значение

Комментарии

0047D280

00A1E188

- Адрес хранения первого вызова процедуры раскриптовки таблицы INIT

0047D284

00A1E1B4

- Адрес хранения второго вызова процедуры раскриптовки таблицы INIT



- Число вызываемых адресов



- Адрес вызова первой процедуры раскриптовки таблицы инициализации



- Начало выполнения процедуры раскриптовки таблицы инициализации (Первое восстанавливаемое значение в script1)



- Завершение выполнения процедуры раскриптовки таблицы инициализации (Первое восстанавливаемое значение в script2)



- Это будет наша новая OEP


Находясь в dump, нажимаем клавиши CTRL + B, и вписываем адрес хранения первого вызова процедуры раскриптовки таблицы INIT в обратном порядке 0047D280 → 80 D2 47 00:


ASProtect 2.3 SKE распаковка, первая часть


Нажимаем кнопку OK:


ASProtect 2.3 SKE распаковка, первая часть


Мы видим, что адрес, который находится выше найденного адреса, должен содержать число вызываемых адресов, но вместо этого, asprotect установил там 1. Кроме того, в следующем адресе записан адрес, в котором находится первый вызов процедуры раскриптовки таблицы INIT. Поэтому, чтобы не усложнять процедуру, мы указываем адрес, откуда надо начать восстановление таблицы INIT, и, соответственно, имеем:



Таблица Nº1: INIT

Адрес

Значение

Комментарии

0047D280

00A1E188

- Адрес хранения первого вызова процедуры раскриптовки таблицы INIT

0047D284

00A1E1B4

- Адрес хранения второго вызова процедуры раскриптовки таблицы INIT

0047D110

#1

- Число вызываемых адресов

0047D114

0047D280

- Адрес вызова первой процедуры раскриптовки таблицы инициализации

0047D118

961E7C57

- Начало выполнения процедуры раскриптовки таблицы инициализации (Первое восстанавливаемое значение в script1)

Проходим в область вызова процедуры раскриптовки таблицы INIT, т.е., на адрес 00A1E188, и устанавливаем там BP (F2). Запускаем программу, и останавливаемся на BP:


ASProtect 2.3 SKE распаковка, первая часть


Вызов первой процедуры раскриптовки таблицы INIT: Теперь мы напишем другую таблицу, которую назовем “Таблица № 2 - Вызов первой процедуры раскриптовки таблицы INIT”.


Аналогично предыдущим действиям, мы должны заполнить эту таблицу, которая будет полезной для написания script1. Первым мы указываем адрес нахождения CALL DWORD PTR DS:[A229C4] (для сведения), и адрес нахождения инструкции RETN:



Таблица Nº2: Вызов первой процедуры раскриптовки таблицы INIT

Адрес Call (для справки)

00A1E1A8

Адрес инструкции RETN

00A1E1B1 (для установки Hardware BP)

Адрес Call EXX

Находится внутри CALL [A229C4] (для установки Hardware BP)


Теперь нам осталось найти адрес Call EXX, для чего входим в CALL DWORD PTR DS:[A229C4] с помощью клавиши F7:


ASProtect 2.3 SKE распаковка, первая часть


Прокручиваем листинг вниз, чтобы найти CALL EXX, где EXX может быть любым регистром:


ASProtect 2.3 SKE распаковка, первая часть


Устанавливаем Hardware BP on execution на этот call, и нажимаем клавишу F9. Останавливаемся на CALL ESI, смотрим в окно регистров, и видим:


ASProtect 2.3 SKE распаковка, первая часть


Здесь мы видим значение, которое должно быть записано нашей таблице инициализации - EAX = 004D6BFC.


Теперь у нас имеется вся таблица № 2:


Таблица Nº2: Вызов первой процедуры раскриптовки таблицы INIT

Адрес Call (для справки)

00A1E1A8

Адрес инструкции RETN

00A1E1B1 (для установки Hardware BP)

Адрес Call EXX (CALL EDX)

01C20263 (для установки Hardware BP)


Нам нужно откорректировать script для восстановления вызовов инициализации, который предложил Rain, и немного доработан мной. Находим помеченные цветом данные в таблице № 2, и записываем эти данные в скрипт.



Данные для script инициализации.



  // Скрипт запускать, когда программа остановлена на VOEP
  // Скрипт разработан Rain, и доработан vnekrilov
 
// Объявляем переменные
var init // Переменная для записи адресов таблицы INIT var value // Счетчик числа восстановленных адресов (с шагом 8)
mov value,0 // Устанавливаем начальное значение переменной value в 0
// Записываем значения из предыдущей таблицы.
bphws 01C20263,"x" // Устанавливаем Hardware BP на CALL ESI bphws 00A1E1B1,"x" // Устанавливаем Hardware BP на RETN, на выходе из подпрограммы // инициализации
search: mov init,0047D118 // Записываем адрес первого восстанавливаемого значения INIT TABLE // из таблицы 1 run // Запускаем программу eob recovery // Если останавливаемся на breakpoint, то прыгаем на метку recovery
recovery: cmp eip,01C20263 // Проверяем, остановились ли мы на CALL ESI jne completion // Если EIP = 01C20263, то выполняем восстановление адреса, если // EIP = 00A1E1B1, то прыгаем на метку completion: add init,value // Сначала счетчик установлен на 0, и его значение мы поочередно // добавляем начальному значению адреса таблицы IAT, который нам // надо восстановить. Счетчик value мы увеличиваем с шагом 8, // поскольку эти элементы Init попарно чередуются друг с другом. mov [init],esi // Остановившись на call ESI, записываем значение регистра ESI в // таблицу инициализации add value,8 // Увеличиваем значение переменной value, для перехода на следующий // адрес таблицы инициализации. jmp search // Продолжаем работу с последующими адресами таблицы INIT
completion: cmp eip,00A1E1B1 // Проверяем, остановились ли мы на инструкции RETN (этот адрес // имеется в таблице № 2) je end // Если Да, то работа завершена успешно. jmp error // Если Нет, то работа была неудачной.


end: add init,value // Получаем последний адрес вызова начала процедуры инициализации mov [init],0 // Этот адрес должен быть заполнен 0 bphwc 01C20263 // Удаляем Hardware BP на CALL ESI bphwc 00A1E1B1 // Удаляем Hardware BP на RETN, на выходе из подпрограммы // инициализации ret
error: MSG "Ошибка, работа не закончена" ret


Удаляем все Hardware BP, которые у нас были, и перезапускаем программу.


Проходим на VOEP с помощью script OEPFinder.osc.




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


ASProtect 2.3 SKE распаковка, первая часть


Ура! Script восстановил адреса таблицы INIT, для которых используется первая процедура раскриптовки. Теперь давайте посмотрим на второй вызов процедуры раскриптовки таблицы INIT:


Таблица Nº1: INIT

Адрес

Значение

Комментарии

0047D280

00A1E188

- Адрес хранения первого вызова процедуры раскриптовки таблицы INIT

0047D284

00A1E1B4

- Адрес хранения второго вызова процедуры раскриптовки таблицы INIT

0047D110

#1

- Число вызываемых адресов

0047D114

0047D280

- Адрес вызова первой процедуры раскриптовки таблицы инициализации

0047D118

961E7C57

- Начало выполнения процедуры раскриптовки таблицы инициализации (Первое восстанавливаемое значение в script1)

0047D30C

A0DAEC24

- Завершение выполнения процедуры раскриптовки таблицы инициализации (Первое восстанавливаемое значение в script2)

0047D310


- Это будет наша новая OEP


В этой таблице вторая строка показывает адрес вызова второй процедуры раскриптовки таблицы INIT - 00A1E1B4. Этот адрес находится чуть ниже инструкции RETN, на которой наш скрипт завершил свою работу. Причем код этой части процедуры раскриптовки, практически ничем не отличается от кода предыдущей процедуры раскриптовки (просто на 4 байта сдвинуты все адреса, по сравнению с адресами второй процедуры раскриптовки таблицы INIT).


Поэтому мы можем легко заполнить таблицу Вызовов конца процедуры инициализации, для чего переходим на адрес подпрограммы раскриптовки по адресу 00A1E1B4. Выделяем инструкцию PUSH, и устанавливаем новый адрес регистра EIP, нажав клавиши CTRL + *:


Таблица Nº3: Вызов второй процедуры раскриптовки таблицы INIT

Адрес Call (для справки)

00A1E1DA

Адрес инструкции RETN

00A1E1E3 (для установки Hardware BP)

Адрес Call EXX (CALL EDX)

01C20263 (для установки Hardware BP)


Устанавливаем новый адрес регистра EIP - 00A1E1B4:


ASProtect 2.3 SKE распаковка, первая часть


И, теперь пишем скрипт, который восстановит нам вторую группу адресов таблицы INIT (еще раз подчеркиваю, что вторая процедура раскриптовки таблицы INIT начинает раскриптовку с последнего адреса таблицы). Этот скрипт очень похож на предыдущий скрипт, но с некоторыми дополнениями.


Первое, что нам надо найти - это конец таблицы INIT. Для этого проходим в окно dump, и ищем последнее восстановленное значение INIT (вспомните, что в 1-м скрипте мы завершили восстановление первой части таблицы INIT записью 0):


ASProtect 2.3 SKE распаковка, первая часть


Красной стрелкой я пометил последнее восстановленное значение первым скриптом (помните, мы в нем записали нулевое значение), и после него идет значение, которое будет первым значением для второго скрипта восстановления таблицы INIT. Адрес этого значения - 0047D30C. А следующий адрес, который следует за этим значением, будет новым OEP - 0047D310. Необходимо иметь в виду, что второй скрипт будет запускаться с адреса предыдущей OEP, поэтому мы завершим работу скрипта адресом, который будет содержать фактическое число адресов Таблицы INIT (0047D110), и восстановим значение первого адреса таблицы INIT (0047D114):





  // Скрипт запускать, когда программа остановлена на VOEP
  // Скрипт разработан Rain, и доработан vnekrilov
 
// Объявляем переменные
var init // Переменная для записи адресов таблицы INIT var value // Счетчик числа восстановленных адресов (с шагом 8) var numbercall // Счетчик числа вызовов процедуры инициализации
mov value,0 // Устанавливаем начальное значение переменной value в 0 mov numbercall,0 // Устанавливаем начальное значение переменной numbercall в 0
// Записываем значения из предыдущей таблицы.
bphws 01C20263,"x" // Устанавливаем Hardware BP на CALL ESI bphws 00A1E1E3,"x" // Устанавливаем Hardware BP на RETN, на выходе из подпрограммы // восстановления вызовов инициализации
search: mov init,0047D30C // Записываем адрес первого восстанавливаемого значения INIT TABLE // из таблицы 1 (Вызов конца процедуры инициализации) run // Запускаем программу eob recovery // Если останавливаемся на breakpoint, то прыгаем на метку recovery
recovery: cmp eip,01C20263 // Проверяем, остановились ли мы на CALL ESI jne completion // Если EIP = 01C20263, то выполняем восстановление адреса, если // EIP = 00A1E1E3, то прыгаем на метку completion: sub init,value // Сначала счетчик установлен на 0, и его значение мы поочередно // добавляем начальному значению адреса таблицы IAT, который нам // надо восстановить. Счетчик value мы увеличиваем с шагом 8, // поскольку эти элементы Init попарно чередуются друг с другом. mov [init],esi // Остановившись на call ESI, записываем значение регистра ESI в // таблицу инициализации add value,8 // Увеличиваем значение переменной value, для перехода на следующий // адрес таблицы инициализации. inc numbercall jmp search // Продолжаем работу с последующими адресами таблицы INIT
completion: cmp eip,00A1E1E3 // Проверяем, остановились ли мы на инструкции RETN (этот адрес // имеется в таблице № 3) je end // Если Да, то работа завершена успешно. jmp error // Если Нет, то работа была неудачной.


end: mov [0047D110],numbercall // Записываем число вызовов процедуры инициализации mov [0047D114],0047D118 // Устанавливаем первый элемент для INIT bphwc 01C20263 // Удаляем Hardware BP на CALL ESI bphwc 00A1E1E3 // Удаляем Hardware BP на RETN, на выходе из подпрограммы // инициализации ret
error: MSG "Ошибка, работа не закончена" ret


Запускаем этот скрипт, который я назвал Recovery_INIT_2.osc.


ASProtect 2.3 SKE распаковка, первая часть

ASProtect 2.3 SKE распаковка, первая часть


Итак, мы восстановили таблицу INIT, и теперь знаем, где должна быть наша новая OEP.


Нам нужно скопировать эту восстановленную таблицу INIT:


ASProtect 2.3 SKE распаковка, первая часть


Запускаем HexWorkshop:


ASProtect 2.3 SKE распаковка, первая часть



ASProtect 2.3 SKE распаковка, первая часть

ASProtect 2.3 SKE распаковка, первая часть


Вставляем и сохраняем этот новый файл с именем Recovery_INIT.


Конец части I


Далее мы рассмотрим восстановление IAT и прыжков на IAT, виртуальную машину Asprotect, и регистрацию программ, которые используют Asprotect.



Скачать статью "Распаковка ASProtect 2.3 SKE, часть 1" в авторском оформление + файлы.
пароль архива на картинке



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


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