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

# Часть 54

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

Мы собираемся немного изменить предыдущее упражнение, а также сделаем программу для пользовательского режима, прямо в **PYTHON**.

Для этого, на целевой машине, где запущен драйвер, мы должны установить **PYTHON**. Я установил версию **2.7**, а также загрузил инсталлятор **PYWIN32**, который соответствует моей версии **PYTHON**.

[https://sourceforge.net/projects/pywin32/files/pywin32/Build 214/](https://sourceforge.net/projects/pywin32/files/pywin32/Build%20214/)

Поскольку моя версия **PYTHON** равна **2.7**, то скачайте этот файл.

![](/files/-LkxkWNpmdOGykRkG7Vh)

Это инсталлятор. Запускаем его и он устанавливается. С этой программой мы сможем запустить скрипт **PYTHON**, который заменит предыдущую пользовательскую программу.

Мы видим, что у драйвера теперь есть еще два кода **IOCTL**.

![](/files/-LkxkWOaMR4DM8mFGFEh)

В дополнение к коду **IOCTL\_SAYHELLO**, который у нас уже был, теперь есть два новых: код **IOCTL\_HOOK** и код **IOCTL\_UNHOOK**.

![](/files/-LjrT8MzfiJwvVAmeqTd)

Мы видим, что внутри **CASE**, когда **MAJORFUNCTION** равен **IRP\_MJ\_DEVICE\_CONTROL**, есть еще один переключатель, который имеет три **CASE IOCTL**.

Мы видим, что код **IOCTL**, который мы имели раньше, все еще печатает только фразу "**HELLO WORLD**"

case IOCTL\_SAYHELLO: DbgPrint("Hello World!\n"); status = STATUS\_SUCCESS; break;

Давайте посмотрим другие два.

case IOCTL\_HOOK: PsSetCreateProcessNotifyRoutine( DriverProcessNotifyRoutine, FALSE); break; case IOCTL\_UNHOOK: PsSetCreateProcessNotifyRoutine( DriverProcessNotifyRoutine, TRUE); break;

Мы видим, что драйвер использует функцию **PSSETCREATEPROCESSNOTIFYROUTINE**

![](/files/-LkxkWPZ8Ci-UHhPt5qH)

Эта функция позволяет нам добавить **CALLBACK**, т.е. свою собственную функцию, которая будет срабатывать каждый раз, когда система запускает или останавливает программу, передавая ей для активации второй аргумент **FALSE**, а в первый аргумент адрес функции, в которую будет переходить драйвер.

Наша функция, в которую будет переходить драйвер, называется **DRIVERPROCESSNOTIFYROUTINE**, и если условие **CREATE** истинно, драйвер печатает, что создан новый процесс, **PID** родительского процесса, который его создал, и сам **ID** процесса.

VOID DriverProcessNotifyRoutine( IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create) { if (Create) { DbgPrint("Process %d created process %d\n", ParentId, ProcessId); } else { DbgPrint("Process %d has ended\n", ProcessId); } }

И когда процесс завершается, так как условие **CREATE** будет ложным, драйвер напечатает, что процесс завершился и его **PID**.

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

case IOCTL\_UNHOOK: PsSetCreateProcessNotifyRoutine( DriverProcessNotifyRoutine, TRUE); break;

Второй аргумент установленный в **TRUE** отключает функцию - и система продолжает работать нормально.

Хорошо. Исходный код драйвера будет доступен во вложении. Помните, что если вы скомпилируете его в **VISUAL STUDIO**, вы должны изменить **НАСТРОЙКИ** в **WINDOWS** 7 и свойства **DESKTOP**, а также снизить уровень строгости ошибок с **4** уровня до **1** или **2**.

Хорошо. Теперь идет скрипт **PYTHON**, который отправит **IOCTL** драйверу, когда тот будет запущен.

![](/files/-LjrT8NX4dTkK-4Dr_VA)

Мы видим, что это небольшой скрипт. Вам нужно импортировать модули **WIN32API** и **WIN32FILE**, в дополнение к **WINIOCTLCON**. Всё это входит в пакет **PYWIN32**, который мы установили. Если вы его не установили, это даст вам ошибку.

IOCTL\_HOOK =winioctlcon.CTL\_CODE( FILE\_DEVICE\_HELLOWORLD, 0x01, METHOD\_BUFFERED, FILE\_ANY\_ACCESS )

IOCTL\_UNHOOK =winioctlcon.CTL\_CODE( FILE\_DEVICE\_HELLOWORLD, 0x02, METHOD\_BUFFERED, FILE\_ANY\_ACCESS )

IOCTL\_SAYHELLO=winioctlcon.CTL\_CODE( FILE\_DEVICE\_HELLOWORLD, 0x00, METHOD\_BUFFERED, FILE\_ANY\_ACCESS )

Мы видим, что функция **CTL\_CODE**, которую мы используем, когда мы создали исполняемый файл на C++, чтобы найти **IOCTL**. В **PYTHON** импортирует их из модуля **WINIOCTLCON**. Мы сможем найти три **IOCTL**.

Затем у нас идёт вызов функции **CREATEFILE**.

hDevice = win32file.CreateFile(**r"\\.\HelloWorld"**,win32file.GENERIC\_READ | win32file.GENERIC\_WRITE, 0, None,win32file.OPEN\_EXISTING, win32file.FILE\_ATTRIBUTE\_NORMAL, 0)

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

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

> **while** 1:
>
> **print "1=HELLO\n"\*\***,"2=HOOK\n"**,"3=UNHOOK\n"**,"0=UNHOOK AND EXIT\n"\*\*
>
> case=raw\_input()
>
> **if** case ==0:
>
> **break**
>
> **if** case==1:
>
> win32file.DeviceIoControl(hDevice,IOCTL\_SAYHELLO, None, None, None)
>
> **if** case == 2:
>
> win32file.DeviceIoControl(hDevice,IOCTL\_HOOK, None, None, None)
>
> **if** case == 3:
>
> win32file.DeviceIoControl(hDevice,IOCTL\_UNHOOK, None, None, None)
>
> win32file.DeviceIoControl(hDevice,IOCTL\_UNHOOK, None, None, None)
>
> win32file.CloseHandle(hDevice)

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

![](/files/-LjrT8NiY7yOAkrEqnTT)

Я запускаю целевую систему и запускаю драйвер с помощью **OSRLOADER**, и оставляю его запущенным. Теперь я буду использовать скрипт **PYTHON**, чтобы узнать, работает ли он.

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

![](/files/-LjrT8No-raV0JeOMekB)

Если я нажму **1**, то ничего не происходит. Что же произошло?

```
case=raw_input()
1
case
type(case)

Out[6]: str
```

Ааа. Результат **RAW\_INPUT** - это строка, и мы сравниваем ее с целым числом. Давайте изменим это.

![](/files/-LjrT8Nvz88IUrLcfdyi)

Посмотрим сейчас.

![](/files/-LjrT8O0vhUr2hYv9O0T)

Теперь всё работает. Когда мы нажимаем **1**, нам показывается перехваченная фраза "**HELLO WORLD**". Сейчас я нажимаю **2**.

![](/files/-LjrT8O8zaYkC4FKnf9L)

Теперь позапускаем некоторые программы в машине.

![](/files/-LjrT8OGbCt1t37XTeb_)

Мы видим, как драйвер логирует процессы, которые запускаются и закрываются. В моем случае, запускается **INTERNET EXPLORER**.

![](/files/-LkxkWUYxToEkIKXtRhg)

**PID IE** равен **4084**, а родителем является – **EXPLORER**. При запуске двойным щелчком, любой процесс, который запускается на машине или останавливается будет логироваться. Теперь я закрываю **IE**.

![](/files/-LkxkWUrABGTi5kXagvw)

Хорошо. Всё работает. Теперь выключим перехват через пункт **3**. Мы видим, что процессы, которые мы открываем и закрываем, больше не регистрируются.

Что касается реверсинга, то это похоже на предыдущий случай.

![](/files/-LkxkWVZKmAcWMcslYG4)

В обработчике мы видим, что в этом случае регистр **EDI**, равен **IRP** + **0x60**. Он будет иметь адрес структуры **\_IO\_STACK\_LOCATION**. Кроме того, поставим там **BP**. Как только мы синхронизируем необходимые структуры в **LOCAL TYPES**, нам покажут, что это поле **MAJORFUNCTION**.

![](/files/-LkxkWVzmrdbbKOju8GA)

В случае, когда **MAJORFUNCTION** равно **0xE**, другими словами, когда мы используем **DEVICEIOCONTROL**. Мы нажимаем **T** и из всех опций, которые есть, мы выбираем, те для которых используется **DEVICEIOCONTROL**.

![](/files/-LjrT8OuVE7OivxfasHD)

Мы видим, что когда код равен **IOCTL\_SAYHELLO**, драйвер переходит к желтому блоку, который напечатает **HELLO WORLD**. В двух других случаях он идёт в зеленые блоки. В случае **IOCTL\_HOOK** выполняется инструкция **PUSH ESI**, регистр которой равен нулю, чтобы передать аргумент **FALSE** в **API** [**PSSETCREATEPROCESSNOTIFYROUTINE@8**](mailto:PSSETCREATEPROCESSNOTIFYROUTINE@8), а в случае **IOCTL\_UNHOOK** исполняет инструкцию **PUSH 1**, что является **TRUE**.

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

![](/files/-LjrT8P1RfYzOfGXiPBv)

Если мы сделаем щелчок здесь, мы перейдём к этой функции.

![](/files/-LjrT8P6I7XMmBmIZJ9I)

Здесь мы видим, если переменная **CREATE** ложная, т.е. равна нулю, драйвер переходит в **PROCESS (PID) HAS ENDED**, а если переменная истинна, то переходит в **ROCESS (PID) CREATED PROCESS(PID)**

Если мы поставим **BP** здесь, драйвер будет останавливаться каждый раз, когда мы запускам процесс, после того, как я нажму **2** в скрипте **PYTHON** для **ПЕРЕХВАТА**.

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

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

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

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

26.10.2018

[**Источник: ricardonarvaja.info**](http://ricardonarvaja.info/WEB/IDA%20DESDE%20CERO/CURSO%20DE%20IDA%20TUTES/54-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-54.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.
