# Часть 16

[\[Используемые материалы\]](https://github.com/yutewiyof/intro-rev-ida-pro/tree/e1367e11cc661f3d69c02ae5f733b7dd168bc5ab/.gitbook/assets/files/16.zip)

Прежде чем продолжать углубляться в реверсинг, мы сделаем ещё одно упражнение по распаковке на другом примере. Этим файлом будет **UNPACKME\_ASPACK 2.2**.

Он относится к категории простых. Далее в курсе, мы вернёмся к расширенной распаковке после изучения других тем.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtub4pSswBBytsuvHA%2F01.png?generation=1563266028325815\&alt=media)

Здесь, видим **EP** упакованного файла. Она начинается с инструкции **PUSHAD**, которую мы, пока, не видели среди часто используемых инструкций, но её работа заключается в том, что она **ПОМЕЩАЕТ(КЛАДЁТ)** каждый регистр в стек, т.е.

Инструкция **PUSHAD** равносильна инструкции **PUSH**, т.е. сохраняет в стек регистры в следующем порядке:

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtub5Y3-lo3HpqAstU%2F02.png?generation=1563266028718778\&alt=media)

Инструкция **POPAD** - это обратная инструкция. Она **ИЗВЛЕКАЕТ(ВЫТАЛКИВАЕТ)** содержимое стека, сохраняя его в регистрах в следующем порядке (за исключением регистра **ESP**, который не меняется командой **POPAD**):

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguuuKCHvT9PM-dD2%2F16-03.png?generation=1563195327282291\&alt=media)

В простых упаковщиках, большинство из них использовали инструкцию **PUSHAD** для сохранения первоначального состояния регистров при запуске программы и использовали **POPAD** для их восстановления, до перехода в **OEP**, для выполнения программы, уже распакованной в памяти.

Благодаря этому, была возможность легко найти **OEP**, используя метод **PUSHAD – POPAD**. Очевидно, в более современных упаковщиках, создатели заметили это и избегают использование этих инструкции.

Что такое метод **PUSHAD – POPAD**?

Прежде всего, мы должны выбрать отладчик и запустить его. Мы уже знаем как это сделать. Идём в меню **DEBUGGER → SELECT DEBUGGER** и выбираем пункт **LOCAL WIN32 DEBUGGER**.

Теперь, чтобы попрактиковаться, запустим отладчик через **PYTHON**. Вы можете вводить инструкции одну за другой в панели **PYTHON** или использовать плагин **IPYIDA**, который мы установили и которой более удобный. Я сделаю это именно так.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguuwXzvsaO6hMBhK%2F16-04.png?generation=1563195327052652\&alt=media)

Видим, что если набрать **idc.Load** и нажать **TAB**, плагин скажет, что **idc.LoadDebugger** уже существует. Проверим это.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtub7QNyMcyo2eQ4pf%2F05.png?generation=1563266029627687\&alt=media)

В нашем случае, мы должны выбрать **WIN32** и **0**, для локального отладчика(**1** используется для удаленного отладчика).

Проверим это. Для этого вводим такую команду.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-Ljpguv4wFREValrWL7p%2F16-06.png?generation=1563195327167187\&alt=media)

Кажется, что плагину понравился наш выбор. Он вернул нам **TRUE**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-Ljpguv6S1M5fHQ9xjFd%2F16-07.png?generation=1563195328183618\&alt=media)

Через меню видно, что отладчик уже выбран. Если я буду повторять ту же команду, плагин вернет мне **FALSE**, потому что дебаггер уже запущен.

Метод **PUSHAD** основывается на выполнении инструкции **PUSHAD**. В следующей инструкции, видим регистры, которые сохранились в стек и устанавливаем там **BP**, чтобы остановить выполнение, когда программа попытается восстановить их с помощью инструкции **POPAD**, непосредственно перед переходом в **OEP**, после распаковки первоначального кода.

Другими словами, я устанавливаю **BP** с помощью **F2** после инструкции **PUSHAD**. Дебаггер должен остановиться после выполнения этой инструкции. (Инструкция **PUSHA** похожа на инструкцию **PUSHAD**).

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtub9CztPPosOHsFXv%2F08.png?generation=1563266028024630\&alt=media)

Если вы хотите установить **BP** с помощью **PYTHON**, Вы можете ввести следующую команду:

```
idaapi.add_bpt(0x46B002, 0, idc.BPT_SOFT)
```

С помощью этой команды, Вы установите **BP** прям из **PYTHON**. Первый аргумент - это адрес **BP**, второй - размер и третий аргумент - его тип. Т.е обычный программный **BP** устанавливается командой **BPT\_SOFT** или **0**.

