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

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

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

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


Распаковка ExeCryptor 2.2 и 2.3 (на примере RAR Repair Tool 4.0), часть 2




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

Восстановление IAT ExeCryptor


Теперь переходим к восстановлению таблицы IAT. При поиске OEP мы использовали метод, связанный с раскриптовкой пакером таблицы IAT, которая расположена в программе в секции 004DC000, и имеет размер 30000 байтов. Сначала нам надо найти начало и конец IAT. Давайте перейдем в окне dump отладчика на начало секции 004DC000, и посмотрим, что там имеется:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Мы видим группу адресов, отделенных от другой группы - нолями. Первая группа адресов очень похожа на переадресованные API. Давайте это проверим. Выделяем первый адрес 004DC000, в окне CPU переходим на секцию кода, которая начинается с адреса 00401000, опять возвращаемся в окно dump, и нажимаем клавиши Ctrl + R, выполняя тем самым поиск ссылок на адрес 004DC000:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Дважды щелкаем по первой ссылке, и попадаем сюда:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Мы видим вызов какой-то API, для получения реального адреса которой используется подпрограмма раскриптовки, которая находится по адресу 005C9785. Поэтому мы можем сказать, что начало таблицы IAT находится по адресу 004DC000.


Теперь нам надо найти конец таблицы IAT. Вспомните, в первой части туториала мы находили конец таблицы IAT, на который устанавливали Hardware BreakPoint on write - это адрес 004DC844:



Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Этот адрес отделен от остального блока адресов нулями. А если мы попытаемся поискать ссылки, например, на адрес 004DC85D, нажав клавиши Ctrl + R, то ссылок на этот адрес нет.


Таким образом:

Начало IAT: 004DC000

Конец IAT: 004DC848

Размер IAT: 004DC848 - 004DC000 = 848 байтов


Здесь мы получили необходимые данные для ImpREC.


Теперь наша задача заключается в том, чтобы посмотреть, нет ли магического прыжка для восстановления IAT. Поэтому давайте посмотрим, как ExeCryptor находит правильный адрес API, и сохраняет адрес этой API в таблице IAT.


Давайте сделаем такой ход. После записи пакером последней API в конце таблицы IAT (unrar.RARSetAllYesSwitch), переходим на вкладку ‘Thread’, и подавляем все нити, кроме главной нити. Это позволит нам нормально запустить программу, поскольку дополнительные нити выполняют какие-то проверки наличия отладчика, и закрывают программу:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Запускаем программу, нажав клавишу F9. Когда программа запущена, идем в окно dump, в котором переходим на таблицу IAT, выделяем ее всю, и выполняем команду бинарного копирования:




Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Скопированные байты сохраняем в файле с помощью Hex Workshop v4.23, для чего выбираем команду Файл → Новый:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Теперь выбираем команду Правка → Специальная вставка:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Появляется диалоговое окно:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Нажимаем кнопку ‘Вставить’, и получаем файл, заполненный байтами нашей таблицы IAT:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Сохраняем этот файл с каким-либо именем, я назвал его Дамп IAT запущенной программы.


Перезагружаем программу, и выполняем раскриптовку таблицы IAT. Открываем в Hex Workshop v4.23 файл с именем Дамп IAT запущенной программы, и копируем все его содержимое. Переходим в отладчик, выделяем всю таблицу IAT, и вставляем в нее скопированные байты:




Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Получаем следующее:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая

Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Как видно, при запуске программы, ExeCryptor произвел раскриптовку многих переадресованных API, и вместо переходников, записал реальные адреса API.


Итак, нам надо посмотреть, как ExeCryptor находит реальный адрес API, и сохраняет в IAT правильное значение адреса API.


Перезагружаем программу, выполняем запись последнего элемента таблицы IAT, подавляем все вспомогательные нити, после чего устанавливаем MEMORY BREAKPOINT ON WRITE на элемент IAT, который соответствует API RegCloseKey (адрес 004DC00C). Нажимаем клавишу F9, и программа останавливается здесь:




Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


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


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Давайте немного потрассируем подпрограмму раскриптовки API с помощью клавиши F7, и видим, что после сохранения реального адреса API, программа записывает байт C3 по адресу 00562586, который она загружает с помощью инструкции LEA:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Эта инструкция RET указывает на адрес, куда должна прыгнуть подпрограмма раскриптовки:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


