Повышение привилегий ядра Windows, еще один способ взлома защиты игрового процесса
Повышение привилегий ядра Windows, еще один способ взлома защиты игрового процесса

Повышение привилегий ядра Windows — еще один способ обойти защиту игры.

1. Ручка стола

1.1 Введение

когдапроцессодеялоЗащищать的时候 比如无法获取其процессручка Разрешения (OpenProcess) Или, когда вы не можете получить права доступа на чтение и запись в память, вы можете использовать этот метод для повышения привилегий.

необходимые знания,Понимание структуры системы Windows. Ручка стола.

Вы можете просмотреть ссылку на этот блог:

Принцип и анализ таблицы дескрипторов ядра x64windows PspCidTable — iBinary — Blog Park (cnblogs.com)

1.2 Принцип

Обработка структуры записи таблицы HANDLE_TABLE_ENTRY В нем записан участник Права доступа, необходимые для текущего дескриптора.

Структура следующая:

Язык кода:javascript
копировать
//0x8 bytes (sizeof)
union _HANDLE_TABLE_ENTRY
{
    volatile LONG VolatileLowValue;                                         //0x0
    LONG LowValue;                                                          //0x0
    struct
    {
        struct _HANDLE_TABLE_ENTRY_INFO* volatile InfoTable;                //0x0
    LONG HighValue;                                                         //0x4
    union _HANDLE_TABLE_ENTRY* NextFreeHandleEntry;                         //0x4
        struct _EXHANDLE LeafHandleValue;                                   //0x4
    };
    ULONG Unlocked:1;                                                       //0x0
    ULONG Attributes:2;                                                     //0x0
    struct
    {
        ULONG ObjectPointerBits:29;                                         //0x0
    LONG RefCountField;                                                     //0x4
    ULONG GrantedAccessBits:25;                                             //0x4
    ULONG ProtectFromClose:1;                                               //0x4
    ULONG NoRightsUpgrade:1;                                                //0x4
    };
    ULONG RefCnt:5;                                                         //0x4
}; 

Большинство из них состоят из консорциумов, и их основными областями деятельности являются GrantedAccessBits

Поэтому наш подход заключается в том, чтобы сначала получить пониженный в должности дескриптор, а затем изменить разрешения этого дескриптора на

Полные разрешения, то есть 0x1fffff . После завершения модификации мы можем использовать дескриптор с повышенными правами для выполнения наших операций.

2. Демонстрация кода

2.1 Код основного драйвера повышения привилегий

Код основного драйвера очень прост.

следующее:

Язык кода:javascript
копировать
#include <ntifs.h>
#include <ntddk.h>

typedef union _EXHANDLE
{
    struct
    {
        int TagBits : 2;
        int Index : 30;
    } u;
    void* GenericHandleOverlay;
    ULONG_PTR Value;
} EXHANDLE, *PEXHANDLE;

