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

# Часть 67

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

> Метод, который мы не рассмотрели, чтобы эксплуатировать одну из уязвимостей драйвера HACKSYS.

Мой друг попросил у меня несколько разъяснений о методе, используемом для обхода **COOKIE** на **32**-битных машинах, когда у нас есть переполнение стека в ядре, и мы можем перезаписать адрес возврата, но есть **COOKIE**, который мешает нам завершить выполнение кода.

Очевидно, что если у нас есть другая уязвимость, которая допускает утечку данных, мы могли бы прочитать значение **COOKIE** и затем использовать его для отправки наших данных, для перезаписи, но есть метод, который я никогда не использовал на практике, который немного стар и в системах, отличных от **WINDOWS 7 32** бит не будет работать, но было бы хорошо взглянуть на него, чтобы уточнить для моего друга и того, кто читает меня (и для меня самого).

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

<https://github.com/hacksysteam/HackSysExtremeVulnerableDriver/releases/download/v1.20/HEVD.1.20.zip>

А сам инструмент для загрузки драйвера, можно загрузить отсюда.

<http://www.osronline.com/OsrDown.cfm/osrloaderv30.zip?name=osrloaderv30.zip&id=157>

Прежде чем скопировать драйвер в целевую машину, мы откроем его в загрузчике **IDA** для его анализа.

Внутри **ZIP** архива находятся такие файлы.

> **HEVD.1.20\DRV\VULNERABLE\I386**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduQ72XPIt0wCJlFA%2F67-01.png?generation=1563261697359342\&alt=media)

Это драйвер и его символы.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduQLYeAH-ioyQ0FO%2F67-02.png?generation=1563261697790744\&alt=media)

При открытии драйвера в **IDA**, мы видим функцию **DRIVERENTRY**, первым аргументом которой всегда является указатель на объект **\_DRIVER\_OBJECT**.

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

Регистр **ESI** это указатель на объект **\_DRIVER\_OBJECT**.

Если мы перейдём во вкладку **LOCAL TYPES**.

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

Мы видим, что эта структура. Если мы поищем структуру **\_IRP**, мы находим наиболее часто используемым для обращения структуры.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduQfvFaXCylTfMm2%2F67-05.png?generation=1563261698867018\&alt=media)

Мы будем отмечать структуры **\_DRIVER\_OBJECT**, **\_IRP**, **\_DEVICE\_OBJECT**, **\_IO\_STACK\_LOCATION** и **PIRP** и синхронизировать их, потому что именно их мы будем использовать чаще всего.

То что нам нужно сделать - это добавить структуру **MAJORFUNCTION**, которой нигде нет.

Напомним, что мы можем добавить структуру через вкладку **LOCAL TYPES**, используя правую кнопку мыши, пункт **INSERT** и вставить этот код.

```cpp
struct __MajorFunction
{
    SIZE_T _MJ_CREATE;
    SIZE_T _MJ_CREATE_NAMED_PIPE;
    SIZE_T _MJ_CLOSE;
    SIZE_T _MJ_READ;
    SIZE_T _MJ_WRITE;
    SIZE_T _MJ_QUERY_INFORMATION;
    SIZE_T _MJ_SET_INFORMATION;
    SIZE_T _MJ_QUERY_EA;
    SIZE_T _MJ_SET_EA;
    SIZE_T _MJ_FLUSH_BUFFERS;
    SIZE_T _MJ_QUERY_VOLUME_INFORMATION;
    SIZE_T _MJ_SET_VOLUME_INFORMATION;
    SIZE_T _MJ_DIRECTORY_CONTROL;
    SIZE_T _MJ_FILE_SYSTEM_CONTROL;
    SIZE_T _MJ_DEVICE_CONTROL;
    SIZE_T _MJ_INTERNAL_DEVICE_CONTROL;
    SIZE_T _MJ_SCSI;
    SIZE_T _MJ_SHUTDOWN;
    SIZE_T _MJ_LOCK_CONTROL;
    SIZE_T _MJ_CLEANUP;
    SIZE_T _MJ_CREATE_MAILSLOT;
    SIZE_T _MJ_QUERY_SECURITY;
    SIZE_T _MJ_SET_SECURITY;
    SIZE_T _MJ_POWER;
    SIZE_T _MJ_SYSTEM_CONTROL;
    SIZE_T _MJ_DEVICE_CHANGE;
    SIZE_T _MJ_QUERY_QUOTA;
    SIZE_T _MJ_SET_QUOTA;
    SIZE_T _MJ_PNP;
    SIZE_T _MJ_PNP_POWER;
    SIZE_T _MJ_MAXIMUM_FUNCTION;
};
```

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduQrH0zjL3gT7z30%2F67-06.png?generation=1563261697900920\&alt=media)

Мы добавляем и синхронизируем структуру, и последнее что мы делаем – открываем во вкладке **LOCAL TYPES** структуру **\_DRIVER\_OBJECT** и изменяем ее так, чтобы последнее поле представляло собой структуру типа **\_MAJORFUNCTION**.

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

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

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

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

Мы видим, что регистр **ESI** сохраняет значение указателя на объект **\_DRIVER\_OBJECT** в этой области, а по адресу **0x000160СF** и это значение указателя затирается.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduR9AVQ3NHsT4GAZ%2F67-09.png?generation=1563261698841074\&alt=media)

Таким образом, мы помечаем эту зону (это можно сделать с помощью **ALT + L**, спустится стрелкой курсора и затем снова нажать **ALT + L** для завершения) или если это небольшая область сделать это той же мышью.

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

