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

# Часть 58

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

Хорошо. Нам осталось добавить сам шеллкод. Это типичный шеллкод, который крадет токен процесса **SYSTEM** и копирует его в наш процесс. Он очень короткий. Но стоит его хорошо проанализировать.

```python
shellcode="\x53\x56\x57\x60\x33\xC0\x64\x8B\x80\x24\x01\x00\x00\x8B\x40\x50\x8B\xC8\xBA\x04\x00\x00\x00\x8B\x80\xB8\x00\x00\x00\x2D\xB8\x00\x00\x00\x39\x90\xB4\x00\x00\x00\x75\xED\x8B\x90\xF8\x00\x00\x00\x89\x91\xF8\x00\x00\x00\x61\x33\xC0\x83\xC4\x0C\x5D\xC2\x08\x00"
```

Шеллкод - довольно общий. То, что нужно знать про шеллкод, состоит в том, что когда он завершается, он возвращается к процедуре откуда он был вызван. Для этого нужно внимательно посмотреть. Последняя инструкция **RETN** должна быть **RETN 4** или больше, чтобы вернуться туда куда нужно. Если бы мы не перезаписали **RET** случилось бы переполнение и программа продолжила работу. Иначе будет **BSOD** и чао-какао.

![](/files/-LjrT8mX5zOi49ITHSKV)

Здесь мы видим, как я разместил шеллкод. В начале данных, которые я пересылаю, я размещаю шеллкод и затем вычитаю **820** байт из длины этого же самого шеллкода для того, чтобы он не изменил положение значения, которым я перезаписываю адрес возврата в дальнейшем и сохраняю его правильным.

Если бы я запустил скрипт, прежде чем объяснять вам всё это, мы бы увидели, что я поместил вызов **RAW\_INPUT** в конец скрипта, чтобы остановить его до того, как он закроется, и посмотрим, смогу ли я повысить системные привилегии. Вы также можете запустить другой процесс и увидеть, есть ли у этого процесса системные привилегии, что может произойти только в том случае, если один системный процесс запускается другим.

![](/files/-LjrT8mkh_uk4YKWwPp4)

Здесь я запустил скрипт. Я вижу, что скрипт остановился на вызове **RAW\_INPUT**. Давайте посмотрим в **PROCESS EXPLORER**. Добавим столбец, который показывает текущего пользователя, который говорит нам следующее

![](/files/-LjrT8n3yVIEgSsM64Ow)

Мы работали над преобразованием процесса с привилегиями обычного пользователя в **SYSTEM**. Давайте посмотрим, как мы это сделали. Присоединим **IDA** и остановимся на инструкции **RET** перед выполнением шеллкода.

![](/files/-Ljtu3sibmGAzgN0rN_u)

Здесь код остановился у инструкции **RET**. Мы трассируем один раз с помощью **F7**.

![](/files/-LjrT8nLZYZhSXkg0vhT)

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

С помощью **P** мы можем создать функцию **CREATE FUNCTION** и преобразить её в графическую форму с помощью пробела.

![](/files/-Ljtu3t9gzWBA3-Vt1nU)

После инструкции **PUSHA**, которая сохраняет регистры в стеке, мы видим, что, поскольку **EAX** равно **0** из-за инструкции **XOR** и программа заканчивает чтение значения регистра **FS:\[124]**

Хорошо. Каждый процесс имеет **TEB** или **TIB**.

<https://es.wikipedia.org/wiki/Win32_Thread_Information_Block>

В вычислительной технике, **WIN32 THREAD INFORMATION BLOCK (TIB)** эта структура данных в системах **WIN32**, особенно в архитектуре **X86**, которая хранит информацию о потоке, который выполняется. Также она известна как **THREAD ENVIRONMENT BLOCK (TEB)**.

Хорошо. Эта структура имеет поля, к которым обращается через регистр **FS:\[x]**. Здесь в таблице мы видим, например, **FS:\[124]**

![](/files/-LjrT8nZiPeWCYQ4WwI0)

Также, широко используется указатель на **PEB**, что расшифровывается как **PROCESS ENVIRONMENT BLOCK**, который находится в **FS:\[30]**

![](/files/-LjrT8ndnAE_mqJDtmX3)

В **WINDBG** вы можете увидеть эту структуру.

![](/files/-LjrT8nlGUTVMDKpO_uS)

Хотя смещение **0x124** не показывается нам даже если мы придадим структуре большую глубину. Как мы видели, это структура **ETHREAD**.

![](/files/-LjrT8nw33Azeumi6VSz)

Как и в позиции **0,** это структура **KTHREAD** или **KERNEL THREAD**. Это означает, что поле **50**, которое программа ищет дальше внутри структуры **ETHREAD**, будет находиться внутри **KTHREAD**, потому что последняя имеет размер **0x200**.

![](/files/-Ljtu3u0LtMrrnad0EmP)

![](/files/-Ljtu3uFcXDQ1iyFPSL9)

Мы видим, что поле **0x50** не показывается нам. Оно находится внутри структуры **\_KAPC\_STATE** которая находится по смещению **0x40**.

Посмотрим её. По смещению **0x10** это **\_KPROCESS**.

![](/files/-Ljtu3u_LMQPXxxba5qE)

Если мы читаем это значение, и передаем его в регистр **EAX**, мы видим, что это знаменитый **EPROCESS** или **KPROCESS** - то же самое? Нет, но почти.

