R0 CREW

Malware Analysis Tutorial 21: Hijacking Disk Driver (Перевод: Prosper-H)

Перейти к содержанию

Цели урока:

  1. Использовать WinDbg для отладки на уровне ядра.
  2. Разобраться во внутренней работе драйвера диска (disk driver).
  3. Разобраться с созданием скрытого виртуального диска.
  4. Исследовать технику используемую руткитом Max++ для инфицирования драйвера.

1. Введение

В этом уроке будет рассматриваться использование WinDbg для анализа вредоносного .sys драйвера (пусть это будет raspppoe.sys, который был случайным образом выбран Max++ для заражения). С помощью WinDbg мы изучим некоторые основные методы анализа.

Как только драйвер был загружен, Max++ установит скрытый виртуальный диск, чтобы хранить в нем вредоносные файлы, которые он извлечет из себя или загрузит из Интернета. Для достижения этой цели, Max++ должен выполнить некоторые низкоуровневые операции с диском. Сначала, он создаст файл, назвав его «12345678.sav», который в действительности хранит всю информацию о скрытом диске. Затем он перезапишет disk/file driver таким образом, чтобы все запросы (операций чтения/записи) над скрытым диском были на самом деле выполнены над файлом «12345678.sav».

Чтобы повторить эксперименты из этого урока, вы должны следовать инструкциям Раздела 2 из Урока 20.

2. Подготовка

Мы будем использовать настройки Раздела 2 из Урока 20. Ниже мы напомним только несколько из наиболее важных шагов, которые требуются для настройки рабочей среды:

(1) Вам нужен отдельный образ виртуальной машины, с именем «Win_Notes», чтобы иметь возможность комментировать код. На этой виртуальной машине, мы не будет запускать исследуемую вредоносную программу, а будем просто использовать ее для записи всех ваших наблюдений с помощью .udd файла. Чтобы сделать это, необходимо изменить поток исполнения IMM таким образом, чтобы избежать сбоя (crash) при работе с .sys файлами.

(2) Второй образ виртуальной машины «Win_DEBUG» должен быть запущен в DEBUG режиме. При этом, на HostXP должен быть запущен WinDbg, который, с помощью COM-порта, присоединиться к «Win_DEBUG» – таким образом, мы сможем отлаживать данную ОС в режиме ядра.

(3) В WinDbg установите брэйкпойнт «bu _+372b», чтобы перехватить функцию driver entry.

После того, как ваша среда Win_Notes была установлена, у вас должен быть следующий дамп по адресу 0x1000372b.

Рис. 1. Дамп Win_Notes

На рис. 2 показано исходное состояние WinDbg.

Рис. 2. Win_DEBUG

Далее мы будем использовать « _ », что представляет базовый адрес драйвера. В Win_Notes базовым адресом является 0x10000000, а в WinDbg он основан на значении, вычисляемом во время выполнения, например, 0xfafe6400. Каждый раз, когда мы будем обращаться к адресу, мы будем использовать следующую форму « _ + offset », например, « _+372b » (является точкой входа [entry address] драйвера).

3. Основные навыки WinDbg для изучения параметров функции

В этом разделе представлено несколько полезных техник для WinDbg, которые можно использовать для анализа функций. В качестве примера, для их демонстрации, мы возьмем функцию по адресу 0x10003743 (Рис. 1). Наша цель состоит в том, чтобы определить: что это за функция и каковы ее параметры.

Так как нам нужно будет войти (step into) в функцию в отладчике WinDbg, то давайте сначала установим брэйкпойнт на следующую инструкцию, идущую сразу после адреса 0x10003743. Если вы посмотрите на Рис. 1, то заметите, что адресом следующей инструкции является « _ + 3749 »

Давайте установим два брэйкпойна в WinDbg:

kd> bp _+3743
kd> bp _+3749
kd> g 

