> 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-49.md).

# Часть 49

На протяжении этого курса мы видели основы использования **IDA** для выполнения статического реверсинга, распаковки, эксплоитинга. У нас остаются ещё несколько тем для обсуждения, но внутри темы об эксплуатации у нас остается одна из наиболее тяжелых форм эксплуатации и которая пугает большое количество людей. Мы рассмотрим атаку **USE AFTER FREE**.

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

Для того, чтобы попытаться понять атаку **USE AFTER FREE**, мы будем использовать упражнение **EXAMEN 20** в качестве примера поскольку его действительно можно эксплуатировать только как **USEAFTER FREE**. В коде нет переполнения и все буферы всегда остаются правильными. Если это так, то как мы можем эксплуатировать уязвимость и отклонить выполнение программы?

Чтобы понять это, Вам нужно сначала загрузить исходный код **EXAMEN 20**.

<https://drive.google.com/file/d/0B13TW0I0f8O2WDRfQTlvT1JoNnc/view?usp=sharing>

Исполняемый файл, который зазипован и имеет пароль **a** находится здесь:

<https://drive.google.com/file/d/0B13TW0I0f8O2N1gtZWNianZpNnM/view?usp=sharing>

И символы

<https://drive.google.com/file/d/0B13TW0I0f8O2c3RRUUpJTFJMaEE/view?usp=sharing>

Символы должны быть переименованы и иметь те же имена как у исполняемого файла, но только с расширением **PDB**

![](/files/-LjtubFJC1BEUDz0yS5r)

В исходном коде, класс называется **EMPLEADOS**. Его конструктор называется **EMPLEADOS::EMPLEADOS** и виртуальные методы, которые говорят **MAL** и **PRONTO**, будут функциями, которые будут использоваться экземплярами этого класса.

Пока здесь всё понятно. Давайте посмотрим экземпляры в функции **MAIN**.

![](/files/-LjtubGC693QnAuXNJPQ)

Мы видим два экземпляра с именами **PEPE** и другой **JOSE** того же класса **EMPLEADOS**. То же самое, в этом случае, выполняется используя функцию **NEW()**, которая очень похожа на **MALLOC**, но более ориентированна на создание, в этом случае, этих экземпляров, резервируя необходимую память в кучи. (Мы помним, что когда мы трассировали функцию **NEW()** мы приходили в функцию **MALLOC**).

![](/files/-LjrTCFfL_S6-_cGipZu)

В исполняемом файле есть два вызова **NEW()** для создания обоих экземпляров **PEPE** и **JOSE**.

И если мы заглянем во внутрь вызова **NEW**, мы увидим, что вызывается функция **MALLOC** с размером, который идёт в качестве аргумента. В этом случае **416** десятичных байт или **0x1A0**, является размером, который необходим каждому экземпляру.

![](/files/-LjrTCFkjsN3_ZnK0g-A)

![](/files/-LjtubHFsTHSiNTHAHEW)

Мы знаем, что на низком уровне экземпляр подобен переменной структурного типа и должен иметь место для хранения всех атрибутов класса, которые эквивалентны полям структуры. Мы видим тип **INT** для **SALARIO\_ACTUAL**, и в публичной части буфер из **200** десятичных байт называемый **CADENA**. Другой буфер называется **NAME** и мы видим, также, объявление виртуальных методов.

Обычно внутри конструктора, на первом месте пространства зарезервированного для каждого экземпляра сохраняется указатель на таблицу адресов виртуальных методов под названием **VTABLE(ВИРТУАЛЬНАЯ ТАБЛИЦА)** и в каждом экземпляре будет указатель на ту же таблицу или **VTABLE**.

В предыдущем упражнении **№19**, которое также было с классами, хотя там не было оператора **NEW** потому что экземпляр был переменной в стеке, а не в куче, конструктор был хорошо виден.

![](/files/-LjrTCFwHHF4So7hjsse)

И поскольку внутри него же в первом **DWORD** сохраняется указатель на **VTABLE**.

![](/files/-LjrTCG0snCAex1jBT9q)

Который указывает на виртуальные методы. Сейчас в этом примере конструктор в **IDA** не рассматривается, если он существует, поскольку мы имеем символы, который программа должна вызывать, называется **EMPLEADOS::EMPLEADOS**, а этот метод не существует.

![](/files/-LjrTCG5qaYdt7Kb6sNQ)

Хорошо. Что происходит, так это то, что компилятор, как я вижу, говорит, что конструктор очень маленький и почти ничего не делает при оптимизации. Я исключаю этот метод и заменяю его инструкциями, которые содержат:

![](/files/-LjtubIr4mrW-5KpOdHt)

Конструктор только устанавливает этот атрибут в нуль и также должен установить **VTABLE** сразу после оператора **NEW**, который создаёт экземпляр. Давайте посмотрим на это в **IDA**.

![](/files/-LjrTCGCGLHHbqd63hHp)

Здесь конструктор делает две вещи - устанавливает в нуль этот атрибут и устанавливает **VTABLE** для её последующего использования.

![](/files/-LjtubJXZHq_OHfxm_vE)

Таким образом, конструктор сохраняет в первое место зарезервированной память каждого экземпляра, указатель на эту таблицу или **VTABLE**.

Прежде чем реверсить полностью пример, что мы увидим в соответствующем видео, давайте посмотрим как выглядит механизм уязвимости **USE AFTER FREE** и как он эксплуатируется.

Внутри программы, в соответствии с определенными условиями, объект удаляется с помощью оператора **DELETE()**, что эквивалентно функции **FREE()**, экземпляра **PEPE** или **JOSE**.

![](/files/-LjtubJrCWwPr0FV3ysv)

![](/files/-LjtubKAOajEEKM1gMdK)