Как только зона отмечена, мы нажимаем **T**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduRQ_rtUdQnkaDFz%2F67-11.png?generation=1563261698226749\&alt=media)

Конечно, мы выбираем регистр **ESI** в качестве базового регистра структуры и смещение, которое мы устанавливаем в нуль, потому что оно указывает на начало структуры, и мы выбираем структуру **\_DRIVER\_OBJECT**, и **IDA** обнаруживает **4** поля которые используются.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduRZyJMFQoRD84by%2F67-12.png?generation=1563261700767897\&alt=media)

Для нас важно то поле, которое обрабатывает **IOCTL**, т.е. **\_MJ\_DEVICE\_CONTROL**.

Если бы у нас не было символов, такая же работа выполнялась бы путем импорта файла **.H** с **32**-битными структурами для реверсинга драйверов.

Файл **.H** с 32-битными структурами находится здесь.

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

И он импортируется в **IDA** отсюда.

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

При этом мы увидим необходимые структуры **DRIVER\_OBJECT**, **\_IRP**, **\_DEVICE\_OBJECT**, **\_IO\_STACK\_LOCATION** и **PIRP** и **\_MAJORFUNCTION** в **LOCAL TYPES**. Мы синхронизируем их и получим таким же образом возможность распознавать функцию, которая обрабатывает **IOCTL**.

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

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

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

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

Вызов идет сюда.

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

И затем сюда.

Мы видим, что есть функция **MEMCPY**, которая копирует буфер в стек. **MAXCOUNT** - количество байтов. Полностью отреверсив функцию мы увидим, что у неё есть **COOKIE**. Хотя мы это уже видели до адреса возврата, который в отличие от другого переполнения стека, который мы уже эксплуатировали.

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

Перед инструкцией **RETN** есть такой вызов.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduS4MV7rqkPVNXSo%2F67-18.png?generation=1563261698794117\&alt=media)

Эта проверка и в начале функции она то же есть.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduSAw172vMQhykRO%2F67-19.png?generation=1563261698018484\&alt=media)

Возвращаясь к началу функции с именем **IRPDEVICEIOCTLHANDLER**, которая обрабатывает **IOCTL**, в регистре **EDI** передается указатель на структуру **IRP**. Мы уже видели в предыдущих туториалах, что в **32х** битных системах по смещению **0x60** это был указатель на структуру **IO\_STACK\_LOCATION**, которая останется в регистре **ESI**.

И я нажимаю **T** на **ESI** + **0xC**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduSGIcnA10n7OtRL%2F67-20.png?generation=1563261699548886\&alt=media)

Как мы уже видели, что структура **IO\_STACK\_LOCATION** варьируется в зависимости от функции, в которой она используется , поскольку здесь мы используем её в случае функции, которая обрабатывает **IOCTL**. Мы должны выбрать **DEVICEIOCONTROL**.

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

Я оставлю всё это так. В этой функции, регистр **ESI** имеет указатель на **IO\_STACK\_LOCATION**, регистр **EDX** – это код **IOCTL** (**IOCONTROLCODE**) и **EDI** указатель на **\_IRP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduSS9x_GVJP8dIt2%2F67-22.png?generation=1563261697433824\&alt=media)

Регистр **ESI** и регистр **EDI –** это два аргумента вызова функции **STACKOVERFLOWGSIOCTLHANDLER**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduS_X8ci9BdsTz_5%2F67-23.png?generation=1563261697656885\&alt=media)

Конечно, поскольку у нас есть символы, мы можем видеть эти два аргумента в определении функции. Первый - это указатель на **\_IRP**, а второй - указатель на **IO\_STACK\_LOCATION**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduSiMxAuGIinh-O_%2F67-24.png?generation=1563261697226791\&alt=media)

Опять же, пытаясь определить поле **\_IO\_STACK\_LOCATION**, мы должны выбрать случай, когда используется **DEVICEIOCONTROL**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduSnXwYYlQ7ydyLR%2F67-25.png?generation=1563261697783582\&alt=media)

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

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

Поле **INPUTBUFFERLENGHT** - это размер входного буфера из режима пользователя, а **TYPE3INPUTBUFFER** - указатель на этот пользовательский входной буфер, который мы также передаем.

Переименуем эти два аргумента. Помните, что та переменная, которую мы называем **SIZE\_BUFFER\_USER**, является произвольным переданным нами числом, которое должно быть размером буфера, но это может быть любое значение, так как не видно никакой проверки.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduSz3Vc4v-O5GZno%2F67-27.png?generation=1563261697745181\&alt=media)

Мы видим, что обе переменные используются без проверки или изменения в функции **MEMCPY**.

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

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduT9vVo_IY0sXWpx%2F67-29.png?generation=1563261697590459\&alt=media)

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

Инициализируется только **0x1FF** байт буфера. Также нет проблем, что некоторые байты ещё остались нетронутыми.

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

В начале функции мы видим, что выше адреса возврата есть структура **CPPEH\_RECORD**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduTU5HrgNzosD08H%2F67-32.png?generation=1563261701905421\&alt=media)

Она находится чуть ниже буфера и поверх адреса возврата.

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

Мы видим, что в стек помещаются два аргумента. Константа **0x210** и указатель на структуру. Константа **0x210**, так как это первый **PUSH**, будет чуть выше адреса возврата **R**, который я сохранил при входе в эту же функцию пролога.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduTih27bBnyILkBf%2F67-34.png?generation=1563261698866078\&alt=media)

Однако мы видим, что **IDA** показывает нам, что чуть выше "**R**" находится сохраненный регистр **EBP** т.е. "**S**".

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