typedef struct _HANDLE_TABLE_ENTRY // Size=16
{
    union
    {
        ULONG_PTR VolatileLowValue; // Size=8 Offset=0
        ULONG_PTR LowValue; // Size=8 Offset=0
        struct _HANDLE_TABLE_ENTRY_INFO* InfoTable; // Size=8 Offset=0
        struct
        {
            ULONG_PTR Unlocked : 1; // Size=8 Offset=0 BitOffset=0 BitCount=1
            ULONG_PTR RefCnt : 16; // Size=8 Offset=0 BitOffset=1 BitCount=16
            ULONG_PTR Attributes : 3; // Size=8 Offset=0 BitOffset=17 BitCount=3
            ULONG_PTR ObjectPointerBits : 44; // Size=8 Offset=0 BitOffset=20 BitCount=44
        };
    };
    union
    {
        ULONG_PTR HighValue; // Size=8 Offset=8
        struct _HANDLE_TABLE_ENTRY* NextFreeHandleEntry; // Size=8 Offset=8
        union _EXHANDLE LeafHandleValue; // Size=8 Offset=8
        struct
        {
            ULONG GrantedAccessBits : 25; // Size=4 Offset=8 BitOffset=0 BitCount=25
            ULONG NoRightsUpgrade : 1; // Size=4 Offset=8 BitOffset=25 BitCount=1
            ULONG Spare : 6; // Size=4 Offset=8 BitOffset=26 BitCount=6
        };
    };
    ULONG TypeInfo; // Size=4 Offset=12
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;

typedef struct _HANDLE_TABLE
{
    ULONG NextHandleNeedingPool;
    long ExtraInfoPages;
    LONG_PTR TableCode;
    PEPROCESS QuotaProcess;
    LIST_ENTRY HandleTableList;
    ULONG UniqueProcessId;
    ULONG Flags;
    EX_PUSH_LOCK HandleContentionEvent;
    EX_PUSH_LOCK HandleTableLock;
    // More fields here...
} HANDLE_TABLE, *PHANDLE_TABLE;

typedef BOOLEAN(*EX_ENUMERATE_HANDLE_ROUTINE)(
    IN PHANDLE_TABLE HandleTable,
    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
    IN HANDLE Handle,
    IN PVOID EnumParameter
    );

#ifdef __cplusplus
extern "C"
{
#endif

    BOOLEAN NTAPI ExEnumHandleTable(
        IN PHANDLE_TABLE HandleTable,
        IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
        IN PVOID EnumParameter,
        OUT PHANDLE Handle);

    VOID FASTCALL ExfUnblockPushLock(
        IN OUT PEX_PUSH_LOCK PushLock,
        IN OUT PVOID WaitBlock
    );

#ifdef __cplusplus
}
#endif

typedef struct _HANDLE_INFO
{
    unsigned long process_id;
    unsigned long access;
    unsigned long long handle;
}HANDLE_INFO, *PHANDLE_INFO;



unsigned char callback(
    PHANDLE_TABLE pHandleTableAddress,
    PHANDLE_TABLE_ENTRY pHandleTableEntryInfo,
    HANDLE Handle,
    PVOID pContext)
{
#define ExpIsValidObjectEntry(Entry) ( (Entry) && (Entry->LowValue != 0) && (Entry->HighValue != -2) )

    unsigned char result = 0;
    if (MmIsAddressValid(pContext))
    {
        PHANDLE_INFO info = (PHANDLE_INFO)pContext;
        if (info->handle == (unsigned long long)Handle
            && MmIsAddressValid(pHandleTableEntryInfo)
            && ExpIsValidObjectEntry(pHandleTableEntryInfo)
            && pHandleTableEntryInfo->GrantedAccessBits != info->access)
        {
            pHandleTableEntryInfo->GrantedAccessBits = info->access;
            result = 1;
        }
    }

    if (pHandleTableEntryInfo) _InterlockedExchangeAdd8((char*)&pHandleTableEntryInfo->VolatileLowValue, 1);
    if (pHandleTableAddress && pHandleTableAddress->HandleContentionEvent) ExfUnblockPushLock(&pHandleTableAddress->HandleContentionEvent, NULL);

    return result;
}

void handleUpdateAccess(HANDLE_INFO info)
{
    PEPROCESS process{ 0 };
    NTSTATUS status = PsLookupProcessByProcessId((HANDLE)info.process_id, &process);
    if (NT_SUCCESS(status))
    {
        //dt _EPROCESS find ObjectTable  offset replace ox418 of offset
        PHANDLE_TABLE table_ptr = *(PHANDLE_TABLE*)((PUCHAR)process + 0x418);
        if (MmIsAddressValid(table_ptr)) ExEnumHandleTable(table_ptr, &callback, &info, NULL);

        ObDereferenceObject(process);
    }
}






VOID DriverUnload(PDRIVER_OBJECT)
{

}

EXTERN_C
NTSTATUS
DriverEntry(
    PDRIVER_OBJECT driver,
    PUNICODE_STRING)
{
    driver->DriverUnload = DriverUnload;

    HANDLE_INFO info{ 0 };
    info.process_id = 6288; //PID процесса, который необходимо повысить
    info.access = 0x1fffff; //Установить все разрешения
    info.handle = 0xA4;     //Повышаем права процесса, чтобы получить дескриптор Разрешения

    handleUpdateAccess(info);
    return STATUS_SUCCESS;
}

2.2 Примеры пользовательской программы и инструкций по использованию

Демонстрационный пример на уровне пользователя:

Язык кода:javascript
копировать
// ShutDownProtectProcess.cpp : Этот файл содержит "main" функция. Выполнение программы начнется и закончится здесь.
//

#include <windows.h>
#include <iostream>

using namespace std;


int main()
{
    //Вы можете получить более низкий уровень Разрешения  Например: PROCESS_QUERY_INFORMATION.
    HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, 7652);
    BOOL bRet = FALSE;
    cout << "HANDLE = " << hex << hProcess << endl;
    cout << "Start Terminate Process " << endl;
    bRet =  TerminateProcess(hProcess,0);
    if (bRet == FALSE)
    {
        cout << "TerminateProcess Error try two Terminate" << endl;
        system("pause"); //Подождите, пока будет установлен файл Ядро для обновления Разрешения, затем нажмите любую клавишу, чтобы продолжить
        bRet = TerminateProcess(hProcess, 0);
        if (bRet == FALSE)
        {
            cout << "Two TerminateProcess Error " << endl;
            system("pause");
            return 0;
        }
        {
            cout << "Two TerminateProcess Success " << endl;
            system("pause");
            return 0;
        }

    }

    else
    {
        cout << "one TerminateProcess Success " << endl;
        system("pause");
        return 0;
    }

    system("pause");
    return 0;

}