Вы могли заметить, что здесь используется «bp» вместо «bu», это потому что имя модуля « _ » может быть разрешено (resolved) отладчиком WinDbg, сразу после загрузки модуля.

Теперь, давайте исследуем данные вокруг ESP. Введите команду «dd esp», результат работу этой команды показан ниже. Очевидно, что текущим значением ESP является 0xfafb39c0, при этом первый параметр будет размещен в 0x81184008, а второй в 0x0000005c и т.д.

kd> dd esp
[B][U]fafb39c0  81184008 0000005c[/U][/B] 81139f38 e1533360
fafb39d0  00000000 dd841000 fafb3a18 812e6f80
fafb39e0  8054b6b8 81184076 e14fd07e 81184000
fafb39f0  805702de e14fd008 e14fd000 e14fd080
fafb3a00  00000001 00000000 00000080 00000020
fafb3a10  81184076 80557ee0 81184000 80566ca2
fafb3a20  e14fd07e 805a65ee 805a669a 81184000
fafb3a30  e1bc9908 00000000 e14fd008 e14fd010

Теперь, в WinDbg нажмите F11, чтобы войти в функцию « _+3743 ». Вы получите следующий результат:

kd> t
nt!wcsrchr:
80506d93 8bff            mov     edi,edi

Обратите внимание, что полученный результат, показывает, что в данный момент мы находимся в теле функции nt!wcsrchr. Это позволяет определить имя функции: wcsrchr. Есть и более простой способ определить это, используя команду «ln». Однако, что интересно, она не работает в нашей отладочной сессии и в данный момент, мы не знаем почему.

Ища документацию для функции wcsrchr(str, c), мы вскоре обнаружим, что wcsrchr является расширенной версией strrchr, которая ищет последнее вхождение символа «c» в строке «str». Здесь расширенная версия означает, что каждый символ, в действительности, занимает два байта (для целей интернационализации и локализации).

Дойдя до этого места, мы могли бы предположить, что 0x81184008 является начальным адресом строки, первый символ которой равен 0x5c. Сделав дамп данных для адреса 0x81184008, мы получим:

kd> db 0x81184008
81184008  5c 00 52 00 45 00 47 00-49 00 53 00 54 00 52 00  [B]\.R.E.G.I.S.T.R.[/B]
81184018  59 00 5c 00 4d 00 41 00-43 00 48 00 49 00 4e 00  [B]Y.\.M.A.C.H.I.N.[/B]
81184028  45 00 5c 00 53 00 59 00-53 00 54 00 45 00 4d 00  [B]E.\.S.Y.S.T.E.M.[/B]
81184038  5c 00 43 00 6f 00 6e 00-74 00 72 00 6f 00 6c 00  [B]\.C.o.n.t.r.o.l.[/B]
81184048  53 00 65 00 74 00 30 00-30 00 31 00 5c 00 53 00  [B]S.e.t.0.0.1.\.S.[/B]
81184058  65 00 72 00 76 00 69 00-63 00 65 00 73 00 5c 00  [B]e.r.v.i.c.e.s.\.[/B]
81184068  2e 00 6d 00 72 00 78 00-73 00 6d 00 62 00 00 00  [B]..m.r.x.s.m.b[/B]...
81184078  da 01 0c 00 00 00 00 00-ff ff ff ff 18 00 00 00  ................

Посмотрев на приведенный выше дамп, можно сразу определить, что строкой является «\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services.mrxsmb», а 0x5c это символ « \ ». Очевидно, что Max++ пытается получить имя сервиса, связанного с драйвером. Запомните, что эта строка (имя сервиса) от Driver_Object (первый параметр из функции driver entry)!

Теперь снова введите «g» в WinDbg, чтобы он попал на адрес « _+3749 ». Затем, несколько раз, выполните программу по F10 (step over) и вы вскоре достигните кода по адресу « _+375f » (адрес 0x1000375f на Рис. 1). Где вы можете заметить, что он сравнивает значение из [ebx] с 0x2E. Посмотрев в дамп, вы увидите, что ASCII-значением для 0x2E является « . ».