Также, если мы войдем в функцию **\_\_SEH\_PROLOG4\_GS**.

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

Мы видим, что после помещения в регистр **EAX** значения переменной **CONS\_0x210**, программа сохраняет здесь регистр **EBP**, так что на самом деле выше "**R**" , наконец, остается "**S**" или сохраненный регистр **EBP**.

Затем, над сохраненным регистром **EBP**, помещается указатель на эту структуру которая передается сразу после инструкции **PUSH 0x210**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduTwPZbhfapIgWIc%2F67-37.png?generation=1563261699057932\&alt=media)

По этому адресу находится структура **STRU\_0x12218**. Программа сохраняет её чуть выше "**S**".

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

И чуть выше "**S**" находится переменная **MS\_EXC**, которая является структурой типа **CPPEH\_RECORD**, так что этот адрес будет последним полем этой структуры, и мы увидим это.

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

Здесь после сохранения сохраненного регистра **EBP** в переименую **CONST\_0X210** программа помещает адрес указанной переменной в регистр **EBP**. Это будет более или менее похоже на начало функции **PUSH EBP**, **MOV EBP**, **ESP**.

Оба должны сохранить значение регистра **EBP** родительской функции **TRIGGERSTACKOVERFLOWGS** и установить новый регистр **EBP** для неё через инструкцию **LEA**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduUGRtd-W50nEyLR%2F67-40.png?generation=1563261701283767\&alt=media)

Затем программа освобождает место для переменных, выполняя инструкцию **SUB ESP**, **EAX**.

И также мы видим, что по адресу **EBP-4 XOR**ится значение, которое было там с **COOKIE**, которое читается из секции данных.

Напомним, что по адресу **EBP-4** находится значение **0x12218**. С этим значением **XOR**ится **COOKIE** и сохраняется по этому адресу.

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

Кроме того, **XOR**ится **COOKIE** с регистром **EBP** и полученное значение сохраняется по адресу **EBP-1C**.

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

Это то, что программа будет проверять в эпилоге.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduUaJoY_yZ7HCEsQ%2F67-43.png?generation=1563261699742254\&alt=media)

И внутри функции **\_\_SECURITY\_CHECK\_COOKIE**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduUioKZU3LxY5Zmi%2F67-44.png?generation=1563261699246552\&alt=media)

Программа сравнивает значения. Если они одинаковы, то всё хорошо, а если нет мне выкидывает **BSOD**.

Мы создадим стек с самого начала в соответствии с порядком, с которым программа размещает значения перед входом в пролог:

```
PUSH 0x210
PUSH 0x12218
```

Затем программа входит в пролог, который заставляет её сохранять адрес возврата в стеке, куда она будет возвращаться. Это будет адрес **0x000148E9**, поскольку при выходе из пролога программа вернется туда.

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

Таким образом, при входе в пролог мы имеем в стеке два аргумента и адрес возврата, куда вернется программа.

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

Давайте продолжим смотреть на то, как аргументы помещаются в стек.

Затем есть еще две инструкции **PUSH** - адрес функции **EXCEPTION\_HANDLER4** и значение, которое содержит регистр **FS:0**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduV3BhCv5FLyqE_E%2F67-47.png?generation=1563261703128252\&alt=media)

Над обратным адресом тогда будут эти два значения.

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

Затем **0x210** перезаписывается **STORED\_EBP**.

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

Мы знаем, что под сохраненным регистром **EBP** был адрес возврата в функцию **TRIGGERSTACKOVERFLOWGS**. Мы добавили его в наше представление стека.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduVMpiywADYqGrU-%2F67-50.png?generation=1563261702473841\&alt=media)

Текущий регистр **EBP** остается с адресом **STORE\_EBP** (смотри на адрес, а не значение)

Из регистра **ESP** вычитается значение **0x210** для пространства переменных, другими словами над адресом **FS:0** - **0x210** останется регистр **ESP**.

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

Затем выше есть еще три **PUSH** - **EBX**, **ESI** и **EDI**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduVbfe67TdOpHx50%2F67-52.png?generation=1563261700216399\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduVj9IC2wQX1KPT4%2F67-53.png?generation=1563261698405857\&alt=media)

Затем содержимое **EBP-4 XOR**ится с **COOKIE**.

Поскольку **ТЕКУЩИЙ EBP** продолжает указывать на адрес **STORE\_EBP**, **EBP-4** указывает на значение **0x12218**, это значение **XOR**ится с **COOKIE**.

```
ЗНАЧЕНИЕ EBX
ЗНАЧЕНИЕ ESI
ЗНАЧЕНИЕ EDI
…
…
…
FS:0
__EXCEPT_HANDLER4
0x148E9 <---- АДРЕС ВОЗВРАТА В ПРОЛОГ
0x12218 <--------XORится с COOKIE
STORED_EBP <----- ТЕКУЩИЙ EBP - АДРЕС STORED_EBP
АДРЕС ВОЗВРАТА В ФУНКЦИЮ TriggerStackOverflowGS
```

Если мы сделаем так, чтобы уточнить первый столбец, с адресами ссылающимися на значение **ТЕКУЩЕГО EBP**.

```
ЗНАЧЕНИЕ EBX
ЗНАЧЕНИЕ ESI
ЗНАЧЕНИЕ EDI
…
…
…
EBP-10 FS:0
EBP-C __EXCEPT_HANDLER4
EBP-8 0x148E9 <---- АДРЕС ВОЗВРАТА В ПРОЛОГ
EBP-4 0x12218 <--------XORИТСЯ С COOKIE
EBP STORED_EBP <----- ТЕКУЩИЙ EBP - АДРЕС STORED_EBP
АДРЕС ВОЗВРАТА В ФУНКЦИЮ TRIGGERSTACKOVERFLOWGS
```

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

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