После прекращения существования любого из этого экземпляра кому-то в голове придет просить заработную плату всех сотрудников, чтобы составить полные затраты и для этого он использует виртуальный метод get\_Salario примененный к каждому экземпляру.

![](/files/-LjrTCGXjCR09PWnpy2J)

Предположим, что **PEPE** это экземпляр, который удаляется. Когда вы пытаетесь вызвать функцию **GET\_SALARIO**, программа будет искать в своем блоке, который был освобожден (**FREE**) и попытается использовать указатель на **VTABLE**, который был там внутри и попытается перейти к методу **GET\_SALARIO**, но поскольку блок освобожден, возможно что программа продолжит выполнение, выделит её там, если она запрашивается и перезапишет указатель на **VTABLE**.

![](/files/-LjrTCGc6gKZ308tapw2)

Здесь, ниже, мы видим вызовы **GET\_SALARIO**. Каждый экземпляр будет искать внутри в первую очередь его указатель на **VTABLE** и пробовать перейти на этот метод, но эксплуатация состоит в попытке увидеть какой размер удаляемого объекта, который удаляется и выделить тот же размер и заполнить с помощью наших фруктов блок, который ранее занимал экземпляр **PEPE**, и сейчас он будет заполняться нашими фруктами. Таким образом, мы переходим к функции **GET\_SALARIO** так как мы переписали его указатель на **VTABLE**. Мы будем перенаправлять выполнение куда захотим.

Мы увидим что код создается вручную, без создания скрипта.

Я запускаю пример в **IDA**. Я устанавливаю **BP** на **NEW()**.

Я продолжаю использовать **WINDOWS 7**, которая на данный момент уверяет меня, что только с **MALLOC** я могу перезаписать занятый блок. Мы увидим как это сделать в **WINDOWS10**.

![](/files/-LjrTCGh6fL-kS5IN1ZG)

Я остановился здесь. Я ввожу **416** байт. Прохожу оператор **NEW** с помощью **F8**.

![](/files/-LjrTCGsZK3EJ3nZS2Xk)

В моём случае, программа выделяет мне блок, который начинается по адресу **0x65B510**

![](/files/-LjtubN4IEnbgyjebcSa)

В первом **DWORD** сохраняется указатель на **VTABLE**. Регистр **EBX** указывает туда где она будет сохраняться.

Здесь находится **VTABLE**. Но мы помним, что в выделенной памяти есть указатель на **THIS**.

![](/files/-LjrTCH2Mzo28_bAFXQI)

Давайте пойдём в другой вызов **NEW()**.

![](/files/-LjrTCH7mKztWkB6fdwv)

Второй экземпляр **JOSE** будет расположен, в моём случае, по адрес **0x65E000** и ниже будет сохраняться его указатель на **VTABLE**.

![](/files/-LjrTCHDRWG9SClD6fp8)

Конечно, этот указатель находится во втором экземпляре, но указывает на ту же самую **VTABLE**, которая была в первом.

![](/files/-LjrTCHJsAVwNE9iYjU_)

Давайте продолжать.

Затем есть часть кода, которая говорит, что мы вводим резюме сотрудников и там есть функция **FGETS**.

![](/files/-LjtubOni34KsRWKu9Dj)

Мы можем поместить **BP** чуть ниже, на вызове **DELETE** и нажать **RUN**.

![](/files/-LjrTCHhw32j73RcDweh)

Я ввожу короткое значение.

![](/files/-LjtubPXUjg4qHaBVe8c)

Когда я нажимаю **ENTER** программа достигает оператора **DELETE()**

Аргумент оператора **DELETE** это адрес экземпляра, который нужной удалить.

![](/files/-LjtubQDcSB-AExsnyPd)

Программа удалит блок из адрес **0x65B510** который был первым, т.е. **PEPE**.

Если я трассирую функцию **DELETE**, я вижу, что отладчик достиг функции **FREE** освобождая память по адресу **0x65B510**.

![](/files/-LjrTCI0Sb0AOp4EWDj1)

Затем программа просит меня ввести длину анкеты.

![](/files/-LjtubQyrYi7VYnObfnF)

И это значение будет тем, что вы используете для выделения и туда будете копироваться значения, чтобы вызвать **USE AFTER FREE**. Программа должна передать тот же размер удаленных инструкций, т.е. **416** десятичных.

Если я установлю **BP** на функции **MALLOC** и нажму **RUN** я введу программе этот размер **416**

![](/files/-LjrTCICln5R4kgGZ23H)

При нажатии **ENTER** я дохожу до вызова функции **MALLOC**.

Я вижу, что программа будет делать вызывать **MALLOC(416)**. Если программа вернет мне тот же адрес памяти, который я освободил то я пойду в правильном направалении, иначе ничего не получится.

![](/files/-LjtubRluTjmwSSziT8x)

Я выделяю в том же адресе. Сейчас я должен только скопировать мои фрукты туда. Они вводятся с помощью **FGETS**. Я нажимаю **RUN**, помещаю **BP** на **PRINTF**.

![](/files/-LjtubSHOwI7rhqmU63j)

![](/files/-LjrTCIS--y16orsb4S7)

Я ввожу мои фрукты и при нажатии **ENTER**.

![](/files/-LjrTCIZej3vSENMCtCS)

Программа пытается найти указатель на **VTABLE PEPE** по адресу **0x65B510** и здесь я заполняю буфер моими символами **A**.

![](/files/-LjrTCIem-CgS5dEioC2)

Здесь мы видим, как отклоняется выполнение кода, которое контролируется фруктами, которые мы вводим.

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

Мы увидим, что он будет глубоко отреверсен, в соответствующем видео на ютубе.

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

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

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

06.08.2018

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


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yutewiyof.gitbook.io/intro-rev-ida-pro/chast-49.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