Так в чем собственно цель этого кода?

_+0x375f:
fae6775f 66833b2e        [B]cmp     word ptr [ebx],2Eh[/B]

kd> db ebx
81184068  [B]2e[/B] 00 6d 00 72 00 78 00-73 00 6d 00 62 00 00 00  ..m.r.x.s.m.b...
81184078  da 01 0c 00 00 00 00 00-ff ff ff ff 18 00 00 00  ................
81184088  00 10 00 00 01 00 00 00-00 00 00 00 d9 01 00 00  ................
81184098  00 00 00 00 58 4d 4c 03-00 00 00 00 d9 01 0c 00  ....XML.........
811840a8  00 00 00 00 ff ff ff ff-18 00 00 00 00 10 00 00  ................
811840b8  01 00 00 00 00 00 00 00-30 00 00 00 00 00 00 00  ........0.......
811840c8  4c 51 4c 03 00 00 00 00-30 00 0c 00 00 00 00 00  LQL.....0.......
811840d8  ff ff ff ff 18 00 00 00-00 10 00 00 01 00 00 00  ................

А цель состоит в том, чтобы определить, начинается ли имя сервиса с символа « . » или нет. Напомним, что в Уроке 18 (Раздел 4), когда Max++ инфицирует драйвер, он также изменяет его запись в реестре (дублирует все содержимое реестра и создает новую запись с « . » в начале). На этот раз, код производит проверку того, что это действительно инфицированный драйвер!

Если это действительно зараженный драйвер, то он выполняется. Теперь Max++ должен скрыть свои следы и правильно установить ключ реестра. Следующее действие, которое он собирается выполнить, должно удалить « . » и «LEGACY_» запись в реестре. Анализ этих действий мы оставим для вас. Вам нужно будет проанализировать две функции по адресам _+3797 и _+379d (0x10003797 и 0x1000379d на Рис. 1).

Задача 1. Проанализируйте функцию по адресу 0x10003797 (Рис. 1). Что она пытается сделать и каковы её параметры?

Задача 2. Проанализируйте функцию по адресу 0x1000379d (Рис. 1). Что она пытается сделать и каковы ее параметры?

4. Инфицирование File Driver

Теперь посмотрим на поведение Max++ относительно дискового драйвера. Сразу после изменения записей реестра, Max++ вызывает функцию _+36CA. (Для настройки рабочего окружения просто перейдите на адрес 0x100036CA в вашей Win_Notes, а в WinDbg поставьте «bp _+36CA»). Как показано на Рис. 2, функция состоит из двух важных стадий: (1) создает disk device “??\C2CAD …” и устанавливает файл 12345678.sav для имитирования всех файловых операций над диском; и (2) инфицирует все дисковые устройства, устанавливая для них обработчики IRP-запросов; инфицирование осуществляется после выполнения инструкции JMP по адресу 0x100036E4 (она переходит на адрес 0x10002C95)… Теперь перейдем к этим двум важным вызовам.

Рис. 2. Инфицирование Disk Driver

4.1 Создание устройства «??\C2CAD…» (_+3108)

По адресу 0x100036DE, Max++ вызывает функцию createDeviceC2CAD (+3108). На Рис. 3 показана первая часть функции «+3108» (createDeviceC2CAD это имя, которое мы присвоили функции). Она содержит два вызова функций: (1) по адресу 0x1000312C, Max++ вызывает вызов ntoskrnl.IoCreateDevice, чтобы создать устройство «??\C2CAD…»; а затем (2) по адресу 0x10003140, Max++ вызывает ntoskrnl.ObMakeTemporaryObject, чтобы сделать вновь созданное устройство более эффективным.

4.1.1 Создание дискового тома

Рис. 3. Добавление Disk Device и обновление IRP-обработчика

