# Часть 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**

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCPEajTE0ymM38QE%2F01.png?generation=1564666295731234\&alt=media) *\*\**

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCPSB1Xckxd0ghUt%2F02.png?generation=1564666296556646\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCPj19IiOjbnZxXo%2F03.png?generation=1564666296680514\&alt=media)

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCPyjMaaMttzbPNP%2F04.png?generation=1564666295976330\&alt=media)

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCQBT9TElfnD2KbD%2F05.png?generation=1564666296298105\&alt=media)

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

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCQGRSeSCgN1jzJ0%2F06.png?generation=1564666296848537\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCQYCPhZYweOT5JC%2F07.png?generation=1564666295733777\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCQgnaACPEN8E9J6%2F08.png?generation=1564666295999043\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCQqVOlpd8ODi1jo%2F09.png?generation=1564666297955609\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCR0P2WEk3y3t_Rj%2F10.png?generation=1564666313744866\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCRBfc7T_fNSb7Ix%2F11.png?generation=1564666297210673\&alt=media)

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

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCRVLDbo168JsmhM%2F12.png?generation=1564666296172464\&alt=media)

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCRn4EQxnZP3c6Sv%2F13.png?generation=1564666296404645\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCS29zderwaAP5v3%2F14.png?generation=1564666295959787\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCSD3xSQ2lIgcFFT%2F15.png?generation=1564666296744703\&alt=media)

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

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

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCSPr4xPenhXNjWU%2F16.png?generation=1564666296358579\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCSaLIzrkal17QtY%2F17.png?generation=1564666295936205\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCSqyuyg1tS_MpiZ%2F18.png?generation=1564666296405591\&alt=media)

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCT7n0-9F1p8Dzzg%2F19.png?generation=1564666297624647\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCTPFrUr2UssOLWt%2F20.png?generation=1564666295816880\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCTXtrpXcT07dai8%2F21.png?generation=1564666295930183\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCToMfpl2qQGfwkd%2F22.png?generation=1564666296493899\&alt=media)

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCU8Oa9iNEB4Yr7l%2F23.png?generation=1564666295591336\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCUXJOzWvEaaeScu%2F24.png?generation=1564666295990206\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCVGkF8tq9vx9EJ0%2F25.png?generation=1564666295832438\&alt=media)

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCVa0pMa7yCXSB92%2F26.png?generation=1564666296021672\&alt=media)

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCW75zkvJMnVoe-w%2F27.png?generation=1564666296026368\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCWSHKWoxskfZL5g%2F28.png?generation=1564666296524086\&alt=media)

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCWrzFyGNkGTkCw8%2F29.png?generation=1564666296106259\&alt=media)

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

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCX6Vb0NSimFDjAa%2F30.png?generation=1564666295894079\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCXIGRzyfIgMQXRQ%2F31.png?generation=1564666295990117\&alt=media)

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCXdJ4jGutAuUauZ%2F32.png?generation=1564666296469833\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCXxdjPEzZwHiQx5%2F33.png?generation=1564666296331779\&alt=media)

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

![](https://2625274913-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LlCLaBFYUXycrwo1F8f%2F-LlCLnPRTA5yNwbyF2aC%2F-LlCNCYEewOSCxc3pOYB%2F34.png?generation=1564666296695545\&alt=media)

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

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

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

**======================================================= Автор текста: Рикардо Нарваха** - **Ricardo** **Narvaja** (**@ricnar456**) Перевод на русский с испанского: **Яша\_Добрый\_Хакер(Ростовский фанат Нарвахи).** Перевод специально для форума системного и низкоуровневого программирования — **WASM.IN 06.08.2018 Версия 1.0**