В справочном окне OllyDbg мы видим адрес прыжка программы - 0056257B. Продолжаем трассирование программы с F7, и попадаем сюда:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Поскольку сам пакер написан на Delphi, то мы видим, как он выполняет прыжок на реальный адрес API - 77DC6BF0 (прыжок на API с опкодом FF25 используется программами, написанными на Delphi).



Возникает вопрос, зачем программа заменяет исходную инструкцию POP EDX, которая находится по адресу 00562586, инструкцией RETN:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Ответ очевиден! Она это делает для того, чтобы дважды не выполнять ту же самую подпрограмму раскриптовки, поскольку уже получен реальный адрес API в таблице IAT. В противном случае, работа программы очень бы сильно тормозилась многократным выполнением одних и тех же подпрограмм пакера.


Однако возникает следующий вопрос, как пакер определяет корректные значения адресов APIs? Как мы видели ранее, пакер, при запуске программы, записывает реальный адрес API RegCloseKey по адресу 004DC00C. Поскольку эта API находится в библиотеке advapi32.dll, то, очевидно, что и вся первая группа переадресованных APIs, до разделительных нолей, также относится к библиотеке advapi32.dll. Давайте перезагрузим программу, выполняем запись последнего элемента таблицы IAT, подавим все вспомогательные нити, и установим BPM on access на эти переадресованные API:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


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



Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Теперь пакер будет определять реальный адрес API, находящейся по адресу 004DC01C. Поскольку пакер производит запись в своей секции, заменяя инструкцию POP EDX инструкцией RET, давайте установим BPM ON WRITE на всю эту секцию, чтобы посмотреть, что в ней изменяется:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Также установим BP на адресе возврата из этой API, чтобы не запустилась программа:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


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


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Пакер записывает значение 41 (‘A’) по адресу 005D10E0. Нажимаем несколько раз клавишу F9, и видим следующее:



Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


По адресу 005D10E0 пакер записал имя библиотеки ADVAPI32.dll, в которой программа будет выполнять поиск API. В конце имени библиотеки, выполнив инструкцию MOV BYTE PTR DS:[EAX],0 по адресу 005C0B3E, пакер записал конечный 0, который завершает текстовую строку. Опять нажимаем клавишу F9, и программа останавливается здесь:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Теперь пакер записывает байт 28 вместо байта 41 (буква A), и это действие продолжается до тех пор, пока пакер полностью не скроет уже использованное имя библиотеки. Продолжаем нажимать клавишу F9:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Здесь программа, по адресу 005D10D4, сохраняет базовый адрес библиотеки advapi32.dll, который на моей машине равен 77DC0000. Нажимаем опять клавишу F9, и программа останавливается здесь:




Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


По адресу 005B1AA4, пакер записывает значение 6981532A, которое является хэшем API RegOpenKeyExA. При очередном вызове API RegOpenKeyExA, пакер не будет выполнять все те действия, которые мы рассмотрели выше, а будет выполнять проверку содержимого адреса 005B1AA4 на наличие ноля (OR EAX,EAX):


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Если по этому адресу будет записано какое-либо значение, то пакер сделает прыжок на адрес 0054E085, который ведет на раскриптовку реального адреса API RegOpenKeyExA.


Давайте немного потрассируем программу с F7, и мы попадаем сюда:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


После выполнения инструкции ROR EAX,0C, в регистре EAX мы видим:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Как мы видим, здесь нет записи инструкции RETN вместо инструкции POP EDX, поскольку реальный адрес API RegOpenKeyExA пакер не записывает в таблицу IAT, и программа останавливается на установленной BP после инструкции CALL:




Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Трассируем программу с помощью клавиши F7, до следующей API:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Также устанавливаем BP на адрес возврата из CALL, устанавливаем Hardware BP on access Dword на адрес 005D10D4, и нажимаем клавишу F9. Программа останавливается на следующем адресе после выполнения Hardware BP on access Dword:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Здесь пакер копирует базовый адрес библиотеки advapi32.dll в регистр EDX, а не определяет его, как это было при выполнении первой API RegOpenKeyExA. Опять нажимаем клавишу F9, и программа останавливается здесь:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


По адресу 00585524, пакер записывает значение 7BB50CB2, которое является хэшем API RegQueryValueExA. Реальный адрес этой API пакер также не записывает в таблицу IAT, а сохраняет переадресованное значение.