Потому что я не инкапсулировал связь с ядром. Поэтому после запуска программы USER она будет ждать, пока пользователь вручную установит драйвер.

PID в драйвере необходимо изменить на идентификатор программы USER, а HANDLE, полученный пользователем, необходимо распечатать и изменить в драйвере.

Затем перекомпилируйте драйвер и установите его. После установки ручка будет поднята. В это время пользовательская программа продолжает работать, завершая работу защищенной программы блокнота.

2.3 Исходный код демонстрации драйвера защиты процесса

Язык кода:javascript
копировать
#include <ntifs.h>
#include <ntstrsafe.h>
#define PROCESS_TERMINATE         (0x0001)  // winnt
#define PROCESS_CREATE_THREAD     (0x0002)  // winnt
#define PROCESS_SET_SESSIONID     (0x0004)  // winnt
#define PROCESS_VM_OPERATION      (0x0008)  // winnt
#define PROCESS_VM_READ           (0x0010)  // winnt
#define PROCESS_VM_WRITE          (0x0020)  // winnt
// begin_ntddk begin_wdm begin_ntifs
#define PROCESS_DUP_HANDLE        (0x0040)  // winnt
// end_ntddk end_wdm end_ntifs
#define PROCESS_CREATE_PROCESS    (0x0080)  // winnt
#define PROCESS_SET_QUOTA         (0x0100)  // winnt
#define PROCESS_SET_INFORMATION   (0x0200)  // winnt
#define PROCESS_QUERY_INFORMATION (0x0400)  // winnt
#define PROCESS_SET_PORT          (0x0800)
#define PROCESS_SUSPEND_RESUME    (0x0800)  // winnt
PVOID g_ObjHandle;


extern "C" NTKERNELAPI
UCHAR * PsGetProcessImageFileName(__in PEPROCESS Process);

OB_PREOP_CALLBACK_STATUS MyObjectCallBack(
    PVOID RegistrationContext,
    POB_PRE_OPERATION_INFORMATION OperationInformation
)
{
    UNREFERENCED_PARAMETER(RegistrationContext);
    PEPROCESS pProcess = NULL;
    CHAR *pszName = NULL;

    pProcess = (PEPROCESS)OperationInformation->Object;
    pszName = (CHAR*)PsGetProcessImageFileName(pProcess);

    //Определяем, следует ли открывать флаг процесса
    if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
    {
        //Получаем совпадение имен
        if (strstr(pszName, (CHAR*)"notepad"))
        {
            KdPrint(("%s \r\n", pszName));
            //Определяем, закончилось ли это
            if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess
                & PROCESS_TERMINATE) == 1)
            {
                //Если оно наше, ставим DesiredAccess Разрешения. Убираем конец Разрешения.
                OperationInformation->Parameters->CreateHandleInformation.DesiredAccess
                    = (ULONG)~PROCESS_TERMINATE;
                return OB_PREOP_SUCCESS;
            }
        }
    }


    return OB_PREOP_SUCCESS;

}
VOID InitHook()
{
    //Выполняем КРЮК Как написать перехватчики обратного вызова. 
    OB_OPERATION_REGISTRATION oper; //Ваша функция обратного вызова и ее тип помещаются в эту структуру, которая может представлять собой массив структур.
    OB_CALLBACK_REGISTRATION CallbackRegistration;
    CallbackRegistration.Version = OB_FLT_REGISTRATION_VERSION; //номер версии
    CallbackRegistration.OperationRegistrationCount = 1;//Следующие несколько перехватчиков, то есть количество массивов структур
    RtlUnicodeStringInit(&CallbackRegistration.Altitude, L"600000");//Укажите строку UNICODE, чтобы указать, что вы делаете
    CallbackRegistration.RegistrationContext = NULL;         //Каковы параметры при поступлении вашей функции обратного вызова? Здесь указано.
    CallbackRegistration.OperationRegistration = &oper; //Настройка типа структуры крючка.
    //Присвоение значения структуре перехвата
    oper.ObjectType = PsProcessType; //Тип процессной операции. Когда процессная операция возвращается. PsThreadType — операция потока.
    oper.Operations = OB_OPERATION_HANDLE_CREATE; //Тип операции должен быть открыт и повторен.
    oper.PreOperation = MyObjectCallBack; //Есть два указателя: передний указатель и задний указатель. Значения такие. Будете ли вы проинформированы до или после создания процесса?
    oper.PostOperation = NULL;
    ObRegisterCallbacks(&CallbackRegistration, &g_ObjHandle);
}

