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

# Часть 57

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

Хорошо. Мы будем пытаться эксплуатировать переполнение стека из скрипта **PYTHON**. Обычно эксплуатация ядра происходит локально. Другими словами, скрипт уже эксплуатирует некоторую программу, которая не имеет привилегий системы и хочет повысить привилегии и быть с правами **SYSTEM**, что устраняет ограничения, которые имеет эксплуатируемый процесс, который имеет только ограниченные привилегии обычного пользователя на машине.

Поэтому, за исключением очень редких исключений, эксплойты ядра - это эксплоиты для повышения привилегий или **PRIVILEDGE ESCALATION**.

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

В любом случае, как код в **C**, так и код на **PYTHON** основаны на вызовах одних и тех же **WINDOWS API**, таких, как **CREATEFILE**, **DEVICEIOCONTROL** и т.д. Поэтому, то, что делается на одном языке, легко переносится на другой.

Давайте напомним нашу модель **PYTHON** предыдущего примера.

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

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

Напомним, что имя генерируется здесь

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

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

Здесь драйвер возвращает **SYMBOLICNAME**, который приходит из строки, которая находится в **DEVICENAME**.

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

Без особых проблем, конечно, если я заменяю имя старого драйвера драйвером новым.

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

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

Этот драйвер запущен, и я запускаю скрипт.

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

Поскольку **SYMBOLICLINK** идет отсюда, имеет смысл использовать это имя.

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

Давайте попробуем так.

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

Мы видим, что всё работает.

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

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

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

На данный момент, мы удаляем **WHILE** и все остальное, что нас не интересует. Следующая вещь заключается в том, чтобы увидеть, какой именно **IOCTL** переносит нас в блок переполнение стека, чтобы отправить его.

Вопрос состоит в том, как добраться туда.

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

Мы видим, что драйвер идёт отсюда.

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

Регистр **EDX** имеет код **IOCTL**, который получается отсюда.

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

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

Давайте посмотрим, достигнет ли программа блока, где мы хотим присоединить **IDA** и устанавливаем **BP**.

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

Я запускаю драйвер на целевой машине и попадаю в **BP**.

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

Мы видим, что в регистр **EDX** драйвер считывает **IOCTL** код, который он передает.

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

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

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

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

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

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrSx7vPF_6hdeduZel%2F-LjrT48JAZg_3tn7-8oY%2F57-20.png?generation=1563225024522710\&alt=media)

Поскольку аргумент равен нулю, программа пропускает функцию, в которой происходит переполнение стека.

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

Поскольку **API** функция, вызывается из **WIN32FILE** в **PYTHON**, она имеет меньше аргументов, чем исходная функция, которая имеет больше.

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

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

Здесь находится определение **WIN32FILE PYTHON**.

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

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

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

Поскольку библиотека **WIN32FILE** не имеет доступа ко всем **API**, она не позволяет копировать непосредственно в буфер как функция **MEMCPY** или что-то вроде этого, поэтому мы можем копировать его только с помощью функции **READFILE**, поэтому мы делаем файл **PEPE.BIN**, заполняя его **0x1000** буквами **A**. Мы передаем файл в функцию **CREATEFILE**, чтобы она открывала его и вернула нам дескриптор, и мы передали его в функцию **READFILE** с аргументом **BUF** буфера, который мы выделяем и копировать содержимое файла туда.

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

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

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

Мы замечаем, что с начала буфера до адреса возврата получается **520** десятичных байт \* **4** размер элемента.

Поэтому

```python
hex(520*4) = '0x820'
```

Поэтому мы должны отправить **0x820** + **RET**.

Сейчас, поскольку мы знаем в **PYTHON** адрес буфера, который мы создаем, чтобы передавать его, мы будем использовать грязный трюк - **REPR**.

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

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

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

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

Здесь cуществует адрес, который мы можем передать с помощью **STRUCT.PACK** после **0x820 A**. Досадно, что мы должны записать их в файл, который читается.

Следовательно, как только у меня есть адрес буфер.

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

Я пишу в файл **ФРУКТЫ**, которые хочу отправить.

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

Перед функцией **READFILE** скопируем их в буфер.

Давайте посмотрим, заработает ли это. В этом случае нет необходимости иметь файл, потому что он будет создан и заполнен, поэтому мы удалили предыдущий.

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

Для этого мы изменили аргумент на **CREATE ALWAYS**.

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

Хорошо. Предположительно здесь - наш буфер с буквами **A**. **IDA** остановлена. Давайте посмотрим, что я передаю.

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

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

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

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

Он не заполнился буквами A. Давайте пропустим эксплуатацию и давайте исправим скрипт.

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

Я меняю **EIP** здесь с помощью правой кнопки и **SET IP** и нажимаю **RUN**.

Я думаю, что проблема в том, что размер буфера должен соответствовать размеру файла.

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

Давайте сделаем так.

Ах, уже упал.

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

Скрипту не хватало установки указателя файла в начале файла. Он читал файл с конца, где я оставил **WRITEFILE**, поэтому я не читал **A**. Теперь всё работает.

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

Я трассирую до **MEMCPY**.

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

Я добираюсь до **RET**.

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

Я продолжаю с помощью **F7**.

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

Я вижу, что я попал в буфер. Проблема состоит в том, что, поскольку я не выделил его с помощью **VIRTUALALLOC**, а выделяю его с помощью **API ALLOCATEREADBUFFER**, **WIN32FILE** у него нет прав на выполнение. Поэтому мне придется найти способ выделить исполняемый код другим способом.

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

Я добавил библиотеку **CTYPES**, и у неё есть функция **VIRTUALPROTECT**, поэтому я дал ей права на выполнение, и теперь у нас нет проблем.

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

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

Версия c **CTYPES** – это так

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

Библиотека использует напрямую функции **CREATEFILE**, **VIRTUALALLOC**, **RTLMOVENEMORY** и **DEVICEIOCONTROL**. Вам просто нужно быть осторожным с одним из типов, но она работает хорошо.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrSx7vPF_6hdeduZel%2F-LjrT4BQpRgA-6R0snoc%2F57-47.png?generation=1563225009063617\&alt=media)

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

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

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

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

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

03.11.2018

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