Сделаем резюме работы пакера. Сначала пакер ищет имя используемой DLL, после чего находит ее базовый адрес (с помощью API LoadLibraryA, которую он выполняет раньше, и сохраняет найденное значение базового адреса библиотеки в своей секции). Затем пакер выполняет раскриптовку реального адреса данной API. Далее работа пакера идет по двум направлениям. Если пакер сохраняет полученное значение реального адреса API в таблице IAT, он делает изменения в своей секции, чтобы закрыть подпрограмму поиска API, которая уже выполнена, и больше не применяется. Для этого он заменяет инструкцию POP EDX инструкцией RETN. Если же пакер не записывает реальный адрес API в таблицу IAT, он сохраняет хэш этой API в своей секции, и, при необходимости, повторно выполняет раскриптовку реального адреса этой API, используя сохраненный хэш.


Теперь нам осталось применить полученные сведения для восстановления таблицы IAT. Естественно, что мы хотим автоматизировать процесс восстановления IAT с помощью скрипта.


Ранее, слово скрипт, у меня вызывало испуг, и казалось чем-то очень сложным. Но, по мере приобретения опыта написания скриптов, все оказалось очень легким. Я постараюсь здесь очень подробно описать процесс написания скрипта применительно к данной программе. В качестве основы я использовал прекрасный туториал № 55 Ricardo Narvaja “Введение в реверсинг с помощью OLLYDBG с ноля”.


Разработка скрипта всегда начинается с идеи, к которой затем присоединяются разные части кода. Идея работы скрипта для восстановления таблицы IAT для ExeCryptor заключается в том, чтобы скрипт просмотрел каждый адрес таблицы IAT, и если он находит переадресованную API в этой таблице, то должен восстановить правильный адрес данной API.


В начале каждого скрипта объявляются переменные, которые будет использовать скрипт в своей работе. Поскольку мы будем просматривать таблицу IAT, то первую переменную мы назовем table. В скрипте объявление переменной записывается так:



  var table
  


Теперь нам надо указать начальное значение, откуда скрипт должен начать просмотр таблицы IAT. Этим значением, естественно, является адрес начала таблицы IAT - 004DC000. Это начальное значением мы должны скопировать в нашу переменную table:



  var table
 
mov table,4dc000


Поскольку у нас уже имеется начальная переменная, мы должны выполнить цикл loop, который просмотрит всю таблицу IAT. Этот цикл должен проверить, является ли элемент таблицы IAT переадресованным, или нет. Если элемент таблицы IAT - переадресованный, то его нужно восстановить, если же элемент содержит реальный адрес API, скрипт должен пропустить его, и выполнить поиск следующего элемента таблицы IAT:



  var table
 
mov table,4dc000
start:
cmp [table],50000000 ja jumped
log table
ret
jumped: add table,4 jmp start


Это - основная схема скрипта. Скрипт проверяет значение элемента таблицы IAT, и если это значение будет больше 50000000 (поскольку с этого адреса, как правило, в памяти программы записываются DLLs), то, следовательно, этот элемент не является переадресованным, а он содержит корректное значение адреса API. Этот элемент мы не будем трогать, а продолжим поиск следующего элемента таблицы IAT, для чего нам нужно увеличить переменную table на 4. Далее процесс повторяется.


Как мы видим, основная схема очень простая. Когда в таблице IAT находится переадресованный элемент, прыжок не выполняется, и скрипт приходит на регистрацию значения переменной table.


Далее мы должны написать, что должен сделать скрипт, когда он найдет переадресованный элемент таблицы IAT, который нужно восстановить. Но, перед этим, мы должны убедиться в том, что найденный элемент таблицы IAT действительно является переадресованной API. Давайте пока только посмотрим на переадресованный элемент таблицы IAT, для чего запишем этот элемент в журнал регистрации LOG, и на этом завершим работу скрипта, не повторяя цикл loop. Когда не приобретен какой-либо опыт написания скриптов, лучше посмотреть, как работает процесс восстановления переадресованного элемента таблицы IAT, поэтому мы регистрируем первый найденный переадресованный элемент в журнале LOG, после чего мы должны посмотреть, как выполняется процесс получения правильного значения адреса для этой переадресованной API.


Естественно, что скрипт мы должны запускать тогда, программа остановлена на OEP, поскольку, когда мы прошли на OEP, мы имеем полностью раскриптованный код программы.


