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

# Часть 52

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

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

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

Чтобы получать информацию из пользовательского режима, мы должны научить наш драйвер отвечать на входные и выходные управляющие коды устройства (**IOCTL**), которые могут быть доставляться из пользовательского режима используя **API DEVICEIOCONTROL**. Мы уже видели, как наш драйвер может изменить процедуру загрузки, используя структуру **DRIVER\_OBJECT** и изменять указатель, который там храниться. Обработка **IOCTL** очень похожа. Нам просто нужно подготовить еще несколько процедур.

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

Первое, что мы должны сделать в нашей точке входа - создать **DEVICE OBJECT**.

Я не буду объяснять всю теорию об этом. Кто хочет узнать больше, почитайте это:

<https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-device-objects>

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

И это должно быть так. В нашем первом драйвере, мы могли только запускать и останавливать его и не могли получать управляющие команды из пользовательского режима. Поэтому теперь мы должны создать **DEVICE OBJECT**, используя **API IOCREATEDEVICE**.

Функция, которую вызывает наша **DRIVERENTRY**, аналогична

`status = IoCreateDevice(DriverObject,0,&deviceNameUnicodeString,FILE_DEVICE_HELLOWORLD, 0,TRUE,&interfaceDevice);`

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

**Parameters**

> **DriverObject \[in]**
>
> Pointer to the driver object for the caller. Each driver receives a pointer to its driver object in a parameter to its [DriverEntry](https://msdn.microsoft.com/es-es/library/windows/hardware/ff544113) routine.

`NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)`

Как мы увидели, **DRIVERENTRY** получает два аргумента. Первый - указатель на структуру **DRIVER OBJECT**, которая передается в качестве первого аргумента функции **IOCREATEDEVICE**.

> **DeviceName \[in, optional]**
>
> Optionally points to a buffer containing a null-terminated Unicode string that names the device object.
>
> WCHAR deviceNameBuffer\[] = L"\Device\HelloWorld";
>
> UNICODE\_STRING deviceNameUnicodeString;

В нашем коде **DEVICENAME** соответствует имени устройства, а затем копируется в переменную **DEVICENAMEUNICODESTRING**, который передается как аргумент **API**.

> **DeviceType \[in]**
>
> Specifies one of the system-defined FILE\_DEVICE\_XXX constants that indicate the type of device (such as FILE\_DEVICE\_DISK or FILE\_DEVICE\_KEYBOARD) or a vendor-defined value for a new type of device.

В нашем случае, это значение, определяется нами в начале кода.

`#define FILE\_DEVICE\_HELLOWORLD 0x00008337`

> **DeviceObject \[out]**
>
> Pointer to a variable that receives a pointer to the newly created [DEVICE\_OBJECT](https://msdn.microsoft.com/es-es/library/windows/hardware/ff543147) structure. TheDEVICE\_OBJECT structure is allocated from nonpaged pool.

Это указатель на **DWORD**, где **API** будет содержать указатель. Поэтому система говорит, что **OUT** – используется для выходного параметра.

Это самые важные функции. Давайте теперь посмотрим на код в **IDA,** теперь, когда мы знаем эти **API**.

Мы видим, что функция, которая вызывает наш **DRIVERENTRY**, аналогична

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

Давайте посмотрим на часть нашего кода.

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

Функция начинается с тех же двух указателей на структуры типа **\_DRIVER\_OBJECT** и **\_UNICODE\_STRING**.

Остальные - это переменные. Поскольку у нас есть символы, это не очень сложный случай. Но хорошо понемногу привыкать к реальным случаям, когда у нас нет символов.

В переменную **VAR\_4** сохраняется **COOKIE** для защиты стека.

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

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

Здесь программа копирует имя устройства **UNICODE** размером **9 DWORD** (**0x24** байта) в назначение, которым является переменная **DEVICENAMEBUFFER**, длина которой составляет **19 WORDS**, т.е. **19** \* **2**, всего **38** байт в десятичном формате или **0x26** байт в шестнадцатеричном, поэтому всё, что копируется, намного меньше, чем буфер.

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

```
Python>hex(0x19 * 2)
0x32
```

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

Затем копируется **DOS\_DEVICE\_NAME** размером **0xB DWORDS,** т.е. **0xB** \* **4** - это **0x2C** байт в шестнадцатеричной системе в общей сложности

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

И буфер назначения это **DEVICELINKBUFFER**. Давайте посмотрим его длину.

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

Это **23** \* **2** в десятичной системе, т.е. **46** байт, т.е **0x2E** в шестнадцатеричной системе, так что здесь тоже нет переполнения.

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

Проблема в том, что в **DEVICENAMEBUFFER** находится имя устройства, а в **DEVICELINKBUFFER** - имя устройства **DOS**.

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

Затем идёт вызов функции **DBGPRINT**, которая печатает сообщение "**DRIVERENTRY CALLED**".

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

Давайте продолжим со следующего: преобразуем строку **UNICODE** в ту, которая имеет тип **\_UNICODE\_STRING**. Для этого существует следующий **API RTLINITUNICODESTRING**.

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

У нас есть вызов в **RTLINITUNICODESTRING**

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

> WCHAR deviceNameBuffer\[] = L"\Device\HelloWorld";

Источник **DEVICENAMEBUFFER** является указателем на буфер, который имеет строку юникода, а назначение - указатель на структуру **UNICODE\_STRING**. Эта структура, которую мы уже видели, имеет три поля, два слова (**LENGHT** и **MAXIMUMLENGHT**, а третья должна быть указателем на строку юникода.

Это означает, что **API** скопирует адрес этого исходного буфера в третье поле структуры, добавит **LENGHT** и **MAXIMUMLENGHT** в соответствующие поля и преобразует общий буфер со строкой **UNICODE** в структуру **UNICODE\_STRING**.

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

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

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

Это структура типа **UNICODE\_STRING** из **8** байт. Так как они представляют собой два слова для **LENGHT** и **DWORD** для копирования указателя на буфер с помощью строки юникода.

Тогда есть вызов к **API IOCREATEDEVICE**, про которую мы говорили.

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

Мы видели, что самый дальний аргумент, т.е. последний, был указателем на **DWORD**, который использовался как выход. Так что **API** хранит там указатель. Мы видим, что программа устанавливает нуль в переменную **INTERFACEDEVICE**, а затем с помощью инструкции **LEA** находит указатель на эту переменную, где будет записан указатель.

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

Затем идет инструкция **PUSH 1**, которая является исключительным аргументом, который мы не видели раньше, потому что это не имело большого значения. Затем появляется инструкция **PUSH EDI**.Мы видим, что в регистре **EDI** есть нуль, поскольку раньше была выполнена инструкция **XOR EDI, EDI**.

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

Это также не очень важно. Затем идёт инструкция **PUSH 8337H**, которая является константой **DEVICETYPE**, которую мы определили в исходном коде.

> \#define FILE\_DEVICE\_HELLOWORLD 0x00008337

Затем появляется указатель на структуру с **\_UNICODE\_STRING** с **DEVICENAME**

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

Затем идет другая инструкция **PUSH EDI**, которая равна нулю **DEVICEEXTENSIONSIZE** и в конце регистр **EBX** является указателем на **DRIVEROBJECT**.

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

Давайте запомним, что это указатель на структуру **\_DRIVER\_OBJECT**.

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

Хорошо. При выходе из **API** будет создан **DEVICEOBJECT**.

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

Если регистр **EAX** имеет отрицательное значение, будет сбой и инструкция **JS** будет переходить на зеленую стрелку. Но у нас всё будет нормально и программа перейдет к функции **DBGPRINT**, которая напечатает "**SUCESS**"

Затем программа будет делать то же самое с другой строкой **UNICODE** при преобразовании ее из буфера со строкой **UNICODE** в структурную форму **\_UNICODE\_STRING**, как и раньше, с помощью **APIRTLINITUNICODESTRING**.

Поэтому **DEVICELINKUNICODESTRING** теперь будет иметь тип **\_UNICODE\_STRING** и будет иметь в своем третьем поле указатель на буфер со строкой **UNICODE L"\DOSDEVICES\HELLOWORLD"**.

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

Затем, передаются указатели на два **\_UNICODE\_STRING** в функцию **IOCREATESYMBOLICLINK**. Мы создаем символическую связь между **DEIVCEOBJECT** и пользовательским режимом.

Регистр **EBX** имеет указатель на структуру **DRIVER\_OBJECT**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrSx7vPF_6hdeduZel%2F-LjrT87V5nHeydm-o2y0%2F52-28.png?generation=1563225018682731\&alt=media)

Если объект не находится в структурах как раньше, мы переходим в **LOCAL TYPES** и синхронизируем программа так, чтобы объект отображался. Мы нажимаем **T** в каждом из этих полей.

Как и в предыдущем случае, мы устанавливаем пользовательскую подпрограмму, когда загружается драйвер, которая находится по смещению **EBX** + **34H**. Теперь нажимая **T**, мы видим, что это поле **DRIVERUNLOAD**.

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

Мы видим, что программа загрузки драйвера не только печатает с помощью **DBGPRINT** строку "**DRIVER UNLOADING**"

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

Поскольку раньше мы создавали символическую ссылку с помощью функции **IOCREATESYMBOLICLINK**, когда мы выходим, мы должны удалить ее с помощью функции **IODELETESYMBOLICLINK**, а также, поскольку мы использовали для создания функцию **DEVICEOBJECT** с **IOCREATEDEVICE**, теперь устройство будет удаляться с помощью **IODELETEDEVICE**, иначе возникнут проблемы с его загрузкой.

Последней вещью во входной функции является поле **MAJORFUNCTION**, которое представляет собой массив указателей обратных вызовов (**DWORD**) на разные функций.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrSx7vPF_6hdeduZel%2F-LjrT87j-UWQMNYgYWwV%2F52-32.png?generation=1563225029256608\&alt=media)

**MAJORFUNCTION** \[**IRP\_MJ\_CREATE**] - это первая позиция в массиве, т.е. **MAJORFUNCION**\[**0x0**].

Поскольку у нас есть таблица.

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

> **\[IRP\_MJ\_CREATE]** это \*\*0x0
>
> \[IRP\_MJ\_CLOSE] **это** 0x02
>
> \[IRP\_MJ\_DEVICE\_CONTROL] **это** 0x0E\*\*

Три поля инициализируются адресом функции **DRIVERDISPATCH**

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

Значение записывается в положение **0x0**, так как \[**IRP\_MJ\_CLOSE**] равно **0x0** \* **4** = **0**

Затем

**\[IRP\_MJ\_CLOSE]** равно **0x2** \* **4** даёт **8**

И затем

**\[IRP\_MJ\_DEVICE\_CONTROL]** это **0x0E** \* **4** даёт **0x38**

Таким образом, все три инструкции пишут один и тот же указатель на одну и ту же функцию.

Каждый из этих обратных вызовов вызывается в разные моменты взаимодействия из программы в пользовательском режиме.

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

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

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

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

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

Функция получает два аргумента. Знаменитый указатель на **DEVICE\_OBJECT**, а второй - указатель на структуру **IRP**, которая является сложной структурой, и мы увидим её позже.

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

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

Мы видим, что, как и в предыдущий раз при регистрации и запуске, драйвер печатает **DRIVERENTRY CALLED** и **SUCESS**, а также при выгрузке **Driver UNLOADING**, но теперь также из пользовательского приложения, которое я сделал при его запуске, хотя раньше нужно было нажимать **START SERVICE** для того, чтобы он начал печатать.

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

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

```c
#include "stdafx.h"
#include <windows.h>

#define FILE_DEVICE_HELLOWORLD 0x00008337
#define IOCTL_SAYHELLO (ULONG) CTL_CODE( FILE_DEVICE_HELLOWORLD, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS )

int main()
{
    HANDLE hDevice;
    DWORD nb;
    hDevice = CreateFile(TEXT(".HelloWorld"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    DeviceIoControl(hDevice, IOCTL_SAYHELLO, NULL, 0, NULL, 0, &nb, NULL);

    CloseHandle(hDevice);
    return 0;
}
```

Т.е. когда я вызываю функцию **CREATEFILE,** чтобы иметь хэндл драйвера, драйвер переходит к обработчику через обратный вызов \[**IRP\_MJ\_CREATE**] и печатает следующее:

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

Затем, когда Вы вызываете с помощью **функции DEVICEIOCONTROL**, передавая его **IOCTL** код.

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

Драйвер использует обратный вызов \[**IRP\_MJ\_DEVICE\_CONTROL**], а затем проверяет, является ли **IOCTL** код равным в этом случае **IOCTL\_SAYHELLO**

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

В этом случае драйвер печатает "**HELLO WORLD**"

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrSx7vPF_6hdeduZel%2F-LjrT88hrpSZaivHD-PA%2F52-45.png?generation=1563225027455718\&alt=media)

