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

# Часть 51

Перед тем, как приступить к **ВИДЕОТУТОРИАЛАМ**, мы должны скомпилировать и пореверсить немного те драйверы, что были сделаны в предыдущей части, а также некоторые другие драйверы, чтобы ознакомиться с тем, как они работают.

В случае простого драйвера из части **50**, это простой **HELLO WORLD**, очень простой для реверсинга. Мы уже увидели, что при его компиляции со старым **WDK 7.1** есть несколько простых подпрограмм, а в новом **WDK 10** есть несколько функций перед инициализацией, но они приходят к тому же коду. Там нет никакой другой функциональности.

Здесь мы находимся в том месте, что будет точкой входа в драйвер **DRIVERENTRY** в старом драйвере сделанном в **WDK 7.1**.

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

Мы видим по звездочкам, что есть два аргумента, которые являются двумя указателями, т.е. по **4** байта. Первый это указатель на структуру **\_DRIVER\_OBJECT**, а второй на структуру **\_UNICODE\_STRING**. Давайте посмотрим их, так как **IDA** обнаруживает их

В **MSDN**.

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

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

Во вкладке структуры их нет. Но не забываем, что в **LOCAL TYPES** иногда есть больше структур. Мы также замечаем там это.

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

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

Хорошо. Вот она. Мы будем импортировать её. Делаем правый щелчок и выбираем **SYNCRONIZE TO IDB**.

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

Поскольку я загружаю адрес структуры в регистр **EAX**, я знаю, что **EAX+34H** это какое-то поле структуры. Мы нажимаем **T**, чтобы увидеть.

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

Из структур, которые загружены, я выбираю **\_DRIVER\_OBJECT** и это поле **DRIVERUNLOAD**.

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

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

В переводе на испанский, это переменная указатель в структуре, которая сохраняет адрес функции, которую система будет вызвать при выгрузке драйвера. Здесь вверху мы видим, что тип функции определен, её аргумент это указатель на **\_DRIVER\_OBJECT** и ввеху всего этого мы видим определение структуры **PDRIVER\_UNLOAD** что очевидно является адресом, так как это указатель на ту же фунцию. Мы видим звездочку в определении.

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

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

В нашем случае, **IDA** показывает нам смещение, так как это адрес функции **\_DRIVERUNLOAD**. Нажимаем пункт **DEMANGLE NAMES → NAMES**. Теперь всё выглядит лучше.

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

Поэтому, когда запускается драйвер, он приходит сюда и печатает "**HELLO WORLD**" каждый раз, когда он запускается, посредством функции **\_DBGPRINT** и сохраняет адрес функции, которая будет выполняться при выгрузке драйвера.

Давайте запомним, что функция, которую мы создали **DRIVERUNLOAD** в нашем коде, должна быть скорректирована до типа, определенного ранее, т.е. его аргумент должен быть указателем на **\_DRIVER\_OBJECT**, и поэтому наш аргумент имеет тип **PDRIVER\_OBJECT**, как говорят определения функции в исходном коде.

```
#include <ntddk.h>

void DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    DbgPrint("Driver unloading\n");
}
```

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

Так что все типы совпадают. Это будет процедура, когда драйвер будет выгружатся, и как мы видим, напечатает сообщение "**DRIVER UNLOADING**" используя функцию **\_DBGPRINT**.

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

Если драйвер отлаживается, сообщение будет видно в **ЛОГАХ** отладчика. Как мы видели в **WINDBG** и в **IDA** сообщение "**HOLA MUND** " и "**DRIVER UNLOADING**" при загрузке и выгрузке.

В этой версии не так много интересного. Мы увидим другую версию, которая скомпилирована с **WDK 10**, поэтому реверсим эту совсем чуть-чуть. Мы проходим мимо части инициализации, и сосредоточимся на том, как драйвер управляет структурой и указателем на **DRIVERUNLOAD**.

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

Функция **\_DRIVERENTRY\@8** имеет те же аргументы, которые являются двумя указателями на структуры, которые мы видели в другой части.

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