Перезагружаем программу в отладчик, и переходим на OEP:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Теперь запускаем наш скрипт, чтобы посмотреть, как он работает:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Посмотрим, зарегистрировано ли первое значение:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Давайте посмотрим, если это - переадресованный элемент, то для него мы можем назначить другую переменную, которая получала бы содержимое этого элемента, для его регистрации, и назовем ее containing:



  var table
  var containing
 
mov table,4dc000
start:
cmp [table],50000000 ja jumped
log table mov containing,[table] log containing
ret
jumped: add table,4 jmp start


Здесь мы добавили переменную containing, имя которой указывает, что она содержит значение переадресованного элемента таблицы IAT. Регистрируем эти оба значения - значение элемента таблицы IAT, и его содержимое:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Здесь мы видим элемент таблицы IAT, который нужно восстановить. Ниже этого элемента IAT показано его содержимое - адрес 005C9785. Пока все идет хорошо.


Следующим нашим шагом будет переход в цикл, и выполнение регистрации всех переадресованных элементов, для чего нам нужно убрать команду ret. И, кроме того, нам надо добавить опцию для того, чтобы скрипт, после завершения чтения всей таблицы IAT, прекратил свою работу. Мы знаем, что конец таблицы IAT находится по адресу 004DC844:



  var table
  var containing
 
mov table,4dc000
start: cmp tablе,4dc844 ja finish cmp [table],50000000 ja jumped
log table mov containing,[table] log containing
jumped: add table,4 jmp start
finish: ret


Здесь мы добавили в скрипт проверку конца таблицы IAT. Когда переменная table примет значение конца таблицы IAT - 004DC844, скрипт должен завершить свою работу, для чего он должен выполнить прыжок на метку finish, где завершается работа скрипта.


Кроме того, мы видим, что удалена команда ret, которая была расположена под командами log. После выполнения регистрации, переменная table увеличивается на 4, и этот процесс повторяется до тех пор, пока переменная table не закончит просмотр всей таблицы IAT. Запускаем скрипт, ждем завершения его работы, и смотрим, что мы получили:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Здесь мы видим два неприятных для нас момента:


  1. Наличие разделительных нулей между разными библиотеками. Для устранения этой проблемы нам нужно добавить содержимого переменной table на нули.

  2. В конце таблицы IAT скрипт показал реальные адреса API библиотеки unrar.dll, которые начинаются с адресов 10000000. Для устранения этой проблемы нам достаточно изменить константу 50000000 на 09000000.


Тогда наш скрипт будет выглядеть так:



  var table
  var containing
 
mov table,4dc000
start: cmp table,4dc844 ja finish cmp [table],9000000 ja jumped
mov containing,[table] cmp containing,0 je jumped log table log containing
jumped: add table,4 jmp start
finish: ret


Мы видим, как понемногу добавляются команды в скрипт. Никакой автор сразу не пишет скрипт в том виде, в каком он представлен в туториале, а понемногу добавляет необходимые команды, и проверяет их работу. Запускаем этот скрипт, и видим, что эти две проблемы были устранены:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Давайте подумаем о дальнейшей работе скрипта. Если мы, после регистрации содержимого переадресованного элемента IAT, изменим, значение регистра EIP, записав в него значение переменной containing, и выполним подпрограмму поиска и восстановления API, то мы сможем получить корректное значение адреса API, который мы можем записать на соответствующее место в таблице IAT.


И здесь у нас возникает серьезный вопрос. Как мы видели ранее, для тех API, реальные адреса которых пакер записывает в таблицу IAT, применяется инструкция типа:


MOV DWORD PTR:[4DCxxx],EAX


Т.е., адрес [4DCxxx] привязан к каждому элементу таблицы IAT. Нам же нужно найти какое-то место, которое будет одинаковым для всех API таблицы IAT. Как мне кажется, таким местом может быть инструкция, при выполнении которой в регистр EAX записывается реальный адрес API. Как можно найти эту инструкцию. Я решил сделать следующее.