Мы уже выбрали **ОТЛАДЧИК** и установили первый **BP**. Сейчас нам нужно запустить отладчик, для того, чтобы остановиться на этом **BP**. Это очень просто. Это можно сделать с помощью **F9** или из самого **PYTHON**, командой:

```
idc.StartDebugger("","","");
```

С помощью этой команды выбранный отладчик будет запущен. Если всё сделано правильно, то отладчик остановится на **BP**, который мы установили по адресу **0x46B002**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguvEdZj_9LGWgmg1%2F16-09.png?generation=1563195327697622\&alt=media)

Здесь мы должны увидеть стек и установить **BP** на первой строке, чтобы остановиться на ней, потому что это место, где сохраняются значения регистров, сохраненные инструкцией **PUSHAD**, и они восстанавливаются позже с помощью инструкции **POPAD**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguvNRI63WlfNYiIu%2F16-10.png?generation=1563195327775890\&alt=media)

Как видно из рисунка, мы должны установить **BP** по адресу **0x19FF64** в моём случае, а в Вашем случае - это будет первый адрес стека, на который указывает регистр **ESP**.

Теперь, я помещаю курсор в окно дизассемблированного списка и нажимаю стрелку, которая находится рядом с регистром **ESP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguvPojMcVVQKv-Ne%2F16-11.png?generation=1563195327889380\&alt=media)

Нажав стрелку рядом с регистром, отладчик будет пытаться показать этот адрес, если он существует, в окне где находится курсор. Таким образом, мы можем установить **BP** вручную с помощью **F2**, но мы должны настроить этот **BP**, так как в нашем случае, он должен сработать при **ЧТЕНИИ** и **ЗАПИСИ**, а не при **ИСПОЛНЕНИИ**, так как здесь он будет останавливаться, когда восстановит или прочитает значение. Он не выполнит здесь код.

После нажатия **F2** открывается окно конфигурации **BP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubBVB-Dj-Io-J-A0%2F12.png?generation=1563266028097558\&alt=media)

Если окно не появляется, то переходим в меню **DEBUGGER → BREAKPOINTS → BREAKPOINT LIST**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubBn68XBn_4-PpzQ%2F13.png?generation=1563266027990487\&alt=media)

И я делаю правый щелчок и выбираю пункт **EDIT**, чтобы изменить конфигурацию, на ту, которую нам нужна.

Можем ли мы установить этот **BP** с помощью **PYTHON**?. Да, для этого существует такая команда:

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubCZ6742KEy4uE-0%2F14.png?generation=1563266028581322\&alt=media)

**idaapi.add\_bpt(0x019FF64, 1, 3)**

Аргумент **1** - это длина **BP** и **3** - это тип **BP**, в этом случае это соответствует типу **READ**-**WRITE ACCESS** как видно из таблицы. Если я напечатаю эту команду, появится такой же **BP**, который мы установили, недавно, вручную.

Мы отключаем предыдущие **BP**, установленные вручную в списке **BP**, с помощью правого щелчка и выбора пункта **DISABLE**. А из **PYTHON**, это можно сделать так:

**EnableBpt(0x46B002, 0)**

Когда второй аргумент равен **1**, Вы включаете **BP**, а с помощью **0** - выключаете.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubCy6Zgsr3Ccu0N0%2F15.png?generation=1563266028551155\&alt=media)

Как видно из картинки, здесь он зеленый, т.е. остановка на нём не будет выполняться (другими словами выключен), а тот **BP**, который красный, принадлежит стеку.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubDW0wBkqvgAQuWD%2F16.png?generation=1563266028219117\&alt=media)

Сейчас, мы должны продолжить с помощью **F9** или напечатать в **PYTHON** команду: **idaapi.continue\_process()**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubDmzB81fQfZDtzY%2F17.png?generation=1563266028717739\&alt=media)

Отладчик остановится сразу после инструкции **POPAD**, когда он восстанавливает регистры и видим, что из **СТАБА** он собирается перейти в **OEP** по адресу **0x4271B0**, так как последовательность инструкций **PUSH XXX** – **RET**, это то же, что и инструкция **JMP XXX**. Так что, давайте потраcсируем, немного, до прибытия в **OEP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubE3vnMjlJVt9Dm7%2F18.png?generation=1563266029531167\&alt=media)

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubEN9dQgZnAMHLNn%2F19.png?generation=1563266028283118\&alt=media)

Следующий шаг, который нужно сделать - это дамп. Для этого, мы должны найти **IB** и конечный адрес в последнем сегменте исполняемого файла.