В обычной функции регистр **ESP** при возврате равен тому же значения, что и перед передачей аргументов.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduVtoRUUIWprMb-o%2F67-54.png?generation=1563261701812447\&alt=media)

Но в данном конкретном случае эта специальная функция похожа на часть функции **TRIGGERSTACKOVERFLOWGS**, выполняемой в отдельном **CALL**.

Если принимать регистр **ESP** в качестве нуля в начале функции, я вижу, что при возврате из **CALL** регистр увеличивается на **0x234** байт, потому что внутри функции пролога было сделано несколько инструкций **PUSH**, была выполнена инструкция **SUB ESP**, **0x210**, и был осуществлен возврат из функции без восстановления регистра **ESP**.

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

Многие скажут, но если регистр **ESP** не восстановлен, как найти адрес возврата в стеке, который намного ниже значения регистра **ESP**.

Мы говорили, что адрес **EBP-8** указывает на адрес возврата, чтобы вернуться из функции пролога в **TRIGGERSTACKOVERFLOWGS** и **ТЕКУЩИЙ ESP** после того, как три **PUSH** из **EBX**, **ESI** и **EDI**остались выше.

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

Если мы посмотрим в функции пролога, увидим, что она возвращает адрес возврата с помощью инструкции **PUSH** - **RET**.

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

Помещенное в стек значение, указанное через адрес **EBP-8**, является адресом возврата. Программа помещает значение обратно в стек и затем выполняет инструкцию **RET**, и программа возвращается к функции **TRIGGERSTACKOVERFLOWGS**, не восстанавливая **ESP** и оставляя весь стек целым, как это было в прологе.

Между инструкцией **PUSH** и **RET** есть только инструкции **MOV** и **LEA**, поэтому стек не затрагивается, и это аналогично **PUSH-RET**.

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

Мы создали стек здесь.

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

До этого момента он был создан так.

```
ЗНАЧЕНИЕ EBX
ЗНАЧЕНИЕ ESI
ЗНАЧЕНИЕ EDI
…
…
…
EBP-10 FS:0
EBP-C __EXCEPT_HANDLER4
EBP-8 0x148E9 &lt;---- АДРЕС ВОЗВРАТА В ФУНКЦИЮ ПРОЛОГ
EBP-4 0x12218 &lt;--------XORED COOKIE
EBP STORED_EBP &lt;----- ТЕКУЩИЙ EBP - АДРЕС STORED_EBP
АДРЕС ВОЗВРАТА В ФУНКЦИЮ TRIGGERSTACKOVERFLOWGS
```

Мы уже знаем, что ничего из этого не будет потеряно, все, что я добавлю или изменю в прологе в стеке, не будет удалено, поскольку **PUSH-RET** покинет стек, как это было для функции **TRIGGERSTACKOVERFLOWGS**.

Еще одна вещь, которая уже настроена для функции **TRIGGERSTACKOVERFLOWGS**, это регистр **EBP**.

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

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

Я смотрю функцию **TRIGGERSTACKOVERFLOWGS**, чтобы попытаться увидеть, где это соответствует адресу **EBP-1C**, где программа хранит **COOKIE**.

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

Мы видим, что переменная **MS\_EXC** находится по адрес **EBP-0x18**. Другими словами место, где программа хранит **COOKIE**, которое вы собираетесь проверить, находится чуть выше структуры **MS\_EXC**.

Напомним, что буфер **DST** был инициализирован только с **0x1FF** байтами, и мы сказали, что осталось несколько байтов чуть ниже него, поэтому, если мы поправим размер **DST** на **0x1FF**, у нас будет переменная, в которой сохраняется **COOKIE** в стеке.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduWiNHIWiKH3Z8DI%2F67-61.png?generation=1563261697449173\&alt=media)

Здесь я назначаю новый размер и у меня остается четыре пустых байта между ними. Я нажимаю **D**, пока я не изменю на **DWORD** (**DD**), и переименую переменную в **COOKIE**.

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

Я вижу, что это по адресу **EBP-1C** (слева от названия есть позиция относительно **EBP** т.е. **0x0000001C**).

Затем идет инструкция **PUSH EAX** и сохраняется текущее значение регистра **ESP** по адресу **EBP-18**, которое было внутри структуры **MS\_EXC**, которая начинается здесь. Это первое поле той же структуры.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduWvrfuwzLvJhUpb%2F67-63.png?generation=1563261701111790\&alt=media)

Если мы заглянем внутрь структуры, первым полем будет **OLD ESP**

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

Так что стек стал таким

```
ЗНАЧЕНИЕ EAX
ЗНАЧЕНИЕ EBX
ЗНАЧЕНИЕ ESI
ЗНАЧЕНИЕ EDI
…
EBP-10 FS:0
EBP-C __EXCEPT_HANDLER4
EBP-8 0x148E9 <---- АДРЕС ВОЗВРАТА В ПРОЛОГ
EBP-4 0x12218 <--------XORится с COOKIE
EBP STORED_EBP <----- ТЕКУЩИЙ EBP - АДРЕС STORED_EBP
АДРЕС ВОЗВРАТА В ФУНКЦИЮ TRIGGERSTACKOVERFLOWGS
```

Поскольку теперь обе функции совместно используют стек, если мы сравним их, мы увидим, что над **STORED\_EBP** находится значение **MS\_EXC**, поэтому внутри пролога чуть выше переменной "**S**" байты также являются полями указанной структуры.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduX9boLoJwu9N9NZ%2F67-65.png?generation=1563261697205743\&alt=media)

