> For the complete documentation index, see [llms.txt](https://yutewiyof.gitbook.io/intro-rev-ida-pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yutewiyof.gitbook.io/intro-rev-ida-pro/chast-15.md).

# Часть 15

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

В предыдущей части, мы увидели несколько из многих методов, которые существуют для обнаружения и получения **OEP** в упакованном файле. Сейчас, вернёмся к двум пропущенными шагам: это **ДАМП** и **ВОССТАНОВЛЕНИЕ IAT**, стараясь объяснить их в этой главе.

![](/files/-LjpguuSPrve426wz5BW)

Мы снова попадаем в **OEP** программы и делаем её **ПОВТОРНЫЙ АНАЛИЗ**. Теперь у нас уже есть всё, чтобы сделать **ДАМП**.

Сейчас будем использовать **IDC** скрипт, а не **PYTHON**.

```cpp
Static main()
{
    auto fp, ea;
    fp = fopen("pepe.bin","wb");
    for(ea = 0x400000; ea < 0x40B200; ea++)
        fputc(Byte(ea), fp);
}
```

В скрипте введём **IMAGEBASE(БАЗА\_ОБРАЗА)**, адрес, которой равен **0x400000** и наибольший адрес последней секции исполняемого файла, который мы видим в **IDA** на вкладке **SEGMENTS**, который нужно **СДАМПИТЬ**. В этом случае секция **OVERLAY**, которая является последней секцией исполняемого файла, заканчивается по адресу **0x40B200**.

![](/files/-LjttuAkmCtfV1EKbITa)

![](/files/-LjttuAwc19Jh_0AnEGN)

Сохраним этот скрипт под каким-нибудь именем, например **DUMPER.IDC**

![](/files/-LjpguunYwXOJ7NkYnzl)

И запускаем его через **FILE → SCRIPT FILE**. Можно видеть, что **IDA** принимает скрипты как **PYTHON** так и свои родные **IDC**, поэтому тут с этим нет проблем.

![](/files/-LjpguurU98rzholNsFP)

Я делаю копию созданного файла и переименовываю его расширение в **EXE**. (Если Вы не видите расширения файлов, Вы должны изменить соответствующую опцию в **НАСТРОЙКАХ ПРОВОДНИКА**)

![](/files/-LjpguutENNyW7DP_yLS)

![](/files/-Ljpguuv44yt_VkGbS6P)

Видим, что у файла нет иконки, потому что некоторые шаги пропущены.

Во вложении приложен **PE EDITOR 1.7**, распакуем и запустим его.

![](/files/-LjpguuxP6oprBhi08nc)

Теперь идём в **СЕКЦИИ**.

![](/files/-Ljpguv2yuxK7zGRwq3x)

Здесь делаем правый щелчок в каждой из секций и выбираем пункт **DUMPFIXER**.

![](/files/-Ljpguv4R6Jk3cD7yaJ1)

![](/files/-Ljpguv63Oh_CYvULfTV)

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

**ЧТО ТАКОЕ IAT?**

**IAT** или **IMPORT ADDRESS TABLE** - это таблица, находящаяся в исполняемом файле, она используется, когда запускается программа. В ней программа сохраняет адреса импортируемых функций, которые она использует, для того, чтобы программа смогла запуститься на любом компьютере.

Если **IAT** верная и если мы дадим исполняемый файл другому человеку, **IAT** будет заполнена значениями, соответствующими конкретному компьютеру, независимо от версии **WINDOWS**, который он имеет, и будет оставаться совместимым, и хорошо работать.

**IAT** будет находиться в определенном месте, в каждом исполняемом файле, и она будет иметь фиксированные позиции для каждой функции, чтобы заполнять их.

Мы помним из предыдущей части, что я хотел объяснить различие между верхним изображением, которое принадлежит упакованному файлу, когда он был в **OEP** перед **ДАМПОМ** и исходного файла.

![](/files/-Ljpguv8uJ6dRCqVTKHG)

Оба изображения показывают адрес **0x403238** и похоже, что они имеют одинаковое содержимое. Сейчас, давайте откроем оригинальный файл.

![](/files/-LjttuCUaR_3N6x6MY41)

Здесь можно видеть **ФАЙЛОВОЕ СМЕЩЕНИЕ**, которое равно **0x1038**, чтобы иметь возможность искать данные в **HXD** в исходном исполняемом файле.

Давайте откроем с помощью **HXD** оригинальный файл.

![](/files/-LjttuCe2k0ah2-H3ipN)

Видим, что содержимое памяти по смещению **0x1038** равно **0x355E**.

Если я прибавлю значение **0x355E** к **IMAGEBASE**, которое равно **0x400000**, то получу результат **0x40355E**. Что существует по этому адресу?

Чтобы увидеть что там находиться, нужно загрузить исходный файл с помощью опции **MANUAL LOAD**, для того, чтобы **IDA** загрузила все секции исполняемого файла.

![](/files/-LjttuCmaQv9L5MvIVN2)

Соглашаемся со всеми секциями для загрузки и когда файл загрузится, идём по адресу **0x40355E** и видим в правой стороне имя **API** функции, оно равно **GetModuleHandleA**.

![](/files/-LjpguvGVbOIhubv9eer)

Итак, когда система загружает файл, программа начинает работать со всеми этими блоками. (**1** блок — это одна **API** функция. Прим. Яши) Их можно увидеть ниже на изображении.

![](/files/-LjttuCzu5xS4TACcPsl)

И каждый блок складывается с содержимым **IMAGEBASE** и ищет соответствующую функции строку. И из этой строки рассчитывается во время выполнения адрес для нашего компьютера. Как например в нашем случае ищется адрес **API** функции **GetModuleHandleA** на нашем компьютере и изменяется значение **5E 35** на адреса **API**.

Вот почему исполняемый файл работает на любом компьютере, потому что он всегда будет находить в каждой записи **IAT** имя соответcтвующей **API** функции и рассчитывать её адрес при загрузке программы. Таким образом всегда содержащийся в нём адрес будет действительным, хотя и будет отличаться от компьютера к компьютеру. Однако адрес блока **GetModuleHandleA** на всех компьютерах будет одинаковым во всех исполняемых файлах без рандомизации. Изменится только его содержимое.

Вот почему на любом компьютере, если я сделаю:

**CALL \[0x403238]**

Это всегда будет работать, потому что адрес **0x403238** - это запись **IAT** для функции **GetModuleHandleA**. Что будет меняться - это содержимое, которое система будет сохранять, изменив исходное значение **5E 35**, которое указывает на строку, если мы сложим её с базой.

Не закрывая две других **IDA** с упакованным файлом, который остановлен в **OEP** и исходным файлом, в третьей **IDA** я открываю **ДАМП**, который мы только что сделали. Это файл **PEPE** - **COPY.EXE**.

В этом файле идём в **IAT** по адресу **0x403238**.

![](/files/-LjttuDKzz58Dt6DoTwF)

Видим, что здесь смещение файла равно **0x3238** и оно не соответствует исходному файлу, потому что **DUMPFIXER** который исправлял **RAWSIZE** и **VIRTUALSIZE**, также изменил смещения, и запись **IAT API GMHA(**&#x47;MHA = GetModuleHandleA прим. Яш&#x438;**)**.

Если откроем этот файл в **HXD** и перейдём по адресу **0x3238**.

![](/files/-LjpguvMVNupJUr9-Ssd)

То по этому адресу увидим:

![](/files/-LjttuDcG9X1bcPPwxxn)

Видим, что здесь у нас есть адрес **API** функции, а не смещение, которое нужно сложить с **IMAGEBASE**, чтобы получился адрес **API**.

Когда система запускает упакованный файл, то рассчитываются адреса **API** функций и сохраняются в таблице. При дампинге эти адреса остаются также в этой таблице.

![](/files/-LjttuDnePG6rBkM7iq3)

Так в чём же проблема?

Когда программа запускается, она ищет в записи **IAT** значение, чтобы сложить его с **IMAGEBASE** и найти строку, чтобы рассчитать адрес, но сейчас значение поломано, потому что при дампинге был сохранен итоговый адрес, и программа будет "падать" при запуске, и будет неспособна правильно заполнить **IAT**.

Хорошо, чтобы закончить с этой темой, давайте подведём итог. Идея состоит в том, чтобы исправить **IAT** и восстановить все эти смещения, которые указывали на строки с именами **API**. Это не надо делать вручную, так как так будет очень долго. Чтобы сделать это быстрее, будем использовать утилиту под названием **SCYLLA**.

Забрать её можно здесь.

<https://tuts4yoututs4you.com/download.php?view.3503>

Пароль на архив **RAR** равен **tuts4you**

![](/files/-LjttuE-zwV2QrDoR8Nx)

Я запускаю нашу распакованную **SCYLLA**.

![](/files/-LjpguvUIkM-tpqOmLTX)

В пункте **ATTACH TO ACTIVE PROCESS** из выпадающего меню я выбираю процесс упакованного файла, который остановлен в **IDA** на **OEP**.

![](/files/-LjttuEKFN4m2Xjn_LXQ)

Теперь меняем в программе **OEP** на значение **401000**.

![](/files/-LjttuETP0Ds3rKcJfu3)

И нажимаем кнопку **IAT AUTOSEARCH**.

![](/files/-LjttuEYgYB_EtyYr0Zc)

Программа говорит нам, что таблица **IAT** начинается по адресу **0x403184** и её размер равен **0x108**.

После этого, давайте нажмём кнопку **GET IMPORTS**.

![](/files/-LjttuEedEPWrYosABta)

Видим, что **SCYLLA** нашла все адреса, за исключением трёх вхождений. Она показывает плохие записи после нажатия кнопки **SHOW INVALID**.

![](/files/-Ljpguvd6XT7GakZKWb8)

С другой стороны, видим, что смещение **3238** в упакованном файле принадлежало, соответственно, функции **GetModuleHandleA** и мы знали про это. Программа очень правильно рассчитало значение. Мы можем посмотреть в упакованном файле недействительные адреса записи **0x403248** в дальнейшем, чтобы увидеть, что они собой представляют.

![](/files/-LjpguvfjWhvq7ynCu3m)

Видим, что эта запись принадлежит библиотеке **COMCTRL32**.

И если я сделаю правый щелчок на неправильных записях в **SCYLLA** и выберу **SCYLLA PLUGIN → PE COMPACT**, она исправит эти ошибки.

![](/files/-LjttuFGJD5eUDp4QBra)

Теперь записи совпадают с теми, которые мы только что видели.

![](/files/-LjpguvjQdMtQvlQqG3w)

Если нажмём кнопку **SHOW SUSPECT**, можем увидеть, верны ли эти два подозрительных вызова по адресам **0x403258** и **0x403278**.

![](/files/-LjttuF_ltZw4d4-71wq)

Да, они получаются правильными. Так что, теперь, можем нажать кнопку **FIX DUMP**.

![](/files/-LjpguvnZQ68XI2vhVJU)

**SCYLLA** сохранит записи в починенный файл **PEPE-COPY\_SCY.EXE**, и теперь видно, что он работает.

![](/files/-Ljpguvpiozw-b77ye4n)

Открыв этот распакованный файл в **IDA**, видим, что теперь **OEP** начинается по адресу **0x401000** и что имена похожи на имена **API** как в исходном файле, так что всё рассчитались правильно.

![](/files/-LjpguvryXtLgUkTdbyf)

![](/files/-LjpguvtA26NSQUGgz4P)

Таблица **IAT** выглядит также хорошо, как и у исходного файла.

Хорошо, мы распаковали наш первый и простой упаковщик. Позже мы увидим другие, более сложные упаковщики.

До встречи в **16**-й главе.

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

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

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

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

22.09.2017

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