![](/files/-Ljtu3uiqCRFJSb9WTQu)

Мы видим, что **KPROCESS** находится в поле **0 EPROCESS**, так что всё нормально, адрес совпадает. Если начиная с этого значения, сумма смещения меньше чем **0x98**, это будет **KPROCESS** и находится внутри этого. Если сумма больше **0x98**, это будет в оставшейся части структуры **EPROCESS**.

![](/files/-Ljtu3upe7n2hsNum2VM)

Мы видим, что программа читает поле **0xB8**, поэтому мы уже вышли из структуры **KPROCESS** и находимся внутри **EPROCESS**.

![](/files/-Ljtu3uzqTFeQdEhUHXe)

Программа читает знаменитую **ACTIVEPROCESSLINKS**.

Как и в предыдущем упражнении, я собрал структуру **EPROCESS**, которая была неполной, но она работает.

![](/files/-LjrT8onGVVRvA-UQVFj)

Через меню **FILE → LOAD FILE → PARSE C HEADER FILE** я ищу структуру и добавляю её.

![](/files/-Ljtu3vGlI9qAub0OvWD)

Я помечаю её через **LOCAL TYPES** и экспортирую её в файл **C HEADER**

![](/files/-Ljtu3vQkX25Coyy1z2T)

Теперь происходит синхронизация.

![](/files/-LjrT8p31qpXezZ9G-68)

![](/files/-Ljtu3voHsq8LkuTZk_c)

Я нажимаю **T** и ищу структуру. И это наш **FLINK**. Другими словами, он указывает на **ACTIVEPROCESSLINK** следующего процесса, так как он находится по смещению **0xB8**. Программа вычитает эту константу, чтобы найти **EPROCESS** следующего процесса.

![](/files/-Ljtu3w0QBqQGcGScSv9)

В регистре **EAX** должен быть указатель на **EPROCESS** следующего процесса.

![](/files/-LjrT8pK4j728PlUXzxO)

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

Мы видим, что программа сравнивает значение поля **0xB4** этого **EPROCESS** со значением **4**. Давайте посмотрим, что это смещение **0xB4**. Поэтому мы добавляем его в нашу структуру.

![](/files/-Ljtu3wJw9l4yWsv5of9)

![](/files/-LjrT8pYsCyqGsKZ4xRX)

То есть, программа замечает, что если **PID** равен **4**, это соответствует процессу **SYSTEM**.

Я добавлю поле в мою структуру. Программа не позволяет редактировать структуру, потому что я импортирую её, поэтому я добавил поле в **.H** файл, который я экспортировал.

![](/files/-Ljtu3w_t_WA5XM1VjKn)

Я повторно импортирую файл, не удаляя предыдущий, и добавляется недостающее поле.

![](/files/-Ljtu3wgQgbWMZUF2Z_7)

Я нахожусь здесь.

Мы видим, что значение не равно **4**, поэтому мы продолжаем трассировать. Конечно, всё начнется снова с первого процесса. Давайте посмотрим.

![](/files/-LjrT8pq2q-HW3esWeA-)

Здесь программа начинается с начала. В этом случае **PID** или **CID** равен **4** и соответствует процессу **SYSTEM**.

![](/files/-LjrT8pxUzyrpmm06M80)

Теперь если программа найдет **EPROCESS** процесса **SYSTEM**, она выйдет из цикла.

![](/files/-Ljtu3x3Dgc2hjUQZZ_c)

Мы видим, что программа читает поле **0xF8 EPROCESS** процесса **SYSTEM**. Давайте посмотрим, что там есть.

![](/files/-LjrT8qHkKPkLexGIoZP)

![](/files/-LjrT8qO9myckAt7JStO)

Хорошо. Программа копирует токен системы в наш **EPROCESS**. Он будет иметь привилегии **SYSTEM**, и вот что программа там делает. Читает токен **SYSTEM**.

![](/files/-Ljtu3xd7HBjdTYcCZ4D)

И поскольку регистр **ECX** имел наш **EPROCESS**, к нему добавляется значение **0xF8**, чтобы сохранить токен **SYSTEM** в нашем процессе.

![](/files/-Ljtu3xoD27lQ7aIpn7J)

Я могу добавить недостающее поле в **.H** файл и импортировать его снова. Нет необходимости удалять предыдущий.

![](/files/-Ljtu3y0_7UsDsVujm7V)

Помните, что значения являются токенами разных процессов. Регистр **EAX** указывает на **EPROCESS SYSTEM,** а **ECX** на наш **EPROCESS** из **PYTHON.EXE**.

С этим уже все работает как нужно. Давайте посмотрим, сможем ли мы с этим **RET** нормально вернутся обратно в программу и продолжить работу с драйвером.

![](/files/-LjrT8qsMvM1AJNbNgWo)

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

![](/files/-Ljtu3yHjxkrcT-Y06C5)

Я нажимаю **RUN** и остаюсь в ожидании функции **RAW\_INPUT**.

У меня сейчас нет **PROCESS EXPLORER**. Я закрыл его, чтобы он обновился.

![](/files/-Ljtu3yT0ermF6pQBKYr)

И у нас есть готовые права **SYSTEM**.

Я могу запустить калькулятор с правами **SYSTEM**.

![](/files/-Ljtu3yZg_R29_K_G0JH)

![](/files/-Ljtu3yj2tHFeK0RSylJ)

Готово. Мы достигли цели.

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

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

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

01.12.2018

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


---

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

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

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

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

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