Эти **4 DWORDS** являются **4** нижними полями структуры **MS\_EXC**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduXH-duvZ_KE64JO%2F67-66.png?generation=1563261697416050\&alt=media)

Помните, что последние **4** поля структуры - это другая структура размером **0x10** байтов, т.е. **16** в десятичной системе (**4 DWORDS**), поэтому на изображении отмечены только те **4 DWORDS**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduXP3iSG3MTxrEYY%2F67-67.png?generation=1563261699227676\&alt=media)

Двумя важными переменными являются **NEXT** и **EXCEPTION HANDLER**. Мы уже знаем их положение в стеке. Мы видим, что переменная **NEXT** в структуре имеет значение **FS:0**, а **EXCEPTIONHANDLER** на данный момент имеет значение **\_\_EXCEPT\_HANDLER4**, хотя они еще не добавлены в цепочку **SEH**.

```
ЗНАЧЕНИЕ EAX
ЗНАЧЕНИЕ EBX
ЗНАЧЕНИЕ ESI
ЗНАЧЕНИЕ EDI
…
…
…
EBP-10 FS:0 - (NEXT)
EBP-C __EXCEPT_HANDLER4 - (EXCEPTION_HANDLER)
EBP-8 0x148E9 <---- АДРЕС ВОЗВРАТА В ПРОЛОГ -(SCOPETABLE)
EBP-4 0x12218 <--------XORится с COOKIE (TRYLEVEL)
EBP STORED_EBP <----- ТЕКУЩИЙ EBP - АДРЕС STORED_EBP
АДРЕС ВОЗВРАТА В ФУНКЦИЮ TRIGGERSTACKOVERFLOWGS
```

Хорошо. У нас создан стек, и мы видим справа синие поля структуры.

Поскольку адрес возврата уже помещен в стек, изменение значения сохраненной переменной не имеет значения.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduXaL2MpinQmIzNq%2F67-68.png?generation=1563261700923401\&alt=media)

Мы видим, что в по адресу **EBP-8** (**SCOPETABLE**) программа сохраняет значение **COOKIE, XOR**ит его со значением **0x12218**, которое было в **EBP-4**, а затем в том же **EBP-4**, что является **TRYLEVEL**, сохраняет значение **0xFFFFFFFE**.

В конце программа сохраняет адрес **EBP-10 - NEXT** в регистр **FS:0** с настроенным обработчиком исключений.

Мы знаем, что регистр **FS:0** указывает на последний элемент в списке цепочки исключений, т.е на верхнюю часть всей цепочки.

Помните, что добавление нового элемента в список осуществляется с помощью этого кода

```
PUSH OFFSET HANDLER
PUSH FS:[0]
MOV FS:[0], ESP
```

Т.е. поскольку здесь выполняется следующая инструкция **MOV LARGE FS:0, EAX**

Этот регистр **EAX** является адресом стека, где находится новый **NEXT** и ниже **SEH**.

Так как регистр **EAX** является адресом **EBP-10**, здесь будет переменная **NEXT** и чуть ниже **SEH**, как мы уже говорили.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduXhSeF_vUII1eH-%2F67-69.png?generation=1563261701046053\&alt=media)

Я вижу, что регистр **FS:0** указывает на верхний элемент цепочки **SEH**. В моем случае он равен **9CCEFCC0**. Если я посмотрю, здесь должны быть переменные **NEXT** и **SEH**. Переменная **NEXT** равна **0xFFFFFFFF**, потому что это последний **NEXT** в цепочке исключений.

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

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduXw7Vu0dWtDIz6Q%2F67-71.png?generation=1563261701211432\&alt=media)

Если я продолжу трассировать пролог, я попадаю туда, где регистр **EAX** сохранится в регистр **FS:0**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduY3ApsvtKTJBbNl%2F67-72.png?generation=1563261702264013\&alt=media)

Здесь мы видим новый драйвер, добавленный в цепочку.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduYAeYN8tmS5PNa4%2F67-73.png?generation=1563261697446121\&alt=media)

Как мы уже рассматривали, адрес **EBP-10** будет новым **NEXT**, а ниже находится **SEH**, который будет являться **\_EXCEPT\_HANDLER4**. Это то значение, которое мы должны будем переписать для эксплуатации

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

Хорошо. У нас уже все хорошо расположено. Пора начинать писать эксплойт.

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

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

Метод работает, но эксплойт делаем сбой и вызывает **BSOD**. Так что нам нужно будет увидеть, где произошел сбой. Наверняка есть что-то что мы не видим.

Основное объяснение этого метода находится здесь:

<http://poppopret.blogspot.com/2011/07/windows-kernel-exploitation-basics-part_16.html>

И исходный код публичного эксплойта находится здесь:

<https://github.com/hacksysteam/HackSysExtremeVulnerableDriver/tree/master/Exploit>

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

Прежде всего, если бы мы сделали это в **PYTHON**, у нас была бы проблема, которую можно решить, но, компилируя его в **C++**, у нас уже есть модуль, который помимо запуска и экслуатации повышения привилегий, мы можем скомпилировать его по своему вкусу, например, без **SAFESEH**, или **DEP** или **ASLR**. В опциях **VISUAL STUDIO** позволят нам выбрать то что нужно, поэтому, если кто-то загружает решение, т.е. файл **SLN** в **VISUAL STUDIO**, вам придется изменить параметры по умолчанию.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduYReyV47T-TCO7c%2F67-75.png?generation=1563261697810454\&alt=media)

