вторник, 26 декабря 2023 г.

Что такое защита Object type в Patch-Guard?

Как известно, 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).

Комментариев нет:

Отправить комментарий