В **СЕГМЕНТАХ** мы видим, что **IB** равна **0x400000** и заканчивается по адресу **0x46E000**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubEnRLeU1fYqf8kz%2F20.png?generation=1563266028276800\&alt=media)

Вместо того, чтобы использовать скрипт, который мы использовали в части **15**, мы используем версию для самого **PYTHON**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-Ljpguw6MzsqnHBFCCkD%2F16-21.png?generation=1563195327069528\&alt=media)

Поскольку скрипт имеет много строк, я создаю его в текстовом редакторе и сохраняю его как файл **IPYTHON\_DUMP.PY**, который также приложен к данному туториалу.

Сейчас, из меню **FILE → SCRIPT FILE**, я открываю этот скрипт. Он исполняется и создаёт файл **ASPACK.BIN**, который не имеет иконку. Для её восстановления, я буду использовать **PEEDITOR**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubFbty_3hwT8tjsM%2F22.png?generation=1563266028120840\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubGeJ4bTL1O4lbVw%2F23.png?generation=1563266028065992\&alt=media)

Делаем правый щелчок и выбираем пункт **DUMP FIXER**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubH20U3YRP62SGJq%2F24.png?generation=1563266028688474\&alt=media)

Теперь, изменив расширение файла на **EXE**, появляется иконка файла.

Сейчас, мы открываем программу **SCYLLA 0.98**. В этой части, я приложил более свежую версию. Как и раньше, будем искать процесс, который все ещё остановлен на **OEP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguwKJNzqI9I08MC9%2F16-25.png?generation=1563195327579417\&alt=media)

Сейчас, мы вводим **OEP**, который равен **0x004271B0** и нажимаем по очереди кнопки **IAT AUTOSEARCH** и **GET IMPORTS**.

Если нажмём кнопку **SHOW INVALIDS** и выберем режим **ADVANCED**, увидим, что существует несколько плохих записей. Давайте посмотрим, сможем ли мы починить их автоматически.

Видим, что программа не смогла их исправить сама. Так что давайте действовать вручную.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguwTtp5rediD9Bel%2F16-26.png?generation=1563195327617514\&alt=media)

Здесь, видим первую запись по адресу **0x460818**, она правильная и совпадает с нужным вызовом.

Более того, выше начинаются недействительные записи. Давайте посмотрим, что есть в первой неверной записи, которая находится по адресу **0x4600EC**.

Если я изменяю порядок байт с помощью **D** и затем перегруппирую их, то

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguwWpxniwByLjsH9%2F16-27.png?generation=1563195328008722\&alt=media)

Видно, что содержимое не указывает ни на какой действительный адрес, а также, если я нажму **CTRL + X**, то увижу, что ссылок не существует.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguwY2Bfda1v2qpX9%2F16-28.png?generation=1563195328537018\&alt=media)

В то время, как в действительной записи, будут существовать ссылки при использовании **API**. Например так.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguwbslOj6ysNPppi%2F16-29.png?generation=1563195327292010\&alt=media)

Так что - это пример недействительные записи **IAT**. Такие мы будем удалять.

Видим, что если я очищу содержимое с помощью кнопки **CLEAR** и нажму **IAT AUTOSEARCH** снова, при этом не используя расширенный режим, всё будет очень хорошо.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjtubJYCD_HB2IS_6cx%2F30.png?generation=1563266028291683\&alt=media)

Мы видим, что **IAT** сейчас начинается по адресу **0x460810**. Видно, что нет плохих записей, которые ошибочно добавил **РЕЖИМ ADVANCED**.

Так что, сейчас, я могу выбрать наш дамп и нажать на нём **FIX DUMP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-LjpguwfULR7FnEGiCPn%2F16-31.png?generation=1563195328008547\&alt=media)

И отремонтировав сдампленный файл, я запускаю его без проблем.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjpgtXYi2m-9DJDfnIk%2F-Ljpguwh3JIqV3ksVo1W%2F16-32.png?generation=1563195327562426\&alt=media)

И мы написали этот туториал, потому что он сам попросил нас об этом.

До встрече в **17**-й части.

Автор оригинального текста — Рикардо Нарваха.

Перевод и адаптация на английский язык — IvinsonCLS.

Перевод и адаптация на русский язык — Яша Яшечкин.

Перевод специально для форума системного и низкоуровневого программирования - WASM.IN

30.09.2017

[**Источник: ricardonarvaja.info**](http://ricardonarvaja.info/WEB/IDA%20DESDE%20CERO/CURSO%20DE%20IDA%20TUTES/16-INTRODUCCION%20AL%20REVERSING%20CON%20IDA%20PRO%20DESDE%20CERO.docx)