Мы видим, что регистр **EDI** берет адрес структуры **DRIVEROBJECT** и использует его во всей функции вплоть до выхода из неё, когда исполняется **POP EDI** перед **RET**.

Я могу сделать правый щелчок и выбрать **RENAME** в регистре **EDI** и в диапазоне, где остается то же значение. Я переименую его в **P\_DRIVEROBJECT**.

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

Эта метка распространяется до самого конца, где уже **POP EDI** изменяет значение.

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

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

Хорошо. Это структура, которая имеет тип **USHORT** (слово) в переменной **LENGHT**. Другая переменная с максимальной длиной буфера и указатель на буфер со строкой типа **UNICODE**. Другими словами, всегда длина структуры будет **0x8**, два **WORD** плюс указатель типа **DWORD**.

**Length** Specifies the length, in bytes, of the string pointed to by the **Buffer** member, not including the terminating **NULL** character

**MaximumLength** Specifies the total size, in bytes, of memory allocated for **Buffer**. Up to **MaximumLength** bytes may be written into the buffer without trampling memory.

**Buffer** Pointer to a wide-character string. Note that the strings returned by the various LSA functions might not be **null**-terminated.

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

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

Мы видим, что эта функция имеет в качестве аргумента указатель на исходную структуру **UNICODE\_STRING** и как назначение, указатель типа **UNICODE\_STRING**.

Здесь мы видим два аргумента, источник, который является **REGISTRYPATH**, который является указателем на структуру **UNICODE\_STRING** и регистр **ESI**, который имеет назначение того же типа.

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

Регистр **ESI** указывает на секцию данных. Здесь есть эта переменная того же типа.

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

Поскольку, мы видим, что длина была **0x8** байт, в секции данных следующий адрес, который остается будет на **0x8** больше, т.е.

```
Python>hex(0x40367c+0x8)
0x403684
```

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

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

Сам буфер имеет **0x104** слова, т.е. **0x208** байта или **520** в десятичной системе

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

```
hex(0x104*2)
0x208
```

```
Python>(0x104*2)
520
```

Здесь я показываю, что это массив **260** типа **WCHAR\_T** (**2** байта), т.е. **260** \* **2** что равно **520**.

Поэтому все нормально. Указатель указывает на буфер длиной **0x208** и максимальное значение также равно **0x208**.

Давайте не будем забывать об этом.

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

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

Это переменная из **4** байтов **DD**, так как это указатель на структуру **\_DRIVER\_OBJECT**.

Затем есть пара недокументированных функций инициализации. По крайней мере я их не нашел в документации, и это не так важно. Всё это чистая инициализация. А затем программа приходит к **DRIVERENTRY**, функция которого эквивалентна предыдущему драйверу.

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

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

Внутри функции, если мы делаем то же самое как в предыдущий раз и пойдем в **LOCAL TYPES** и синхронизируем структуру **DRIVER\_OBJECT**.

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

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

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

Мы видим, как поле **DRIVERUNLOAD** проверяется на нуль. Программа переходит в розовую часть, где будет сохранен указатель на нашу функцию в эту переменную секции данных под названием **WDFDRIVERSTUBDISPLACEDDRIVERUNLOAD**.

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

И также программа перезаписывает поле **DRIVERUNLOAD** функцией, которая не является моей и называется **FXSTUBDRIVERUNLOAD** и которая выглядит так если мы её посмотрим.

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

При выгрузке драйвера программа будет переходить в функцию **FXSTUBDRIVERUNLOAD**, но затем загрузит нашу функцию **DRIVERUNLOAD** через переменную **WDFDRIVERSTUBDISPLACEDDRIVERUNLOAD**, так как туда программа сохранила адрес функции. И программа переходит в инструкцию **CALL EAX** так же, как и в предыдущем примере, только для того, чтобы сделать немного больше циклов.

В следующей части, мы будем стараться скомпилировать драйвер, который вызывает **IOCTL** из пользовательского режима, зная, что это один из способов эксплуатации драйвера (И это не единственный способ)

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

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

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

21.10.2018

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