Чуть выше находится это.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduYWQ2yXdNp8HNEA%2F67-76.png?generation=1563261700098785\&alt=media)

Хорошо. Я приложу скомпилированный файл с его символами **HACKSYSEVDEXPLOIT.EXE** и **HACKSYSEVDEXPLOIT.PDB**, чтобы его было легко увидеть в **IDA**.

Исполняемый файл скомпилирован для всех уязвимостей, которые есть у драйвера, и его выполнение в консоли в **WINDOWS 7 32** с аргументами **-G -C XXX.EXE** достаточно, так как я уже добавляю в конце этого метода выполнение калькулятора c правами **SYSTEM** после поднятия прав. В остальных вместо **XXX.EXE** придется подставить **CALC.EXE** или **CMD.EXE**

Хорошо. Мы переходим к функции, которая использует эту уязвимость. В данном случае - **STACKOVERFLOWGSTHREAD**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduYamrUYHKggDpMG%2F67-77.png?generation=1563261699937566\&alt=media)

После исправления некоторых проблем консоли, которые не имеют отношения, давайте проанализируем эксплойт, который мы открываем в **IDA**, и видим, что эксплойт начинается здесь:

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

Внутри мы видим вызов функции **CREATEFILE** для получения дескриптора драйвера.

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

Все это так же, как и случаи, которые мы видели в предыдущих ядрах.

Регистр **EBX** остается с дескриптором драйвера, он используется только при вызове **DEVICEIOCONTROL** ниже.

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

Хорошо. Затем идет вызов функции **CREATEFILEMAPPING**, что является пространством виртуальной памяти, которое будет связано с содержимым файла. (Функция не резервирует память, только создает объект и возвращает дескриптор)

<https://docs.microsoft.com/en-us/windows/desktop/memory/file-mapping>

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduYzHROPALqs4xbn%2F67-81.png?generation=1563261698316068\&alt=media)

Но если мы посмотрим в описание функции **CREATEFILEMAPPING**, мы увидим, что первым аргументом является дескриптором файла, но нам также говорится, что может быть передан аргумент **INVALID\_HANDLE\_VALUE**. В этом случае, программа создаст отображение файла, не связывая его с файлом, и это будет общая анонимная память.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduZ5fAa8e_pmBHB_%2F67-82.png?generation=1563261702733964\&alt=media)

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

Хорошо. Это тот случай, поэтому мы видим, что когда вызывается эта **API**, вы передаете значение **0xFFFFFFFF**, которое является **INVALID\_HANDLE\_VALUE**.

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

В исходном коде, под названием **SHARED MEMORY**, созданном здесь, мы видим, что функции передаются разрешение на выполнение, чтение и запись.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduZMHYcl64mnYWOY%2F67-85.png?generation=1563261700037688\&alt=media)

Хорошо. Она возвращает нам дескриптор файлового отображения.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduZTKhP0oqOtMLWA%2F67-86.png?generation=1563261698778966\&alt=media)

Затем программа вызывает функцию **MAPVIEWOFFILE**, которая отображает объект в памяти, зарезервировав необходимое для него пространство.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduZ_jWhLOy3b0CHM%2F67-87.png?generation=1563261700875029\&alt=media)

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

Хорошо. Функция возвращает адрес начала секции, созданного для отображения файлов.

Чтобы отладить эксплойт в режиме пользователе, несмотря на драйвер, я копирую сервер **IDA** - **WIN32\_REMOTE.EXE** в целевую машину и запускаю его.

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

Я запускаю его на сервере с правами администратора в целевой системе, а на машине, где я реверсил эксплойт, меняю отладчик на удаленный отладчик **WINDOWS**. В **PROCESS OPTIONS** я указываю **IP**-адрес и порт.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduZxzsVzSBvMKtbb%2F67-90.png?generation=1563261699861169\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdu_5gVOHrgmW8T3n%2F67-91.png?generation=1563261703077786\&alt=media)

Напомним, что мы можем отлично отладить этот эксплойт в пользовательском режиме, но на шелл-код, который вызывается из ядра, мы не сможем поставить **BP** или что-либо еще, потому что это вызовет исключение **INT3** в ядре, которое не обрабатывается как в пользовательском режиме, и будет создан **BSOD**.

Если мы запустим файл без аргументов, он покажет нам опции.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdu_EIzMdFPnEeVVW%2F67-92.png?generation=1563261701482946\&alt=media)

Я запускаю эксплойт с аргументами **-G**, чтобы задействовать уязвимость **STACK OVERFLOW GS**,

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdu_LKdvuRVhD334j%2F67-93.png?generation=1563261700653510\&alt=media)

Теперь я ожидаю.

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

Так что я могу теперь прикрепить **IDA**, ту где я реверсил эксплойт (не ту, которой был проанализирован драйвер)

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

Нажав клавишу в целевой машине, чтобы пропустить паузу, мы останавливаемся на **BP**, который я ставлю после паузы.

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

Я дохожу до функции **CREATEFILEMAPPING**.

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

Пройдя вызов с помощью **F8**, мне возвращается дескриптор файла.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdu_zXrgeJ6Ymx57p%2F67-98.png?generation=1563261698133701\&alt=media)

Как мы уже говорили, этот дескриптор передается в регистре **ESI**.

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

Здесь нам вернется адрес отображаемого файла.

![0.png](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdua7T9aJTUiwQiGe%2F67-100.png?generation=1563261698316845\&alt=media)

Это секция будет из **0x1000** байт.

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

Я поставлю эту **IDA** на паузу на одну минуту и открою другую, где у меня есть драйвер.

Одна вещь, которую я не видел и допустил ошибку - это то, что буфер назначения

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

Мы видим, что он инициализируется байтами **0x1FF**, но непосредственно перед обнулением байта, который находится чуть выше, и место назначения начинается с **VAR\_21C**, поэтому вам нужно исправить буфер назначения, чтобы иметь возможность хорошо вычислять размер, и теперь начинать с **VAR\_0x21C**, и он будет равен **0x200** байт.

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

Теперь, если всё в порядке, я переименую его в **BUFFER\_DESTINO**.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduaNFlneG1_wo-Ii%2F67-103.png?generation=1563261701017336\&alt=media)

Очевидно, что мы не должны копировать с начала секции файлового отображения, потому что данные должны быть копированы только до **SEH**. Я должен увидеть, сколько байтов я должен скопировать.

Мы должны скопировать **0x200** байт, чтобы заполнить буфер. Еще **4**, чтобы перезаписать **COOKIE**, а затем ещё идёт структура **MS\_EXC**.

Внутри структуры есть **8** байтов, а затем **NEXT** и **SEH**, поэтому было бы так.

Всего cкопировано = **0x200 + 4 + 8 + NEXT + SEH**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduaSHhBpvgnY1wlt%2F67-104.png?generation=1563261697249462\&alt=media)

Т.е. **0x214** байтами мы перезаписываем **SEH**.

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

Поскольку длина секции составляет **0x1000** байт, чтобы узнать, какое адрес передать, чтобы начать копирование, в начальный адрес секции я добавляю **0x1000**, а затем вычитаю **0x214**. При этом программа будет использовать этот новый адрес в качестве входного буфера, просто, чтобы перезаписать **SEH** и вызвать сбой при чтении.

Давайте посмотрим на это в отладчике, который был остановлен на эксплойте.

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

Мы видим, что адрес файлового отображения, хранится в регистре **ESI** и к нему добавляется значение **0xDEC**. Т.е. **0x1000** – **0x214 = 0xDEC**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtduadUTbr-7Vpno77%2F67-107.png?generation=1563261697429158\&alt=media)

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

На моей машине **0x2C0DEC** будет адресом, с которого начнется копирование **0x214** байт. Источник функции **MEMCPY** в стек.

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

С помощью функции **MEMSET** заполняется вcя секция буквами **A** (**0x41**)

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

Здесь заполняется входной буфер.

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

Мы видим, что в позицию **0x0204** записывается значение **0x42424242**. Это предположительно говорит о том, что программа перезаписала **COOKIE**, так как буфер занимает **0x200**, а **COOKIE**находится ниже. Для меня, так как это значение **0x204**, перезаписывается **DWORD** чуть ниже **COOKIE** - первое поле структуры **MS\_EXC**.

Затем программа записывает по адресу **ESI** + **4** значение **0x43434343**.

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

Затем добавляет значение **8** к исходному регистру **ESI** и записывает **NEXT** и **SEH**.

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

Мы видим, что, как я уже сказал, **COOKIE** не перезаписался значением **0x41414141**, и я затер чуть ниже **4 DWORD** структуры **MS\_EXC**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdubt-e6FSnMLnm4p%2F67-128.png?generation=1563261701737329\&alt=media)

Это **4 DWORD** которые я перезаписал, поэтому последний **DWORD -** это **SEH**.

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

Чуть ниже **SEH** заканчивается секция. Поскольку мы хотим вызвать сбой при чтении мы продолжим чтение данных. Мы передадим размер немного больше, чем **0x214**.

Я устанавливаю **BP** перед функцией **DEVICEIOCONTROL**, и когда я нажимаю **RUN**, мне нужно нажать клавишу в целевой маишине, чтобы пройти следующую системную паузу.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdubAFSPplZ0udQx9%2F67-115.png?generation=1563261698258526\&alt=media)

Давайте посмотрим аргументы, которые передаются функции.

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

Указатель на возвращенные байты передаются с помощью инструкции **LEA**. Затем идет **PUSH 0** и **PUSH 0** для выходного буфера. Его размер не имеет значения. Затем мы видим, что количество байтов, которые мы передает функции, чтобы она скопировала из входного буфера, равно **0x218** или на **4** байт больше, чем длина входного буфера, который был равен **0x214**. Это приведет к сбою при чтении в конце источника.

Адрес входного буфера был оставлен в регистре **EDI**.

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

И затем передается код **IOCTL 0x222007** от этой ошибки **STACK OVERFLOW GS** и дескриптор устройства, который находится в регистре **EBX**.

Мы уже проанализировали эксплойт. Поэтому теперь мы можем закрыть его и присоединить **IDA** с анализом драйвера к **ЯДРУ** и посмотреть, как копируются данные.

Прежде чем прикрепить **IDA**, я поставлю **BP** в начале уязвимой функции.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdubNgb9T0vqRYjE7%2F67-118.png?generation=1563261698507789\&alt=media)

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

Готово. **IDA** уже обнаружила, что это тот же файл, который я проанализировал, и если я соглашусь и перемещу базу секции, **IDA** скажет, что это тот же файл.

Я запускаю эксплойт на целевой машине.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdubUQoEemPL0bfzH%2F67-120.png?generation=1563261701251739\&alt=media)

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

Мы останавливаемся на **BP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdub_BHG186c3CCHW%2F67-122.png?generation=1563261699207426\&alt=media)

Как мы уже говорили, будут скопированы **NEXT** и **SEH**, которые мы должны будем перезаписать позже в функции **MEMCPY**.

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