VOID UnHook()
{
    ObUnRegisterCallbacks(g_ObjHandle);
}





VOID
DriverUnLoad(
    _In_ struct _DRIVER_OBJECT *DriverObject
)
{
    UNREFERENCED_PARAMETER(DriverObject);
    UnHook();
}

typedef struct _LDR_DATA_TABLE_ENTRY {
    LIST_ENTRY64    InLoadOrderLinks;
    LIST_ENTRY64    InMemoryOrderLinks;
    LIST_ENTRY64    InInitializationOrderLinks;
    PVOID            DllBase;
    PVOID            EntryPoint;
    ULONG            SizeOfImage;
    UNICODE_STRING    FullDllName;
    UNICODE_STRING     BaseDllName;
    ULONG            Flags;
    USHORT            LoadCount;
    USHORT            TlsIndex;
    PVOID            SectionPointer;
    ULONG            CheckSum;
    PVOID            LoadedImports;
    PVOID            EntryPointActivationContext;
    PVOID            PatchInformation;
    LIST_ENTRY64    ForwarderLinks;
    LIST_ENTRY64    ServiceTagLinks;
    LIST_ENTRY64    StaticLinks;
    PVOID            ContextInformation;
    ULONG            OriginalBase;
    LARGE_INTEGER    LoadTime;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;


extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{
    UNREFERENCED_PARAMETER(pRegPath);
    PLDR_DATA_TABLE_ENTRY ldr;
    ldr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
    ldr->Flags |= 0x20;

    pDriverObj->DriverUnload = DriverUnLoad;

    InitHook();
    return STATUS_SUCCESS;
}

//Относительно полный код

Язык кода:javascript
копировать
#define PROCESS_TERMINATE (0x0001)
#define PROCESS_CREATE_THREAD (0x0002)
#define PROCESS_SET_SESSIONID (0x0004)
#define PROCESS_VM_OPERATION (0x0008)
#define PROCESS_VM_READ (0x0010)
#define PROCESS_VM_WRITE (0x0020)
#define PROCESS_DUP_HANDLE (0x0040)
#define PROCESS_CREATE_PROCESS (0x0080)
#define PROCESS_SET_QUOTA (0x0100)
#define PROCESS_SET_INFORMATION (0x0200)
#define PROCESS_QUERY_INFORMATION (0x0400)
#define PROCESS_SUSPEND_RESUME (0x0800)
#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
#define PROCESS_SET_LIMITED_INFORMATION (0x2000)

Примечание. Удаление: ObUnRegisterCallbacks (obHandle);
NTSTATUS ProtectProcess()
{
	OB_CALLBACK_REGISTRATION obReg;
	OB_OPERATION_REGISTRATION opReg;
	memset(&obReg, 0, sizeof(obReg));
	obReg.Version = ObGetFilterVersion();
	obReg.OperationRegistrationCount = 1;
	obReg.RegistrationContext = NULL;
	RtlInitUnicodeString(&obReg.Altitude, L"321000");
	memset(&opReg, 0, sizeof(opReg));
	opReg.ObjectType = PsProcessType;
	opReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
	opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall;
	obReg.OperationRegistration = &opReg;
	return ObRegisterCallbacks(&obReg, &obHandle);
}
OB_PREOP_CALLBACK_STATUS preCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
{
	HANDLE pid = PsGetProcessId((PEPROCESS)pOperationInformation->Object);
	if (pid == PID)
	{
		if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
		{
			if (pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess & PROCESS_TERMINATE)
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= (~PROCESS_TERMINATE);
			if (pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess & PROCESS_VM_OPERATION)
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= (~PROCESS_VM_OPERATION);
			if (pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess & PROCESS_VM_READ)
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= (~PROCESS_VM_READ);
			if (pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess & PROCESS_VM_WRITE)
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= (~PROCESS_VM_WRITE);
			if (pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess & PROCESS_SUSPEND_RESUME)
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= (~PROCESS_SUSPEND_RESUME);
		}
		if (pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
		{
			if (pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess & PROCESS_TERMINATE)
				pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= (~PROCESS_TERMINATE);
			if (pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess & PROCESS_VM_OPERATION)
				pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= (~PROCESS_VM_OPERATION);
			if (pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess & PROCESS_VM_READ)
				pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= (~PROCESS_VM_READ);
			if (pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess & PROCESS_VM_WRITE)
				pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= (~PROCESS_VM_WRITE);
			if (pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess & PROCESS_SUSPEND_RESUME)
				pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= (~PROCESS_SUSPEND_RESUME);
		}
	}
	return OB_PREOP_SUCCESS;
}

3. Реализация кода BlockBone

Фактически этот код реализован в BlockBone.

кодследующее:

Сначала определите необходимую структуру

Язык кода:javascript
копировать
#define EX_ADDITIONAL_INFO_SIGNATURE (ULONG_PTR)(-2)
typedef union _EXHANDLE
{
    struct
    {
        int TagBits : 2;
        int Index : 30;
    } u;
    void * GenericHandleOverlay;
    ULONG_PTR Value;
} EXHANDLE, *PEXHANDLE;

typedef struct _HANDLE_TABLE
{
    ULONG NextHandleNeedingPool;
    long ExtraInfoPages;
    LONG_PTR TableCode;
    PEPROCESS QuotaProcess;
    LIST_ENTRY HandleTableList;
    ULONG UniqueProcessId;
    ULONG Flags;
    EX_PUSH_LOCK HandleContentionEvent;
    EX_PUSH_LOCK HandleTableLock;
    // More fields here...
} HANDLE_TABLE, *PHANDLE_TABLE;

typedef struct _HANDLE_TABLE_ENTRY // Size=16
{
    union
    {
        ULONG_PTR VolatileLowValue; // Size=8 Offset=0
        ULONG_PTR LowValue; // Size=8 Offset=0
        struct _HANDLE_TABLE_ENTRY_INFO * InfoTable; // Size=8 Offset=0
        struct
        {
            ULONG_PTR Unlocked : 1; // Size=8 Offset=0 BitOffset=0 BitCount=1
            ULONG_PTR RefCnt : 16; // Size=8 Offset=0 BitOffset=1 BitCount=16
            ULONG_PTR Attributes : 3; // Size=8 Offset=0 BitOffset=17 BitCount=3
            ULONG_PTR ObjectPointerBits : 44; // Size=8 Offset=0 BitOffset=20 BitCount=44
        };
    };
    union
    {
        ULONG_PTR HighValue; // Size=8 Offset=8
        struct _HANDLE_TABLE_ENTRY * NextFreeHandleEntry; // Size=8 Offset=8
        union _EXHANDLE LeafHandleValue; // Size=8 Offset=8
        struct
        {
            ULONG GrantedAccessBits : 25; // Size=4 Offset=8 BitOffset=0 BitCount=25
            ULONG NoRightsUpgrade : 1; // Size=4 Offset=8 BitOffset=25 BitCount=1
            ULONG Spare : 6; // Size=4 Offset=8 BitOffset=26 BitCount=6
        };
    };
    ULONG TypeInfo; // Size=4 Offset=12
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;


/// <summary>
/// Input for IOCTL_BLACKBONE_GRANT_ACCESS
/// </summary>
typedef struct _HANDLE_GRANT_ACCESS
{
    ULONGLONG  handle;      // Handle to modify
    ULONG      pid;         // Process ID
    ULONG      access;      // Access flags to grant
} HANDLE_GRANT_ACCESS, *PHANDLE_GRANT_ACCESS;

#define IOCTL_BLACKBONE_GRANT_ACCESS   (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define STATUS_WAIT_0                           ((NTSTATUS)0x00000000L) // winnt

typedef BOOLEAN(*EX_ENUMERATE_HANDLE_ROUTINE)(
#if !defined(_WIN7_)
    IN PHANDLE_TABLE HandleTable,
#endif
    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
    IN HANDLE Handle,
    IN PVOID EnumParameter
    );

extern "C" NTKERNELAPI
BOOLEAN
ExEnumHandleTable(
    IN PHANDLE_TABLE HandleTable,
    IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
    IN PVOID EnumParameter,
    OUT PHANDLE Handle
);

extern "C" NTKERNELAPI
VOID
FASTCALL
ExfUnblockPushLock(
    IN OUT PEX_PUSH_LOCK PushLock,
    IN OUT PVOID WaitBlock
);

#define ExpIsValidObjectEntry(Entry) \
    ( (Entry != NULL) && (Entry->LowValue != 0) && (Entry->HighValue != EX_ADDITIONAL_INFO_SIGNATURE) )

Основной код следующий:

Язык кода:javascript
копировать
/// <summary>
/// Check if process is terminating
/// </summary>
/// <param name="imageBase">Process</param>
/// <returns>If TRUE - terminating</returns>
BOOLEAN BBCheckProcessTermination(PEPROCESS pProcess)
{
    LARGE_INTEGER zeroTime = { 0 };
    return KeWaitForSingleObject(pProcess, Executive, KernelMode, FALSE, &zeroTime) == STATUS_WAIT_0;
}


/// <summary>
/// Handle enumeration callback
/// </summary>
/// <param name="HandleTable">Process handle table</param>
/// <param name="HandleTableEntry">Handle entry</param>
/// <param name="Handle">Handle value</param>
/// <param name="EnumParameter">User context</param>
/// <returns>TRUE when desired handle is found</returns>
BOOLEAN BBHandleCallback(
#if !defined(_WIN7_)
    IN PHANDLE_TABLE HandleTable,
#endif
    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
    IN HANDLE Handle,
    IN PVOID EnumParameter
)
{

    BOOLEAN result = FALSE;
    ASSERT(EnumParameter);

    if (EnumParameter != NULL)
    {
        PHANDLE_GRANT_ACCESS pAccess = (PHANDLE_GRANT_ACCESS)EnumParameter;
        if (Handle == (HANDLE)pAccess->handle)
        {
            if (ExpIsValidObjectEntry(HandleTableEntry))
            {
                // Update access
                HandleTableEntry->GrantedAccessBits = pAccess->access;
                result = TRUE;
            }
            else
            {

            }
        }
    }

#if !defined(_WIN7_)
    // Release implicit locks
    _InterlockedExchangeAdd8((char*)&HandleTableEntry->VolatileLowValue, 1);  // Set Unlocked flag to 1
    if (HandleTable != NULL && HandleTable->HandleContentionEvent)
        ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
#endif

    return result;
}

/// <summary>
/// Change handle granted access
/// </summary>
/// <param name="pAccess">Request params</param>
/// <returns>Status code</returns>
NTSTATUS BBGrantAccess(IN PHANDLE_GRANT_ACCESS pAccess)
{
    NTSTATUS status = STATUS_SUCCESS;
    PEPROCESS pProcess = NULL;


    status = PsLookupProcessByProcessId((HANDLE)pAccess->pid, &pProcess);
    if (NT_SUCCESS(status) && BBCheckProcessTermination(pProcess))
        status = STATUS_PROCESS_IS_TERMINATING;

    if (NT_SUCCESS(status))
    {
        PHANDLE_TABLE pTable = *(PHANDLE_TABLE*)((PUCHAR)pProcess + 0x418);/*Найдите смещение OBJECTTABLE каждого EPROCESS в соответствии с системой*/
        BOOLEAN found = ExEnumHandleTable(pTable, &BBHandleCallback, pAccess, NULL);
        if (found == FALSE)
            status = STATUS_NOT_FOUND;
    }
    else
    {

    }

    if (pProcess)
        ObDereferenceObject(pProcess);

    return status;
}

Используйте тот же метод, что и выше. Вы можете указать процесс, а затем указать дескриптор этого процесса, чтобы повысить привилегии этого дескриптора.

4. Рисунок эффекта

Сначала вы можете увидеть РУЧКУ, а затем закрыть блокнот в первый раз. Поскольку драйвер защиты загружен, первое закрытие блокнота не удается.

Затем попробуйте закрыть блокнот во второй раз. В это время пользователю будет предложено нажать любую клавишу для продолжения. Ожидая нажатия любой клавиши, сначала загрузите драйвер повышения привилегий. пользовательскую программу и нажмите любую клавишу, чтобы продолжить.

Продолжение завершит защищенный процесс.

5. Взлом защиты игры

Эта статья демонстрирует это обычным способом. Если вы знаете принцип, вы сможете совершить прорыв самостоятельно. (Внедрение виртуальных разрешений, у которых нет разрешений на открытие и разрешений на запись, затем вы можете повысить привилегии, а затем использовать авторизованный дескриптор для работы.)

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose