Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / Майкл_Сикорски,_Эндрю_Хониг_Вскрытие_покажет!_Практический_анализ.pdf
Скачиваний:
18
Добавлен:
19.04.2024
Размер:
17.17 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

w

 

 

to

 

 

248  Часть III  •  Продвинутый динамический анализ

w Click

 

 

 

 

 

 

 

 

 

 

 

o

m

 

w

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

сделанном из пользовательского пространства, вы можете получить информацию о его объекте, применив команду !devobj.

kd> !devobj FileWriterDevice Device object (826eb030) is for:

Rootkit \Driver\FileWriter DriverObject 827e3698

Current Irp 00000000 RefCount 1 Type 00000022 Flags 00000040 Dacl e13deedc DevExt 00000000 DevObjExt 828eb0e8 ExtensionFlags (0000000000)

Device queue is not busy.

Объект устройства содержит указатель на объект драйвера, и, получив указатель на последний, вы сможете найти таблицу функции MajorFunction.

Но даже после обнаружения зараженного драйвера вам, вероятно, нужно будет выяснить, какие приложения его используют. Одним из параметров команды !devobj, которую мы только что запустили, является дескриптор объекта устройства. Его можно передать команде !devhandles, чтобы получить список всех программ в пользовательском пространстве, которые его хранят. Эта команда перебирает таблицы дескрипторов всех процессов, что может занять довольно много времени. Ниже представлен отрывок ее вывода, в котором видно, что наш зараженный драйвер использовало приложение FileWriterApp.exe:

kd>!devhandles 826eb030

...

Checking handle table for process 0x829001f0 Handle table at e1d09000 with 32 Entries in use

Checking handle table for process 0x8258d548

Handle table at e1cfa000 with 114 Entries in use

Checking handle table for process 0x82752da0 Handle table at e1045000 with 18 Entries in use

PROCESS 82752da0 SessionId: 0 Cid: 0410 Peb: 7ffd5000 ParentCid: 075c DirBase: 09180240 ObjectTable: e1da0180 HandleCount: 18.

Image: FileWriterApp.exe

07b8: Object: 826eb0e8 GrantedAccess: 0012019f

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

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

Руткиты

Руткиты модифицируют внутреннюю функциональность ОС, чтобы скрыть свое присутствие. Они могут прятать от запущенных программ файлы, процессы, сетевые соединения и другие ресурсы, мешая антивирусам, администраторам и аналитикам безопасности обнаружить вредоносную активность.

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Глава 10. Отладка ядра с помощью WinDbg   249

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Большинство действующих руткитов тем или иным образом изменяют ядро. И хотя они применяют широкий набор разнообразных методик, на практике наиболее популярен прием под названием «перехват таблицы дескрипторов системных служб». Он возник несколько лет назад, и его легко обнаружить по сравнению с другими методиками. Тем не менее ввиду своей понятности, гибкости и простоты в реализации он по-прежнему применяется во вредоносном ПО.

Таблица дескрипторов системных служб (System Service Descriptor Table, SSDT) используется внутри Windows для поиска функций в ядре. Обычно она недоступна сторонним приложениям или драйверам. Как вы помните из главы 7, к коду ядра из пользовательского пространства можно обращаться только с помощью инструкций SYSCALL, SYSENTER и INT 0x2E. Инструкция SYSENTER применяется в современных версиях Windows, позволяя получать инструкции из кода функции, хранящегося в регистре EAX. В листинге 10.11 показан код из библиотеки ntdll.dll, который реализует функцию NtCreateFile и берет на себя переход между режимами пользователя и ядра, который происходит при каждом вызове NtCreateFile.

Листинг 10.11. Код функции NtCreateFile

 

7C90D682

mov

eax, 25h

; NtCreateFile

7C90D687

mov

edx, 7FFE0300h

 

7C90D68C

call

dword ptr [edx]

 

7C90D68E

retn

2Ch

 

Вызов dword ptr[edx] будет транслирован в следующие инструкции:

7c90eb8b

8bd4

mov

edx,esp

7c90eb8d

0f34

sysenter

 

В листинге 10.11 регистру EAX присваивается значение 0x25 , указатель на стек сохраняется в EDX, а затем вызывается инструкция sysenter. Значение EAX представляет собой номер функции NtCreateFile, который будет использован в качестве индекса в таблице SSDT, когда код дойдет до ядра. В частности, адрес со сдвигом 0x25 в SSDT будет вызван в режиме ядра. В листинге 10.12 показано несколько записей из SSDT; запись для NtCreateFile имеет сдвиг 25.

Листинг 10.12. Несколько записей из таблицы SSDT, в том числе и для NtCreateFile

SSDT[0x22] = 805b28bc (NtCreateaDirectoryObject) SSDT[0x23] = 80603be0 (NtCreateEvent) SSDT[0x24] = 8060be48 (NtCreateEventPair)

SSDT[0x25] = 8056d3ca (NtCreateFile) SSDT[0x26] = 8056bc5c (NtCreateIoCompletion) SSDT[0x27] = 805ca3ca (NtCreateJobObject)

При перехвате одной из этих функций руткит меняет значение в SSDT, подставляя свой код вместо кода ядра. В предыдущем примере запись со сдвигом 0x25 после изменения будет указывать на функцию в зараженном драйвере. С помощью этой модификации можно сделать невозможным открытие и анализ вредоносного файла. Обычно руткиты вызывают для этого оригинальную функцию NtCreateFile

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

w

 

 

to

 

 

250  Часть III  •  Продвинутый динамический анализ

w Click

 

 

 

 

 

 

 

 

 

 

 

o

m

 

w

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

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

Анализ руткитов на практике

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

Первым и самым очевидным способом проверки является изучение самой SSDTтаблицы. Просмотреть ее можно с помощью WinDbg; она имеет сдвиг, который хранится в nt!KeServiceDescriptorTable. Все сдвиги в SSDT должны указывать на функции, которые находятся в границах модуля NT, поэтому первым делом нужно получить эти границы. В нашем случае ntoskrnl.exe начинается с адреса 804d7000 и заканчивается в 806cd580. Если функция перехватывается руткитом, она, скорее всего, выходит за эти рамки. В ходе изучения SSDT мы обнаруживаем функцию, которая, как нам кажется, не вписывается в модуль NT. В листинге 10.13 показан отрывок из SSDT-таблицы.

Листинг 10.13. Простая SSDT-таблица, одну запись которой переопределил руткит

kd> lm m nt

 

 

 

 

...

 

 

 

 

8050122c

805c9928

805c98d8

8060aea6

805aa334

8050123c

8060a4be

8059cbbc

805a4786

805cb406

8050124c

804feed0

8060b5c4

8056ae64

805343f2

8050125c

80603b90

805b09c0

805e9694

80618a56

8050126c

805edb86

80598e34

80618caa

805986e6

8050127c

805401f0

80636c9c

805b28bc

80603be0

8050128c

8060be48

f7ad94a4

8056bc5c

805ca3ca

8050129c

805ca102

80618e86

8056d4d8

8060c240

805012ac

8056d404

8059fba6

80599202

805c5f8e

Значение со сдвигом 0x25 в этой таблице указывает на функцию, которая выходит за пределы модуля ntoskrnl, поэтому ее, вероятно, перехватывает руткит. В данном случае она называется NtCreateFile. Для определения ее имени можно посмотреть, что находится по этому сдвигу в SSDT незараженной системы. Чтобы узнать, на какой модуль указывает переопределенная запись, можно вывести список открытых модулей с помощью команды lm, как это показано в листинге 10.14. Все модули ядра являются драйверами. После исследования мы обнаруживаем, что адрес 0xf7ad94a4 находится в драйвере с названием Rootkit.

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Глава 10. Отладка ядра с помощью WinDbg   251

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Листинг 10.14. Поиск драйвера, содержащего определенный адрес, с помощью команды lm

kd>lm

 

 

 

...

 

 

 

f7ac7000

f7ac8580

intelide

(deferred)

f7ac9000

f7aca700

dmload

(deferred)

f7ad9000

f7ada680

Rootkit

(deferred)

f7aed000

f7aee280

vmmouse

(deferred)

...

 

 

 

Теперь мы можем приступить к анализу драйвера и кода перехватчика. Нас интересуют две вещи: участок кода, переопределяющий запись в таблице, и функция, которая выполняет перехват. В первом случае проще всего воспользоваться IDA Pro и поискать ссылки на функцию-перехватчик. В листинге 10.15 показан ассемблерный код, который переопределяет SSDT.

Листинг 10.15. Код руткита, который устанавливает перехватчик в SSDT-таблицу

00010D0D

push

offset aNtcreatefile

; "NtCreateFile"

00010D12

lea

eax, [ebp+NtCreateFileName]