Как мы видели ранее, при выполнении инструкции CALL DWORD PTR DS:[4DC00C], пакер записывал по адресу 004DC00C реальный адрес API RegCloseKey. Причем запись этого адреса выполнялась здесь:



Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Поскольку программа у нас остановлена на OEP, переходим на вызов инструкции CALL DWORD PTR DS:[4DC00C], который находится по адресу 0042BEF5, и устанавливаем на эту инструкцию BP. Запускаем программу, нажав клавишу F9, и программа останавливается на BP. Переходим на адрес 005C97C7, и устанавливаем на него BPM on access. И нажимаем клавиши Ctrl + F11. Трассирование этой подпрограммы пакера занимает довольно продолжительное время (на моей машине потребовалось около 8 минут, поэтому можно спокойно попить кофе), и программа останавливается на BPM on access. Переходим в окно трассирования, нажав кнопку ‘…’, и прокручиваем полученный листинг вниз, до самого конца:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


И немного выше последней зарегистрированной инструкции, мы видим нужную для нас инструкцию MOV EAX,DWORD PTR SS:[EBP-C], при выполнении которой, в регистр EAX записывается реальный адрес API. Мы можем установить на эту инструкцию Hardware Breakpoint, чтобы посмотреть, выполняется ли эта инструкция для остальных элементов IAT. Немного поэкспериментировав с разными вызовами API (с теми, которые записываются в таблицу IAT, и с теми, которые не записываются в таблицу IAT), мы видим, что эта инструкция всегда выполняется, и здесь в регистр EAX записывается реальный адрес API. Корректируем наш скрипт:



  var table
  var containing
 
mov table,4dc000
start: cmp table,4dc844 ja finish cmp [table],9000000 ja jumped
mov containing,[table] cmp containing,0 je jumped log table log containing
mov eip,containing bphws 5baf66, "x" cob restoring run
restoring: bphwc 5baf66 log eax mov [table],eax

jumped: add table,4 jmp start
finish: ret


Здесь мы видим установку Hardware Breakpoint на адрес 005BAF66, который следует за инструкцией, где в регистр EAX копируется корректное значение API. Затем скрипт записывает полученное значение регистра EAX в журнал регистрации, после чего он сохраняет значение регистра EAX в содержимом переменной table. Запускаем скрипт, и практически сразу же получаем сообщение об ошибке:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


А если мы посмотрим в журнал LOG, то там видим следующее:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Скрипт восстановил и записал реальное значение API по адресу 004DC000, после чего произошел сбой в работе скрипта (по адресу 005CD345 должно быть записано какое-то значение, которого там нет, и работа скрипта - завершена).


Давайте попытаемся сделать следующим образом. Перезагрузим программу, пройдем на OEP, предварительно подавив дополнительные нити, по адресу 004DC000 вручную запишем восстановленное значение API, и снова запустим скрипт. Получаем следующее сообщение об ошибке:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


А в журнале LOG видим следующее:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Скрипт восстанавливает значение одной API, после чего происходит сбой. Почему так происходит? Немного подумав, я пришел к следующему выводу: вся проблема заключается в том, что при запуске подпрограмм восстановления реальных адресов API, меняются значения регистров, по сравнению с теми, что были в программе, остановленной на OEP. На нижнем рисунке (слева) приведены значения регистров, когда программа остановлена на OEP, а справа приведены значения регистров программы, перед восстановлением реального адреса второй API:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая

Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Давайте попытаемся сохранить и восстанавливать исходные значения регистров перед восстановлением реального адреса очередной API. В этом случае скрипт будет выглядеть следующим образом:



  var table
  var containing
  var Temp_EAX
  var Temp_ECX
  var Temp_EDX
  var Temp_EBX
  var Temp_ESP
  var Temp_EBP
  var Temp_ESI
  var Temp_EDI
  var Temp_EIP
 
mov Temp_EAX,eax mov Temp_ECX,ecx mov Temp_EDX,edx mov Temp_EBX,ebx mov Temp_ESP,esp mov Temp_EBP,ebp mov Temp_ESI,esi mov Temp_EDI,edi mov Temp_EIP,eip
mov table,4dc000
start: cmp table,4dc844 ja finish cmp [table],9000000 ja jumped
mov containing,[table] cmp containing,0 je jumped log table log containing
mov eip,containing bphws 5baf66, "x" cob restoring run
restoring: bphwc 5baf66 log eax mov [table],eax
mov eip,Temp_EIP mov edi,Temp_EDI mov esi,Temp_ESI mov ebp,Temp_EBP mov esp,Temp_ESP mov ebx,Temp_EBX mov edx,Temp_EDX mov ecx,Temp_ECX mov eax,Temp_EAX
jumped: add table,4 jmp start
finish: ret


Объявляем переменные для хранения значений всех регистров, и, когда программа остановлена на OEP, сохраняем значения регистров в соответствующих переменных. После восстановления реального адреса какой-либо API, восстанавливаем все исходные значения регистров. Давайте проверим работу этого скрипта.


После восстановления нескольких элементов, мы опять получаем сообщение об ошибке:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


А в журнале регистрации мы видим следующее:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Произошла попытка записи в системную библиотеку ntdll.dll. Давайте пройдем на адрес 004DC298, и найдем на этот адрес ссылки в секции кода, и установим BP на каждый вызов этой API:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


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


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Интересно, мы еще не пришли на OEP, а эта API уже вызывается. Устанавливаем Hardware Breakpoint на адрес 005BAF66, нажимаем клавишу F9, и программа останавливается на Hardware Breakpoint. В регистре EAX мы видим реальный адрес API:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Теперь стал понятным сбой в работе скрипта при восстановлении данной API. Как я уже писал раньше, когда подпрограмма восстанавливает реальный адрес API, пакер хранит ее хэш в специально выделенном адресе. При последующих вызовах этой API, пакер уже не восстанавливает ее адрес через инструкцию MOV EAX,DWORD PTR SS:[EBP-C], а просто использует хэш этой API, для ее раскриптовки. В результате этого, инструкция MOV EAX,DWORD PTR SS:[EBP-C] не выполняется, подпрограмма раскриптовки не останавливается на установленной скриптом Hardware Breakpoint, а продолжает свое выполнение. Но, поскольку запуск программы выполняется не из OEP, то мы получаем сбой в работе программы и, естественно, скрипта. Решение этой проблемы может быть таким: нужно, перед запуском скрипта, по адресу 004DC298 вручную записать реальный адрес API, и скрипт, при своей работе, пропустит обработку этого адреса:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Запускаем скрипт, и после некоторого времени, опять происходит сбой:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Здесь, после восстановления реального адреса API GetThreadLocale, просто закрывается главная нить. Как быть в таком случае? Я поступил очень просто - скопировал всю таблицу IAT, и сохранил ее в Hex Workshop v4.23 с именем Таблица IAT до завершения главной нити (как это мы делали ранее).


После этого, перезагружаем программу, проходим на OEP, и вставляем в таблицу IAT байты, сохраненные в файле Таблица IAT до завершения главной нити, как это мы делали ранее. И опять запускаем скрипт. Далее скрипт работает без сбоев, и, через небольшой промежуток времени, он заканчивает свою работу:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


На всякий случай, сохраняем восстановленную таблицу IAT в Hex Workshop v4.23 с именем Recovery_IAT.


3. Получение рабочего дампа распакованной программы.


Теперь можно сдампировать память программы. Для этой цели я использую plugin OllyDbg PE Dumper v3.03 by FKMA:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Сохраняем полученный дамп памяти с любым именем, (я его сохранил с именем dumped).



Не закрывая Olly, открываем ImpREC, выбираем процесс, и вводим следующие данные:


  OEP : 004359C9 - 00400000 = 000359C9
  RVA:  004DC000 - 00400000 = 000DC000
  SIZE: 004DC848 - 004DC000 = 848
  


Нажимаем кнопку “Get Imports”, и в окне “Imported Functions Found” видим:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Все API были распознаны!!!


Теперь нам нужно вставить таблицу IAT в наш дамп. По ее родному адресу 004DC000 вставить таблицу IAT невозможно, поскольку ниже таблицы IAT расположен код, который нужен для работы программы. Можно, конечно, создать новую секцию в файле, и в нее поместить таблицу IAT. Однако, как мы видели ранее, пакер ExeCryptor создал в данной программе четыре дополнительные секции, которые вряд ли нам все понадобятся. Какие-то секции пакера нам придется удалить, а если ImpREC создаст свою секцию после секций пакера, удаление каких-либо секций пакера создаст нам определенные трудности. Поэтому, я всегда стараюсь, на стадии получения рабочего дампа памяти программы, таблицу IAT поместить где-то в теле программы, а не после секций, созданных пакером.


