R0 CREW

Malware Analysis Tutorial 28: Break Max++ Rootkit Hidden Drive Protection (Перевод: Prosper-H)

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

Цели урока:

  1. Попрактиковаться в перехвате загрузки DLL-библиотек с помощью WinDbg.
  2. Попрактиковаться в изменении двоичного кода в IMM.
  3. Используя IMM протрейсить и изменить поток исполнения программы.

1. Введение

Характерной чертой Max++ является его возможность скрывать вредоносные файлы в скрытом диске. В этом уроке, мы покажем вам, как модифицировать руткит, чтобы сломать его защиту скрытого диска. Наша цель будет состоят в том, чтобы извлечь B48DADFD.sys из скрытого диска. Напомним, что B48DADFD.sys используется для загрузки ряда вредоносных DLL-файлов, которые были представлены в Уроке 27.

2. Вступление: Кто загрузил B8DADFD.sys?

Вначале, нам нужно определить, кто загружает B48DADFD.sys. Следуйте инструкциям 1-4 из Урока 19, чтобы установить соответствующее окружение для экспериментов. После того, как запустится WinDbg, нажмите «Debug => Event Filter», чтобы включить обработку события «Load Module» (Рис. 1). Затем, после того, как вы попадете на брэйкпойнт (BP) по адресу 0x401417 в IMM, нажмите SHIFT+F9, чтобы дать возможность руткиту продолжить свое выполнение. Первым модулем, который вы перехватите, будет « _ » (тот, который хакает lz32.dll), а вторым модулем будет B48DADFD.sys.

Рис. 1. Включение фильтра событий для загрузки модуля

Как показано ниже, WinDbg попадает на DebugService2+0x10, это обработчик события загрузки модуля. Если вы отобразите список всех существующих модулей командой «lm», то заметите, что модуль B48DADF8 был загружен. Мы можем продолжить осмотр содержимого стэка, чтобы обнаружить вызывающего.

kd> g
[B][U]nt!DebugService2+0x10:[/U][/B]
80506d3e cc              int     3

kd> [B][U]lm[/U][/B]
start    end        module name
804d7000 806ed680   nt         (pdb symbols)          c:\windows\symbols\ntoskrnl.pdb\47A5AC97343A4A7ABF14EFD9E99337722\ntoskrnl.pdb
[B][U]fadfc000 fae01000   B48DADF8   (deferred)[/U][/B]             
faed4000 faedc000   _          (deferred)             

Unloaded modules:
f77c4000 f77ef000   kmixer.sys
f7b6e000 f7b99000   kmixer.sys
fb206000 fb207000   drmkaud.sys
f7b99000 f7bbc000   aec.sys 
f7c89000 f7c96000   DMusic.sys
facec000 facfa000   swmidi.sys
fb0f0000 fb0f2000   splitter.sys
fad6c000 fad77000   imapi.sys
fad5c000 fad6b000   redbook.sys
fae6c000 fae71000   Cdaudio.SYS
fb050000 fb053000   Sfloppy.SYS
fae64000 fae69000   Flpydisk.SYS
fae5c000 fae63000   Fdc.SYS 

kd> [B][U]kv[/U][/B]
ChildEBP RetAddr  Args to Child              
f76a251c 80506d80 f76a25b4 f76a2530 00000003 nt!DebugService2+0x10 (FPO: [Non-Fpo])
f76a2540 805a3113 f76a25b4 fadfc000 ffffffff nt!DbgLoadImageSymbols+0x42 (FPO: [Non-Fpo])
f76a26e4 805a7c9d f76a2800 00000000 00000000 nt!MmLoadSystemImage+0xa80 (FPO: [Non-Fpo])
f76a2894 804de7ec 00000036 f76a2974 0000001c nt!NtSetSystemInformation+0x8a9 (FPO: [Non-Fpo])
f76a2894 804dd98d 00000036 f76a2974 0000001c nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f76a28a8)
*** ERROR: Module load completed but symbols could not be loaded for *
f76a2918 faed50c7 00000036 f76a2974 0000001c nt!ZwSetSystemInformation+0x11 (FPO: [3,0,0])
WARNING: Stack unwind information not available. Following frames may be wrong.
f76a299c faed6b93 ffbd2478 ffb23550 003f005c _+0x10c7
f76a2a34 faed6bf8 ffbd2478 ffb23550 ffb97840 _+0x2b93
f76a2a4c 804e37f7 ffa337b0 ffbd2468 ffbd2468 _+0x2bf8
f76a2a5c 8056c712 ffa33798 ffaad86c f76a2c04 [B][U]nt!IopfCallDriver[/U][/B]+0x31 (FPO: [0,0,0])
f76a2b3c 80563fec ffa337b0 00000000 ffaad7c8 nt!IopParseDevice+0xa12 (FPO: [Non-Fpo])
f76a2bc4 805684da 00000000 f76a2c04 00000040 nt!ObpLookupObjectName+0x56a (FPO: [Non-Fpo])
f76a2c18 8056cbeb 00000000 00000000 160de801 nt!ObOpenObjectByName+0xeb (FPO: [Non-Fpo])
f76a2c94 8056ccba 0012d624 00100000 003d3150 nt!IopCreateFile+0x407 (FPO: [Non-Fpo])
f76a2cf0 8056cdf0 0012d624 00100000 003d3150 [B][U]nt!IoCreateFile[/U][/B]+0x8e (FPO: [Non-Fpo])
f76a2d30 804de7ec 0012d624 00100000 003d3150 nt!NtCreateFile+0x30 (FPO: [Non-Fpo])
f76a2d30 7c90e4f4 0012d624 00100000 003d3150 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f76a2d64)
0012d648 003c2507 00401166 003c0000 fffffffe 0x7c90e4f4
0012ffd0 8054b6b8 0012ffc8 81148da8 ffffffff [B][U]0x3c2507[/U][/B]
00413a40 ec81ec8b 0000030c d98b5653 f4b58d57 nt!ExFreePoolWithTag+0x676 (FPO: [Non-Fpo])
00413a4c f4b58d57 8bfffffd f45589c3 0000c0e8 0xec81ec8b
00413a50 8bfffffd f45589c3 0000c0e8 10c38300 0xf4b58d57
00413a54 f45589c3 0000c0e8 10c38300 0cf85d89 0x8bfffffd
00413a58 00000000 10c38300 0cf85d89 f3b58dff 0xf45589c3