И последний код вызывается, когда я вызываю функцию **CLOSEHANDLE** и вызывается соответствующий \[**IRP\_MJ\_CLOSE**]

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

Я синхронизирую структуру **IRP** через **LOCAL TYPES**.

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

И я вижу на вкладке **STRUCTURES** ту же самую структуру.

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

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

Драйвер читает из структуры **IRP** часть **TAIL,** которая не определена в **MSDN**, но здесь, после поиска по смещению **EDI+60** и передачи этого значения в регистр **EBX**, его содержимое переходит в регистр **EAX**, который впервые имеет значение \[**IRP\_MJ\_CREATE**], т.е. нуль. И в этом случае драйвер пойдет туда, чтобы напечатать сообщение о том, что произошло создание.

Если я снова нажму **RUN**, драйвер снова остановится со значением регистра **EAX** равным **0x0E** из \[**IRP\_MJ\_DEVICE\_CONTROL**].

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

Поскольку регистр **EAX** отличается от нуля, драйвер идет сюда.

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

И в этом случае драйвер приходит в розовый блок, печатая, что добрался сюда через **IOCTL**.

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

```c
#define IOCTL_SAYHELLO (ULONG) CTL_CODE(FILE_DEVICE_HELLOWORLD, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS)
```

В коде **IOCTL** код, который получается из значения **0x8337 FILE\_DEVICE**, выполняется несколькими операциями в соответствии с типом **IOCTL** (в этом случае **METHOD BUFFERED** и т.д. и т.д), Который дает нам **IOCTL** код равным **83370000**.

Здесь драйвер сравнивает это и как есть. Он выходит и печатает сообщение "**HELLO WORLD**!".

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

Когда мы проходим через функцию **DEBUGPRINT**, драйвер показывает нам в панели **WINDBG** сообщение. Если бы было несколько **IOCTL** с разными кодами, здесь был бы переключатель.

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

В третий раз, когда мы останавливаемся, мы исполняем функцию **CLOSEHANDLE** и регистр **EAX** равен **2**.

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

И происходит печать.

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

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

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

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

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

22.10.2018

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