Далее приводится объявление функции IoCreateDevice() взятое из MSDN [1]. Для анализа ее содержимого, мы воспользуемся той же техникой, что была представлена ранее, и остановимся на адресе _+312C, чтобы исследовать стэк. Ниже приводятся значения (в виде комментариев) для некоторых из атрибутов рассматриваемой функции.

NTSTATUS IoCreateDevice(
  __in      PDRIVER_OBJECT DriverObject, //[B]"\Driver\.mrxsmb"[/B]
  __in      ULONG DeviceExtensionSize,
  __in_opt  PUNICODE_STRING DeviceName, //[B]""\??\C2CAD972#4079#4fd3#A68D#AD34CC121074""[/B]
  __in      DEVICE_TYPE DeviceType,
  __in      ULONG DeviceCharacteristics,
  __in      BOOLEAN Exclusive,
  __out     PDEVICE_OBJECT *DeviceObject
);

Таким образом, её цель состоит в том, чтобы создать новое устройство, с именем «??\C2CAD972…», драйвером которого является «.mrxsmb».

Задача 3. Где будет находиться результирующий объект DEVICE_OBJECT? (Подсказка: смотрите на последний параметр IoCreateDevice).

Далее, для ново-выделенного объекта DEVICE_OBJECT, последовательно вызываются две функции ObMakeTemporary и ObDereferenceObject. Две эти функции зарезервированными за ОС и не существуют в официальной документации. Их цель состоит в том, чтобы полностью уничтожить ново-созданный объект! (так, чтобы он больше не жил в ядре!) Вы можете задаться вопросом, почему?

Потому что, как только объект устройства будет удален, вы больше не сможете его найти. Но, механизм драйвера, отвечающий за обработку запросов к «??\C2CAD…» как-то частично пережил удаление объекта устройства. Следующий из шагов руткита Max++ должен завершить создание обработчика ВВОДА/ВЫВОДА для устройства «??\C2CAD…» и имитировать его действия используй файл 12345678.sav.

4.1.2 Создание файла 12345678.sav используемого для имитации

Теперь давайте посмотрим на то, как создается файл 12345678.sav. Как показано на Рис. 4, его создание состоит из трех шагов: (1) по адресу 0x10003176 он encrypts 12345678.sav, используя последнее записанное AGP-время, и генерирует случайно имя файла, такое как yknueenef.sav; (2) затем по адресу 0x100031B4 вызывает ZwCreateFile, чтобы создать файл; (3) вызывает ZwSetFileControlInfo, чтобы убедиться, что файл не является сжатым (compressed).

Рис. 4. Создание файла 12345678.sav

Чтобы увидеть трюк кодирования имени файла, посмотрите на следующий дамп WinDbg (до и после вызова по адресу 0x10003177).

kd> dd esp
fafaf8f4  [B]fafaf940[/B] 81138bb8 812f2000 812f2068
fafaf904  fafaf927 0073005c 00730079 00650074
fafaf914  0072006d 006f006f 005c0074 00790073
fafaf924  00740073 006d0065 00320033 0063005c
fafaf934  006e006f 00690066 005c0067 00320031
fafaf944  00340033 00360035 00380037 0073002e
fafaf954  00760061 00000000 00000000 00000000
fafaf964  00000000 00000000 00000000 00000000

kd> db [B]fafaf940[/B]
fafaf940  31 00 32 00 33 00 34 00-35 00 36 00 37 00 38 00  [B]1.2.3.4.5.6.7.8.[/B]
fafaf950  2e 00 73 00 61 00 76 00-00 00 00 00 00 00 00 00  [B]..s.a.v[/B].........
fafaf960  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
fafaf970  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
fafaf980  00 00 00 00 00 00 00 00-23 00 00 00 c1 c8 4d 80  ........#.....M.
fafaf990  08 00 00 00 10 8b 13 81-10 8b 13 81 cc fd fa fa  ................
fafaf9a0  30 00 00 00 10 8b 13 81-00 20 2f 81 68 20 2f 81  0........ /.h /.
fafaf9b0  7c fc fa fa 00 00 00 00-7c fc fa fa e3 76 e0 fa  |.......|....v..

kd> p
_+0x317c:
fae0717c 53              push    ebx
kd> db fafaf940
fafaf940  79 00 6b 00 6e 00 75 00-65 00 65 00 6e 00 66 00  [B]y.k.n.u.e.e.n.f.[/B]
fafaf950  2e 00 73 00 61 00 76 00-00 00 00 00 00 00 00 00  [B]..s.a.v[/B].........
fafaf960  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
fafaf970  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
fafaf980  00 00 00 00 00 00 00 00-23 00 00 00 c1 c8 4d 80  ........#.....M.
fafaf990  08 00 00 00 10 8b 13 81-10 8b 13 81 cc fd fa fa  ................
fafaf9a0  30 00 00 00 10 8b 13 81-00 20 2f 81 68 20 2f 81  0........ /.h /.
fafaf9b0  7c fc fa fa 00 00 00 00-7c fc fa fa e3 76 e0 fa  |.......|....v..

Задача 4. Проанализируйте детали вызова функции по адресу 0x10003177 (кодирование имени файла).
Задача 5. Проанализируйте детали вызова функции по адресу 0x100031B4 (создание файла).
Задача 6. Проанализируйте детали вызова функции по адресу 0x100031E5 (set file control information).

Рис. 5. Set up Properties of 12345678.sav and Test Disk Drive

Как показано на Рис. 5, следующее действие, которое выполняет Max++, должно установить конец файла 12345678.sav в 0x0100 0000 (потому что это будет большим файлом, который будет содержать очень много данных). Затем он получает дескриптор устройства из 12345678.sav (обратите внимание, что текущим драйвером диска [disk dirver] является «FileSystem\sr»), однако, этот дескриптор не будет никогда использоваться (by the IoDeleteDevice at the end). Потому, что по адресу 0x1000329E, руткит делает прыжок и пропускает вызов функции IoDeleteDevice.

Задача 7. Проанализируйте детали вызова функции по адресу 0x100031FD (ZwSetInformation).
Задача 8. Проанализируйте детали вызова функции по адресу 0x1000322E (getDevice).
Задача 9. Проанализируйте детали вызова функции по адресу 0x10003297 (который вызывает _+302E).

Обратите внимание, что функция « _+302E » (Задача 9) просто осуществляет возможность открытия «??\C2CAD…» и она приводит к ошибке (ничего удивительного, ведь IRP-обработчик еще не был установлен для нового дискового драйвера).

4.2 Infect Disk Devices (_+2C95)

Теперь посмотрим на функцию по адресу 0x10002C95 (переход осуществляется из 0x100036E4). На Рис. 6. показано тело этой функции. Эта функция инфицирует (изменяет) все объекты устройств (device objects) связанные с Disk driver. Сейчас углубимся в детали. Как показано в выделенных областях из Рис. 6, функция выполняет следующие действия: (1) вначале она вызывает IoEnumerateDeviceObjectList, чтобы получить список объектов устройств зарегистрированных с драйвером «\Driver\Disk» (в нашей системе, мы получили список из двух устройств); (2) затем она использует цикл, чтобы изменить связанные устройства (создает новое устройство и делает несколько копий и модификаций). Но какова цель всех этих действий? Нам нужно получить больше деталей и проследить за потоком исполнения.

Рис. 6. Инфицирование устройств связанных с Disk Driver

4.2.1 Device Object List

Мы заинтересованы в том, чтобы определить список вовлеченных устройств. Для достижения этой цели, нам, вначале, нужно проверить параметры IoEnumerateDeviceObjectList. Согласно [2], функция IoEnumerateDeviceList имеет следующий прототип:

NTSTATUS IoEnumerateDeviceObjectList(
  __in   PDRIVER_OBJECT [B][U]DriverObject,[/U][/B]
  __out  PDEVICE_OBJECT [B][U]*DeviceObjectList,[/U][/B]
  __in   ULONG DeviceObjectListSize,
  __out  PULONG [B][U]ActualNumberDeviceObjects[/U][/B]
);

Очевидно, что первый параметр является выходящим (INPUT) объектом драйвера (для которого мы хотим перечислить все устройства, которые с ним связанны), второй параметр является указателем, который указывает на место, где будет храниться список из объектов _DEVICE_OBJECT, ну а четвертый параметр это еще один указатель, который указывает на целочисленную переменную, которая хранит количество объектов устройств.

Чтобы исследовать содержимое стэка, отобразим первые четыре слова начиная со значения из ESP, как показано ниже. Здесь, первый параметр (DriverObject) равен 81299670, а четвертый параметр (ActualNumberDeviceObjects) равен fafab9bc.

kd> bp _+2cd8
kd> g
fae36cd8 ff15d480e3fa    call    dword ptr [_+0x40d4 (fae380d4)]
kd> dd esp
fafab5a0  [B][U]81299670 fafab5b4[/U][/B] 00000400 [B][U]fafab9bc[/U][/B]

kd> [B]dt _DRIVER_OBJECT [U]81299670[/U][/B] 
nt!_DRIVER_OBJECT
   ...
   +0x018 DriverExtension  : 0x81299718 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING [B]"\Driver\Disk"[/B]

Исследуя содержимое _DRIVER_OBJECT при помощи команды dt отладчика WinDbg, мы узнаем, что драйвером является «\Driver\Disk». После прохода через (stepping over) вызов функции, мы сможем определить, что существует два объекта устройства, которые связанны с выше названным драйвером, и они расположены по адресам 812fb810 и 812fc030. Детали показаны ниже.

kd> p
_+0x2cde:
fae36cde 395dfc          cmp     dword ptr [ebp-4],ebx
kd> dd [B][U]fafab9bc[/U][/B]
fafab9bc  [B][U]00000002[/U][/B] fafabc7c fae377af ffb3a6e8

kd> dd [B][U]fafab5b4[/U][/B]
fafab5b4  [B][U]812fb810 812fc030[/U][/B] 00000000 e1b63f30

Мы можем отобразить содержимое двух объектов устройств так, как показано ниже. Сначала обратите внимание на их различие в Sector size. Каково ваше предположение? Вы могли бы предположить, что _DEVICE_OBJECT 812fc030 не является томом (volume)! Согласно [3], «если объект устройства не представляет собой том (volume), то этот элемент структуры обнуляется. Если объект устройства представляет том, то этот элемент определяет размер сектора тома, в байтах».

kd> dt _DEVICE_OBJECT 812fb810
nt!_DEVICE_OBJECT
   +0x000 Type             : 0n3
   +0x002 Size             : 0x368
   +0x004 ReferenceCount   : 0n0
...
   [B][U]+0x0ac SectorSize       : 0x200[/U][/B]
   +0x0ae Spare1           : 0
   +0x0b0 DeviceObjectExtension : 0x812fbb78 _DEVOBJ_EXTENSION
   +0x0b4 Reserved         : (null) 

kd> dt _DEVICE_OBJECT 812fc030 
nt!_DEVICE_OBJECT
   +0x000 Type             : 0n3
   +0x002 Size             : 0x518
   +0x004 ReferenceCount   : 0n0
  ...
   [B][U]+0x0ac SectorSize       : 0[/U][/B]
   +0x0ae Spare1           : 1
   +0x0b0 DeviceObjectExtension : 0x812fc548 _DEVOBJ_EXTENSION
   +0x0b4 Reserved         : (null) 

4.2.2 Цикл который выполняет инфицирование

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

Рис. 7. Первая часть цикла: проверяет, является ли это модулем