Как мы видим, таблица IAT, вместе с текстовыми строками ASCII и загрузчиком будет занимать 1270 байтов. Нам надо найти в файле свободное место с таким размером, где можно было бы поместить восстановленную таблицу IAT. В секции кода свободного места с таким размером нет. А вот во второй секции, начиная с адреса 00508651, имеется свободное место с размером 2CDD байтов. Как я это нашел? В окне CPU переходим на адрес 004DC000, и выполняем бинарный поиск нолей, (я постарался ввести их как можно больше - 9B):


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Поисковик несколько раз остановился на областях кода, заполненных нолями. Но они имеют небольшие размеры. А вот область кода, которая начинается с адреса 00508651, имеет нужный для нас размер (2CDD байтов):


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Нам надо проверить, записывается ли что-либо в этой области кода, при запуске программы, для чего нажимаем клавишу F9, и запускаем программу. Видим, что в этой области кода ничего не записывается, поэтому мы можем записать сюда таблицу IAT. Давайте запишем таблицу IAT с адреса 00508655.


Удаляем флажок из опции “Add new section”, и в окно вводим адрес начала таблицы IAT - 00508655 - 00400000 = 00108655:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Нажимаем кнопку Fix Dump, выбираем сделанный нами дамп памяти программы, и получаем дамп с восстановленной секцией импорта:




Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Попытаемся загрузить наш дамп в отладчик, и он нормально загружается. При этом программа сначала останавливается на TLS Callback, а затем на Entry Point программы:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


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


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Значит, где-то имеется проверка CRC. Давайте щелкнем по строке “щелкните здесь”, и посмотрим, что там имеется:



Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Итак, ошибка сгенерирована по адресу 00034913 + 00400000 = 00434913. Давайте перезагрузим наш дамп, и пройдем на этот адрес:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Выше этого адреса находится инструкция CALL 004395B4, которая, очевидно, выполняет проверку CRC. Давайте установим BP на эту инструкцию, и запустим программу, нажав клавишу F9. Когда программа останавливается на BP, давайте, заменим инструкцию CALL инструкцией NOP, и посмотрим, запустится ли программа:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая




Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


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


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Сохраняем полученные изменения в нашем дампе, и пытаемся запустить программу без отладчика. Программа нормально запускается без отладчика.


Теперь давайте попытаемся удалить ненужные секции пакера. Но, предварительно, для удобства дальнейшей работы, давайте изменим имена секций на более читабельные, для чего будем опять использовать PE Tools v1.5 RC7 by NEOx. Секцию, где находится таблица IAT, мы назовем .idata:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


А четыре секции файла, добавленные протектором, назовем .prot1, .prot2, .prot3, .prot4:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


И, на всякий случай, сделаем резервную копию нашего файла dumped_exe:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Теперь давайте посмотрим, какие секции пакера вызывает программа, при ее запуске. Загружаем наш файл dumped_exe в OllyDbg, проходим на OEP, и, будем поочередно устанавливать BPM on access на четыре секции, созданные пакером. Видим, что программа вызывает первые 3 секции - .prot1, .prot2 и .prot3. Давайте попробуем удалить последнюю секцию .prot4 с помощью PE Tools v1.5 RC7 by NEOx:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


После удаления этой секции, проходим на вкладку Optional Header, и корректируем параметры, возле которых находится кнопка с вопросительным знаком. А также исправляем параметр Base of Code:



Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Запускаем программу, и программа нормально запускается.


Теперь попытаемся удалить секцию .prot3, и посмотрим, что у нас получится. Повторяем все те же самые действия, которые мы делали с секцией .prot4:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая



Загружаем программу в OllyDbg, и видим следующее сообщение об ошибке:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Такая ошибка появляется только при сбое в таблице IAT, или TLS. В нашем файле, TLS Directory находилась в секции .prot3, которую мы удалили:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Удаляем адрес TLS Directory, и ее размер:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Сохраняем эти изменения, и загружаем файл dump_.exe в OllyDbg. Программа нормально загрузилась. Пытаемся запустить программу, и, программа запускается:


Распаковка ExeCryptor на примере RAR Repair Tool, часть вторая


Пытаемся запустить программу без отладчика, и она также прекрасно запускается.


Однако, если мы попытаемся удалить секции протектора .prot1 и .prot2, то программа не запускается, поскольку при своей работе она использует код в этих секциях. Программа имеет очень много ссылок на эти секции, и восстанавливать этой код вручную не имеет никакого смысла.


На этом мы закончили рассмотрение второй части туториала по распаковке программы, запакованной ExeCryptor.


vnekrilov



Скачать статью "Распаковка ExeCryptor 2.2 и 2.3 (на примере RAR Repair Tool 4.0), часть 2" в авторском оформление + файлы.



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


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