00010D15

push

eax

; DestinationString

00010D16

mov

edi, ds:RtlInitUnicodeString

00010D1C

call

edi ; RtlInitUnicodeString

00010D1E

push

offset aKeservicedescr ; "KeServiceDescriptorTable"

00010D23

lea

eax, [ebp+KeServiceDescriptorTableString]

00010D26

push

eax

; DestinationString

00010D27

call

edi ; RtlInitUnicodeString

00010D29

lea

eax, [ebp+NtCreateFileName]

00010D2C

push

eax

; SystemRoutineName

00010D2D

mov

edi, ds:MmGetSystemRoutineAddress

00010D33

call

edi ; MmGetSystemRoutineAddress

00010D35

mov

ebx, eax

 

00010D37

lea

eax, [ebp+KeServiceDescriptorTableString]

00010D3A

push

eax

; SystemRoutineName

00010D3B

call

edi ; MmGetSystemRoutineAddress

00010D3D

mov

ecx, [eax]

 

00010D3F

xor

edx, edx

 

00010D41

 

; CODE XREF: sub_10CE7+68 j

00010D41

add

ecx, 4

 

00010D44

cmp

[ecx], ebx

 

00010D46

jz

short loc_10D51

 

00010D48

inc

edx

 

00010D49

cmp

edx, 11Ch

 

00010D4F

jl

short loc_10D41

 

00010D51

 

; CODE XREF: sub_10CE7+5F j

00010D51

mov

dword_10A0C, ecx

 

00010D57

mov

dword_10A08, ebx

 

00010D5D

mov

dword ptr [ecx], offset sub_104A4

Этот код переопределяет функцию NtCreateFile. Первые два вызова, и , создают строки NtCreateFile и KeServiceDescriptorTable. Они будут использоваться

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

w

 

 

to

 

 

252  Часть III  •  Продвинутый динамический анализ

w Click

 

 

 

 

 

 

 

 

 

 

 

o

m

 

w

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

при поиске экспортных адресов модуля ntoskrnl.exe, которые могут быть импортированы драйвером ядра, как и любые другие значения. Этот экспорт можно извлечь и на этапе выполнения. Мы не можем загрузить GetProcAddress, но в ядре есть аналогичная функция под названием MmGetSystemRoutineAddress, хоть и с небольшим отличием: она может получать экспортные адреса только из модулей ядра hal и ntoskrnl.

Первый вызов MmGetSystemRoutineAddress раскрывает адрес функции NtCreateFile, с помощью которой вредонос распознает, какую запись в SSDTтаблице нужно переопределить. Второй вызов MmGetSystemRoutineAddress дает нам адрес самой таблицы.

Далее, между и , находится цикл, который перебирает SSDT до тех пор, пока не найдет значение, совпадающее с адресом NtCreateFile. Вместо этого значения будет записан перехватчик.

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

Функция-перехватчик выполняет несколько простых действий. Одни запросы она отфильтровывает, а другим позволяет дойти до оригинального вызова NtCreateFile. Ее код показан в листинге 10.16.

Листинг 10.16. Код функции-перехватчика

000104A4

mov

edi, edi

000104A6

push

ebp

000104A7

mov

ebp, esp

000104A9

push

[ebp+arg_8]

000104AC

call

sub_10486

000104B1

test

eax, eax

000104B3

jz

short loc_104BB

000104B5

pop

ebp

000104B6

jmp

NtCreateFile

000104BB -----------------------------

000104BB

 

; CODE XREF: sub_104A4+F j

000104BB

mov

eax, 0C0000034h

000104C0

pop

ebp

000104C1

retn

2Ch

При одних запросах перехватчик переходит к оригинальной функции NtCre­ ateFile, а при других возвращает 0xC0000034. Значение 0xC0000034 соответствует коду STATUS_OBJECT_NAME_NOT_FOUND. Вызов содержит код (здесь он не показан), проверяющий ObjectAttributes файла, который пользовательская программа пытается открыть (в ObjectAttributes содержится информация об объекте, например имя файла). Если функции NtCreateFile позволено продолжить, перехватчик возвращает ненулевое значение, а если руткит не позволяет открыть файл, возвращается ноль. Во втором случае пользовательское приложение выдаст ошибку, указывающую на то, что файл не существует. Таким образом можно помешать программам в пространстве пользователя получить дескрипторы определенных файлов, однако остальные вызовы NtCreateFile будут работать как обычно.