По адресу « _+2CF6 » (или 0x10002CF6), EDI указывает на текущий _DEVICE_OBJECT. Вы можете проверить эту информацию ниже (сейчас он указывает на второе устройство 812FC030). Обратите внимание, что цикл начинает обработку с ПОСЛЕДНЕГО устройства в списке! Можете ли вы определить, почему?

kd> bp _+2CF6
kd> g
Sat Mar 17 10:40:52.406 2012 (UTC - 4:00): Breakpoint 1 hit
_+0x2cf6:
fae36cf6 8b4728          mov     eax,dword ptr [edi+28h]

kd> r edi
edi=812fc030

Задача 10. Докажите, что цикл из Рис. 6, обрабатывает объекты устройств в направлении с конца к началу.

Теперь, как показано на Рис. 7, Max++ выполняет множество проверок над свойствами устройства, в основном, над структурой DeviceExtension. Структура device extension является специфической для устройства и мы не можем получить больше деталей здесь, но 2-й модуль устройства проходит все проверки и Max++ выполняет модификацию этого модуля.

4.2.3 Инфицирование

Вторая часть цикла показана на Рис. 8.

Рис. 8. Создание нового объекта устройства, чтобы обернуть старый объект устройства

Первым интересным действием является вызов IoCreateDevice() по адресу «_+2D34 ». Его первым параметром является DRIVER_OBJECT. Когда мы сдампим его содержимое, найдем кое-что интересное:

kd> dt _DRIVER_OBJECT ffb3a6e8
nt!_DRIVER_OBJECT
   +0x000 Type             : 0n4
  ...
   +0x02c DriverInit       : [B][U]0xfae3772b[/U][/B]     long  +0
   +0x030 DriverStartIo    : (null) 
   +0x034 DriverUnload     : (null) 
   +0x038 MajorFunction    : [28] [B][U]0xfae36bde[/U][/B]     long  +0

Это инфицированный драйвер (entry address 372b)! Так, что Max++ создает еще одно устройство ввода-вывода, которое связанно с инфицированным драйвером. Обратите внимание, что DEVICE_OBJECT, возвращаемый функцией, будет храниться в [EBP-8]. К этому выводу можно прийти, рассмотрев спецификацию и код функции IoCreateDevice().

Далее, Max++ выполнит некоторые действия связанные с копированием. Например, по адресу « _+2D3E » он копирует параметр StackSize (размещенный по смещению 0x30) _DEVICE_OBJECT из старого объекта устройства в новое. Затем, по адресу « _+2D4D », он, для нового устройства, устанавливает DeviceExtension.FIRST_WORD (предположительно: AttachedDevice) в значение, взятое из старого устройства.

В DeviceExtension[0] хранится объект СТАРОГО устройства, в DeviceExtension[4] хранится реально присоединенное низкоуровневое аппаратное устройство (управляемое ATAPI)! В то время, как само устройство зарегистрировано с помощью ИНФИЦИРОВАННОГО драйвера!

Отсюда, совершенно ясно, что хочет сделать Max++: он вставляет еще один слой в цепочку обработки IRP-запросов, так что любой IRP-запрос к диску будет проходить через ИНФИЦИРОВАННЫЙ ДАРЙВЕР (entry function: 372b)!

На данный момент, мы уже имеем большую картину: Max++ завершил первую часть соединений вредоносного драйвера с дисковыми операциями (создал новую обертку для дискового объекта устройства). Все IRP-запросы связанные с диском, будут, вначале, передаваться вредоносному драйверу! Но, обратите внимание, что устройство «??\C2CAD…» еще не было полностью установлено. Мы перейдем ко второй части в следующем уроке.

© Translated by Prosper-H from r0 Crew

Ссылки

[1] Microsoft, MSDN, “IoCreateDevice”
[2] Mcrosoft MSDN, “IoEnumerateDeviceObjectList”
[3] Microsoft MSDN, “Device Object”