Потому что, когда мы нажимаем **RUN**, мы будем копировать данные и продолжим, не имея возможности остановить этот процесс. Мы можем установить **BPM ON WRITE**, чтобы остановить отладчик, когда скопируется **NEXT** прямо перед сбоем. Поэтому мы посмотрим, все ли в порядке.

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

Я вставил это в панель **WINDBG**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdubkhipWpaS_rQ5y%2F67-125.png?generation=1563261699196806\&alt=media)

Я создаю сегмент и преобразовываю его в код.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdubnb3v6fZFJeXI2%2F67-126.png?generation=1563261699907602\&alt=media)

Или если мне хочется посмотреть на сегмент в панели **WINDBG**, я делаю так.

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

Напомним, что когда я armada источник мы помещаем значение **0x44444444**, чтобы перезаписать значение **NEXT**.

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

Это изображение выше было источником. Давайте посмотрим, хорошо ли оно перезаписано в стеке.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdubwRDvp34BY4fMK%2F67-129.png?generation=1563261701811921\&alt=media)

Вот оно. Я останавливаюсь на **BPM ON WRITE** сразу после копирования **NEXT**, и теперь я скопирую **SEH**. Я нажимаю **F7**.

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

Сюда я скопирую наш **SEH**.

Также я могу посмотреть на него в **IDA**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtduc1ZIqxUiCO2VKo%2F67-131.png?generation=1563261699632180\&alt=media)

Конечно, модуль эксплойта, куда будет переходить отладчик, скомпилирован без **DEP** и без **SAFE SEH**, поскольку это является частью эксплуатации. Если бы он был создан с **PYTHON**, проблем не было бы. Вам нужно было бы создать область памяти, которая позволила бы ему работать с функцией **VIRTUALALLOC**, скопировать туда код и указать адрес этой области как **SEH**.

Давайте не будем забывать, что это **PRIVILEGE ESCALATION**, поэтому у нас уже есть выполнение кода на машине, но с обычным пользователем. Идея состоит в том, чтобы масштабироваться до прав **SYSTEM**, чтобы мы могли выполнять действия на компьютере, ограниченные нашими привилегиями, но запускать **EXE** с теми же привилегией. Также, если бы это был **PYTHON**, мы должны установить **PYTHON** для запуска **.PY**.

Давайте посмотрим на процедуру обработчика исключений.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtduc40nM4RxOdUIcv%2F67-132.png?generation=1563261702299484\&alt=media)

Я уже создал сегмент, я преобразовал его в код с **C**, и я создал функцию.

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

Здесь я не могу поставить **BP** в отладчике в пользовательском режиме на целевой машине, но могу сделать так.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtducAzU-0qSrFWBmi%2F67-134.png?generation=1563261699851335\&alt=media)

Я помещаю эту команду в **WINDBG**. Затем я нажимаю **RUN**.

Отладчик остановился здесь. Наш обработчик исключений работает.

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

Конечно, этот код - это шелл-код который называется как **TOKEN STEALER**, который уже был проанализирован в предыдущих туториалах.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtducESM5Z8BBLOTHt%2F67-136.png?generation=1563261698034258\&alt=media)

В регистр **EDX** вы должны поместить регистр **EIP**, куда программа вернетесь, когда вернетесь в пользовательский режим, а в регистр **ECX** - регистр **ESP**. В моем случае, поскольку файл компилирован без **ASLR**, я помещаю в регистр **EDX** адрес чуть ниже вызова **DEVICEIOCONTROL**, а в регистр **ESP** адрес основания стека **0x12FF00**, который не совпадает со значением, которое выполнялось до вызова функции **DEVICEIOCONTROL**, но, поскольку я сохранил адрес в секции данных в регистре **ESP**, которое у меня был, когда я вернусь, я смогу восстановить правильный регистр **ESP**.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtducH7ImCIDvwa98D%2F67-137.png?generation=1563261700923628\&alt=media)

В текущей **IDA**, в которой я отлаживаю, я вижу ту же часть кода.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtducJxb0ZjMBE1OcP%2F67-138.png?generation=1563261698997778\&alt=media)

Я могу поставить здесь **BP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtducLiQPOz9b03x_q%2F67-139.png?generation=1563261700407737\&alt=media)

Я удаляю предыдущие **BP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtducNWeXKSq_7qW6X%2F67-140.png?generation=1563261700122782\&alt=media)

И нажимаю **RUN**.

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

Я вижу, что программа вернулась в режим пользователя с регистрами **EIP** и **ESP**, которые я установил до вызова **SYSEXIT**.

Здесь восстанавливается регистр **ESP**. Идет чтение с того места, где вы его сохранили, в секции данных **0x4212B0**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtducRpmGxus04-a_R%2F67-142.png?generation=1563261701814985\&alt=media)

Теперь я буду выполнять калькулятор или код, который я хочу, с привилегиями **SYSTEM**. Я мог бы, например, инжектировать код в какой-нибудь процесс **SYSTEM**, и выйти.

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

Я удаляю все **BP** и нажимаю **RUN**.

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

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

Давайте посмотрим, какой пользователь является владельцем.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtducZNTmgCmZyXJxn%2F67-146.png?generation=1563261697731070\&alt=media)

Готово. Я закончил. Я могу повышать привилегии до **SYSTEM**.

Я приложил **ZIP** файл с измененным исходным кодом и скомпилированным исполняемым файлом. Помните, что если вы скомпилируете его самостоятельно, вы должны сделать это без **DEP**, без **SAFESEH** и без **ASLR**, и он будет работать только в **32**-разрядной версии **WINDOWS** 7 и отрегулировать.
