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

Видеокурс программиста и крэкера 5D 2O17
(актуальность: декабрь 2O17)
Свежие инструменты, новые видеоуроки!

  • 400+ видеоуроков
  • 800 инструментов
  • 100+ свежих книг и статей

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


Взлом Asprotect 2.2 SKE, часть 1




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



Программа

CHM Editor v1.1

Download

http://www.oemailrecovery.com/rar_recovery.html

Описание

Редактирование файлов справки .chm

Инструменты

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 2.1xSKE

Защита

ASProtect 2.1xSKE

Цель

Inline patching

Cracker

vnekrilov

Туториал №




0. ВВЕДЕНИЕ


В настоящее время программистами широко применяются справочные материалы в формате .chm. Справки в этом формате занимают небольшой размер, и удобны для их рассылки по сети Internet. Однако эти справки невозможно редактировать обычными редакторами для форматов .html; их необходимо предварительно преобразовывать в формат .html с помощью специальных конверторов, затем редактировать в редакторах файлов .html, и потом снова компилировать в формат .chm.

Компания GridinSoft разработала весьма неплохую программу CHM Editor v1.1, которая позволяет непосредственно выполнять редактирование файла .chm, без его предварительной декомпиляции. К сожалению, эта программа - условно бесплатная, которая работает в тестовом режиме в течение 15 дней, после чего требует покупки регистрационного ключа. Поскольку этого ключа у меня нет, я решил распаковать эту программу, и доработать ее таким образом, чтобы она больше не требовала регистрационного ключа.


Анализируем программу в Peid:


Для опытных cracker



Программа упакована ASProtect 2.1xSKE.


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


Для опытных cracker


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


1. Поиск OEP на ASProtect, имеющих версию выше 2.xx SKE:



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


Снимаем флажки со всех опций вкладки Debugging Options → Exceptions, чтобы посмотреть, что содержит эта новая версия:




Для опытных cracker


Запускаем программу ( F9 ):


Для опытных cracker


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



Для опытных cracker


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


Для опытных cracker


Значит, таблица IAT находится здесь:


Для опытных cracker


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




Для опытных cracker


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


Для опытных cracker


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


Для опытных cracker


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


Для опытных cracker



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


Для опытных cracker


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


Для опытных cracker


Что-то не очень-то похоже на OEP! Смотрим в стек:


Для опытных cracker


Переходим на адрес возврата 00C59806:


Для опытных cracker


Выполняется какой-то код пакера, который явно не связан с OEP, поэтому, трассируем до адреса 005E567C (инструкция RET 8), и нажимаем еще раз клавишу F9. Попадаем сюда:


Для опытных cracker


Опять выполняется какой-то код пакера, который не связан с OEP, поэтому, трассируем до адреса 0061A5D0 (инструкция RET 8), и еще раз нажимаем клавишу F9. Попадаем сюда:


Для опытных cracker


Это и есть наша OEP, но - это ложная OEP. Очевидно, что мы имеем дело с Виртуальной Машиной (VM), в которой должна выполняться реальная OEP. Итак, мы находимся на ложной OEP, и теперь нам надо найти реальную OEP; смотрим в стек, куда мы должны вернуться, именно где-то здесь и будет находится реальная OEP. Мы видим, что наша реальная OEP должна находиться в области памяти 003D0000. И, немного ниже вершины стека мы видим адрес реальной OEP - 003D025E:


Для опытных cracker


Давайте посмотрим, что там имеется:


Для опытных cracker


Давайте теперь перейдем на адрес возврата из программы - 003D0C95:


Для опытных cracker


Щелкаем мышкой по CALL 00DD0000, и нажимаем клавишу Enter. Устанавливаем Hardware BP on access на начало подпрограммы CALL 00DD0000:


Для опытных cracker


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


Для опытных cracker


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


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


Здесь я показал, как вручную можно найти VOEP. REVENGE Crew написал скрипт, который успешно выполняет эту работу:



  // ASProtect 1.32 and greater (except ASProtect 2.0 alpha) OEP finder by  
  // sanniassin::REVENGE Crew
  // Ignore all exceptions
  // Clear all breakpoints
  // Tested on WinXP only
 
var x // Объявляем переменные var y var is_DLL
mov x,esp // В переменную Х копируем значение регистра ESP sub x,48 // Из значения Х вычитаем число 48 bphws x,"r" // Устанавливаем Hardware breakpoint on read на полученном // адресе mov y,[eip] // В переменную Y записываем байты кода регистра EIP and y,000000FF // Выполняем логическую операцию AND cmp y,60 // Сравниваем полученное значение с числом 60 jne zzz // Если не равно, прыгаем на метку ZZZ: mov is_DLL,1
zzz: run // Запускаем программу mov y,[eip] // Записываем в переменную Y байты кода регистра EIP cmp y,01B80875 // Сравниваем полученное значение с числом 01B80875 jne zzz // Если не равно, прыгаем на метку ZZZ: bphwc x // Удаляем Hardware breakpoint on read find edi,#83C404010424C3# // Ищем цепочку байтов mov x,$RESULT // Результат поиска записываем в переменную Х add x,6 // Прибавляем число 6, чтобы получить адрес инструкции RETN bp x // Устанавливаем BP на инструкции RETN run // Запускаем программу bc x // Удаляем BP на инструкции RETN sto // Выполняем F8 mov x,eip // Записываем в переменную Х значение регистра EIP
findcall: dec x // Вычитаем из значения переменной Х - 1 mov y,[x] // Записываем в переменную Y содержимое полученного значения cmp y,5B5E5F5D // Сравниваем полученную цепочку байтов с цепочкой 5B5E5F5D jne findcall // Если не равно, продолжаем поиск sub x,8 // Из полученного значения переменной Х вычитаем число 8 go x // Выполняем программу до указанного адреса в переменной Х sti // Входим в CALL по F7 rtr // Выполняем код до инструкции RETN sto // Выходим из CALL по F8 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
VM_on_OEP: msg "OEP found! OEP stolen." // Показываем сообщение о VOEP jmp pause
no_VM_on_OEP: mov x,esp // Записываем в переменную Х адрес регистра ESP cmp is_DLL,1 // Проверяем на равенство 1 jne is_exe // Если не равно, прыгаем на метку is_exe: add x,10 jmp label_9
is_exe: add x,8 // Добавляем 8 к значению переменной Х
label_9: bphws x,"r" // Устанавливаем Hardware breakpoint on read на полученном // адресе run // Запускаем программу mov y,eip // В переменную Y записываем значение регистра EIP dec y mov y,[y] // Записываем в переменную Y байты полученного адреса and y,000000FF // Логическа операция AND cmp y,5C // Сравниваем со значение 5С jne label_9 bphwc x cmp is_DLL,1 jne is_exe2
find eip,#8944241C61FFE0# add $RESULT,5 bp $RESULT run bc $RESULT sto jmp msg is_exe2: mov x,eax go x msg: msg "OEP found! OEP not stolen."
pause: pause


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



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


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

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


Для опытных cracker


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




Для опытных cracker


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


Для опытных cracker


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


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

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


Для опытных cracker


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

004AB1FC: OEP.


Вот такую таблицу мы и должны восстановить на нашей программе chmEditor. Каким образом это можно сделать. Загружаем программу в OllyDbg, и когда она остановилась на Entry Point, нажимаем клавиши ALT+M, и устанавливаем BPM on write на секцию кода:




Для опытных cracker


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


Для опытных cracker


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


Для опытных cracker


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


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


Для опытных cracker




Примечание: Снова обратите внимание на эту область памяти, потому что она реализует действия с таблицей инициализации. Мы видим, что адрес 00C57A24 находится внутри области памяти = 00C40000.


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


Для опытных cracker


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


Для опытных cracker



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


Для опытных cracker

Для опытных cracker


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


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

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


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

Адрес

Значение

Комментарии

0061A72C


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



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



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



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



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



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



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


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


Для опытных cracker


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


Для опытных cracker


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


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

Адрес

Значение

Комментарии

0061A72C

00C57194

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

0061A730

00C571C0

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



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



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



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



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



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


Находясь в dump, нажимаем клавиши CTRL + B, и вписываем адрес хранения первого вызова процедуры раскриптовки таблицы INIT в обратном порядке 0061A72C → 2C A7 61 00:



Для опытных cracker


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


Для опытных cracker


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


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

Адрес

Значение

Комментарии

0061A72C

00C57194

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

0061A730

00C571C0

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

0061A5FC

#1

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

0061A600

0061A72C

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

0061A604

F47AA054

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

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



Для опытных cracker


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


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


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

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

00C571B4

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

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

Адрес Call EXX

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


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




Для опытных cracker


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


Для опытных cracker


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


Для опытных cracker


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


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


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

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

00C571B4

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

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

Адрес Call EXX (CALL EDX)

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


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


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



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


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


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


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


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




Для опытных cracker


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


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

Адрес

Значение

Комментарии

0061A72C

00C57194

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

0061A730

00C571C0

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

0061A5FC

#1

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

0061A600

0061A72C

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

0061A604

F47AA054

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

0061AA90

4A45F10E

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

0061AA94


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


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


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


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

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

00C571E6

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

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

Адрес Call EXX (CALL EDX)

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


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


Для опытных cracker


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


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


Для опытных cracker


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



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


end: mov [0061A5FC],numbercall // Записываем число вызовов процедуры инициализации mov [0061A600],0061A604 // Устанавливаем первый элемент для INIT bphwc 00DC00DE // Удаляем Hardware BP на CALL EDX bphwc 00C571EF // Удаляем Hardware BP на RETN, на выходе из подпрограммы // инициализации ret
error: MSG "Ошибка, работа не закончена" ret


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



Для опытных cracker

Для опытных cracker


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


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


Для опытных cracker



Запускаем HexWorkshop:




Для опытных cracker


Для опытных cracker

Для опытных cracker


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


Конец части I


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

Для опытных cracker



Скачать статью "Взлом Asprotect 2.2 SKE, часть 1" в авторском оформление + файлы.



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


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