Как известно, Patch-Guard защищает определенные критические части ОС, полный перечень тут:
0 : A generic data region
1 : Modification of a function or .pdata
2 : A processor IDT
3 : A processor GDT
4 : Type 1 process list corruption
5 : Type 2 process list corruption
6 : Debug routine modification
7 : Critical MSR modification
8 : Object type
9 : A processor IVT
a : Modification of a system service function
b : A generic session data region
c : Modification of a session function or .pdata
d : Modification of an import table
e : Modification of a session import table
f : Ps Win32 callout modification
10 : Debug switch routine modification
11 : IRP allocator modification
12 : Driver call dispatcher modification
13 : IRP completion dispatcher modification
14 : IRP deallocator modification
15 : A processor control register
16 : Critical floating point control register modification
17 : Local APIC modification
18 : Kernel notification callout modification
19 : Loaded module list modification
1a : Type 3 process list corruption
1b : Type 4 process list corruption
1c : Driver object corruption
1d : Executive callback object modification
1e : Modification of module padding
1f : Modification of a protected process
20 : A generic data region
21 : A page hash mismatch
22 : A session page hash mismatch
23 : Load config directory modification
24 : Inverted function table modification
25 : Session configuration modification
26 : An extended processor control register
27 : Type 1 pool corruption
28 : Type 2 pool corruption
29 : Type 3 pool corruption
2a : Type 4 pool corruption
2b : Modification of a function or .pdata
2c : Image integrity corruption
2d : Processor misconfiguration
2e : Type 5 process list corruption
2f : Process shadow corruption
30 : Retpoline code page corruption
101 : General pool corruption
102 : Modification of win32k.sys
И если большая часть того, что защищается понятно из названия, то для Object type это как-то не очевидно. Попробуем разобраться.
Предположим, есть задача перехвата создания/открытия объекта Device.
Ядро предоставляет ограниченный набор объектов, которые можно перехватить:
The ObRegisterCallbacks routine registers a list of callback routines for thread, process, and desktop handle operations.
Как видно, создание объекта Device не входит в этот набор и данная api не подходит.
Но выход есть. Так как Device это объект ядра, у него есть набор предопределенных функций:
struct _OBJECT_TYPE_INITIALIZER
{
...
VOID (*DumpProcedure)(VOID* arg1, struct _OBJECT_DUMP_CONTROL* arg2);
LONG (*OpenProcedure)(enum _OB_OPEN_REASON arg1, CHAR arg2, struct _EPROCESS* arg3, VOID* arg4, ULONG* arg5, ULONG arg6);
VOID (*CloseProcedure)(struct _EPROCESS* arg1, VOID* arg2, ULONG arg3, ULONG arg4);
VOID (*DeleteProcedure)(VOID* arg1);
union
{
LONG (*ParseProcedure)(VOID* arg1, VOID* arg2, struct _ACCESS_STATE* arg3, CHAR arg4, ULONG arg5, struct _UNICODE_STRING* arg6, struct _UNICODE_STRING* arg7, VOID* arg8, struct _SECURITY_QUALITY_OF_SERVICE* arg9, VOID** arg10);
LONG (*ParseProcedureEx)(VOID* arg1, VOID* arg2, struct _ACCESS_STATE* arg3, CHAR arg4, ULONG arg5, struct _UNICODE_STRING* arg6, struct _UNICODE_STRING* arg7, VOID* arg8, struct _SECURITY_QUALITY_OF_SERVICE* arg9, struct _OB_EXTENDED_PARSE_PARAMETERS* arg10, VOID** arg11);
};
LONG (*SecurityProcedure)(VOID* arg1, enum _SECURITY_OPERATION_CODE arg2, ULONG* arg3, VOID* arg4, ULONG* arg5, VOID** arg6, enum _POOL_TYPE arg7, struct _GENERIC_MAPPING* arg8, CHAR arg9);
LONG (*QueryNameProcedure)(VOID* arg1, UCHAR arg2, struct _OBJECT_NAME_INFORMATION* arg3, ULONG arg4, ULONG* arg5, CHAR arg6);
UCHAR (*OkayToCloseProcedure)(struct _EPROCESS* arg1, VOID* arg2, VOID* arg3, CHAR arg4);
...
};
Объект Device создается функцией IoCreateDevice, которая в свою очередь вызывает ObCreateObject + ObInsertObject.
ObInsertObject выполняет поиск имени на предмет уже существующего через ObpLookupObjectName => ParseProcedure и на этом шаге у объекта можно подменить ParseProcedure на свою, получив управление.
Однако, все эти манипуляции видит Patch Guard, и выдает на это свой вердикт ввиде BSOD'a:
Bug Check 0x109: CRITICAL_STRUCTURE_CORRUPTION
0x8 Object type
CRITICAL_STRUCTURE_CORRUPTION (109)
This BugCheck is generated when the kernel detects that critical kernel code or
data have been corrupted. There are generally three causes for a corruption:
1) A driver has inadvertently or deliberately modified critical kernel code
or data. See http://www.microsoft.com/whdc/driver/kernel/64bitPatching.mspx
2) A developer attempted to set a normal kernel breakpoint using a kernel
debugger that was not attached when the system was booted. Normal breakpoints,
"bp", can only be set if the debugger is attached at boot time. Hardware
breakpoints, "ba", can be set at any time.
3) A hardware corruption occurred, e.g. failing RAM holding kernel code or data.
Arguments:
Arg1: a3a0016274a8d5a6, Reserved
Arg2: b3b70de8c72b012a, Reserved
Arg3: ffffc209daaa6970, Failure type dependent information
Arg4: 0000000000000008, Type of corrupted region, can be
...
8 : Object type <=== Here I am!
...
Соответственно, это и есть ответ на вопрос: что такое защита Object type в Patch-Guard.
Правда остался еще один вопрос: как же в итоге поймать создание device object?
Довольно просто(если у вас есть ELAM driver) - с помощью провайдера Microsoft-Windows-Threat-Intelligence, eventId 31 THREATINT_DEVICE_OBJECT_LOAD(для unload'a eventId 32).
вторник, 26 декабря 2023 г.
Что такое защита Object type в Patch-Guard?
Подписаться на:
Сообщения (Atom)