Исходя из содержимого стэка, загрузку B48DADFD.sys, по сути, вызывает код из lz32.dll (код вызывающего находится перед адресом 0x3C2507). Цепочка вызовов имеет следующий вид:

«Инструкция до адреса 0x3C2507 (lz32.dll) => ... => IoCreateFile => ... => IopfCallDriver ... => load B484DADFD.sys»

Задача 1. Используйте методы анализа, представленные в Уроке 27, чтобы проанализировать как загружается B48DADFD.

3. Настройка окружения для экспериментов

Учитывая то, что B48DADFD загружается при помощи инструкции находящейся перед адресом 3C2507, то мы начнем нашу настройку окружения с того, что дойдем до вредоносного драйвера. Шаги по настройке окружения приведены ниже:

Сначала следуйте инструкциям 1-4 из Урока 19. Когда сработает брэйкпойнт по адресу 0x004017, в панели CPU, перейдите на адрес 0X3C2502 (при помощи «right click => Go to Expression») и установите на него программный брэйкпойнт. Вы должны видеть код, как показано ниже (Рис. 2).

Рис. 2. Брэйкпойнт перед загрузкой B48DADFD.sys

В данный момент, мы готовы извлечь B48DADFD из скрытого диска.

4. Операция над скрытым диском

Так как скрытый диск не отображается в Проводнике Windows, то мы должны вызывать некоторые функции, доступные в системной библиотеке Windows, чтобы извлечь B48DADFD.sys из скрытого диска. Это возможно, потому что Max++ подключается к драйверу файловой системы для обработки специальных запросов, направленных к скрытому диску. Наш план заключается в том, чтобы перезаписать инструкции, находящиеся сразу после инструкции расположенной по адресу 0x003C2502, и попытаться скопировать файл из скрытого диска.

Просмотр kernel32.dll (View => Executable Modules => ViewNames) дает нам хорошего кандидата, для осуществления наших целей (Рис. 3).

Рис. 3. Библиотека kernel32.dll функция CopyFileA

Согласно MSDN, прототип функции CopyFileA имеет вид, как показано ниже (где «A» обозначает ASCII, т.е. указывает на то, как кодируется имя файла. Вы могли видеть, что на Рис. 3, есть несколько вариантов этой функции, таких как, например, CopyFileW):

BOOL WINAPI CopyFile(
  _In_  LPCTSTR lpExistingFileName,
  _In_  LPCTSTR lpNewFileName,
  _In_  BOOL bFailIfExists
);

Таким образом, следуя нашему плану, начиная с адреса 0x003C250C, мы можем, используя IMM, модифицировать код и вставить инструкцию CALL 7C8286D6. При этом, мы так же изменим содержимое стэка, чтобы три параметра требуемых функции были правильно в нем расположены. Вначале мы можем модифицировать инструкции так, как показано на Рис. 4. Просто в панели CPU нажмите «right click => Assmeble» (или нажмите «пробел») и введите «CALL 7C8286D6», чтобы изменить двоичный код.

Рис. 4. Изменение двоичного кода в IMM

Теперь нам нужно создать параметры для вызова функции CopyFileA. Нам нужно вставить две строки в окно дампа, общий подход того, как это делается, показан на Рис. 5. «Right click => Binary => Edit». Убедитесь что, вставка данных происходит при значении EIP равном 0x003c2507, дабы избежать разрушения данных относящихся к предыдущим вызовам Max++.

Рис. 5. Изменение двоичного кода

Вставленные данные показаны на Рис. 6. Строка файла «\.\C2CAD…\B48DADF8.sys» получена из более раннего анализа дампа стэка функции ntLoadImage, в Разделе 2. Как показано на Рис. 6, мы вставили две строки, одна из которых «\.\C2CAD…\B48DADF8.sys», а другая «c:\bad.sys». К тому же, как только мы ввели данные в окно дампа, в окне стэка отобразились соответствующие параметры. Третий параметр (FailfExists) может быть установлен в «False» (0).

Рис. 6. Входящие параметры для CopyFileA

Выполнив один шаг (Step In) в панели CPU, мы успешно вытащим вредоносный файл из скрытого диска (Рис. 7).

Задача 2. Выведите список всех файлов, которые находятся в скрытом диске и извлеките их из него.

Рис. 7. Успешное извлечение B48DADF8.sys

© Translated by Prosper-H from r0 Crew