Driver to disable BE process/thread object callbacks

Durum
Üzgünüz bu konu cevaplar için kapatılmıştır...
Üye
Katılım
13 Eyl 2018
Mesajlar
1
Tepki puanı
0
Ödüller
6
Yaş
26
7 HİZMET YILI
Basically, this dynamically gets the offset to the CallbackList in the OBJECT_TYPE structure (in a really shitty, long-winded way - pls improve) so this will work on any Windows version 7+. The other structures which I've labeled CALLBACK_ENTRY and CALLBACK_ENTRY_ITEM that are completely undocumented have not changed from Windows 7 to Windows 10. So, this will work on any version of Windows.

After getting the offset to the CallbackList, I just go through the linked list of both process and thread object callbacks and check the altitude string to see if it's BattlEye. If it is BattlEye (the altitude is 363220, source:
Bağlantıları görmek için lütfen Giriş Yap
) then I set the PreOperation and PostOperation callback functions to dummy functions in my own driver. This essentially disables the process/thread object callbacks set by BE, so you can use OpenProcess/OpenThread and do stuff as normal, pretty much.

There's also a function to restore the callbacks afterwards, so you could disable the callbacks, inject, then restore the callbacks. Nice.

main.c
Code:
Kod:
#include <ntifs.h>
#include <windef.h>
 
// Pre-Processor definitions for our I/O control codes.
#define REMOVE_BEOBJECT_CALLBACKS_IOCTL CTL_CODE(FILE_DEVICE_KS, 0x806, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
#define RESTORE_BEOBJECT_CALLBACKS_IOCTL CTL_CODE(FILE_DEVICE_KS, 0x807, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
 
// Global variable to our device.
PDEVICE_OBJECT deviceObj = NULL;
 
// QWORD
typedef unsigned __int64 QWORD;
 
// OLD_CALLBACKS
typedef struct _OLD_CALLBACKS {
    QWORD PreOperationProc;
    QWORD PostOperationProc;
    QWORD PreOperationThread;
    QWORD PostOperationThread;
} OLD_CALLBACKS, *POLD_CALLBACKS;
 
// CALLBACK_ENTRY
typedef struct _CALLBACK_ENTRY {
    WORD Version; // 0x0
    WORD OperationRegistrationCount; // 0x2
    DWORD unk1; // 0x4
    PVOID RegistrationContext; // 0x8
    UNICODE_STRING Altitude; // 0x10
} CALLBACK_ENTRY, *PCALLBACK_ENTRY; // header size: 0x20 (0x6C if you count the array afterwards - this is only the header. The array of CALLBACK_ENTRY_ITEMs is useless.)
 
// CALLBACK_ENTRY_ITEM
typedef struct _CALLBACK_ENTRY_ITEM {
    LIST_ENTRY CallbackList; // 0x0
    OB_OPERATION Operations; // 0x10
    DWORD Active; // 0x14
    CALLBACK_ENTRY *CallbackEntry; // 0x18
    PVOID ObjectType; // 0x20
    POB_PRE_OPERATION_CALLBACK PreOperation; // 0x28
    POB_POST_OPERATION_CALLBACK PostOperation; // 0x30
    QWORD unk1; // 0x38
} CALLBACK_ENTRY_ITEM, *PCALLBACK_ENTRY_ITEM; // size: 0x40
 
// Dummy object callback functions.
OB_PREOP_CALLBACK_STATUS DummyObjectPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) {
    return(OB_PREOP_SUCCESS);
}
VOID DummyObjectPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation) {
    return;
}
 
QWORD GetCallbackListOffset(void) {
    POBJECT_TYPE procType = *PsProcessType;
 
    __try {
        if (procType && MmIsAddressValid((void*)procType)) {
            for (int i = 0xF8; i > 0; i -= 8) {
                QWORD first = *(QWORD*)((QWORD)procType + i), second = *(QWORD*)((QWORD)procType + (i + 8));
                if (first && MmIsAddressValid((void*)first) && second && MmIsAddressValid((void*)second)) {
                    QWORD test1First = *(QWORD*)(first + 0x0), test1Second = *(QWORD*)(first + 0x8);
                    if (test1First && MmIsAddressValid((void*)test1First) && test1Second && MmIsAddressValid((void*)test1Second)) {
                        QWORD testObjectType = *(QWORD*)(first + 0x20);
                        if (testObjectType == (QWORD)procType)
                            return((QWORD)i);
                    }
                }
            }
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        return(0);
    }
}
 
void DisableBEObjectCallbacks(POLD_CALLBACKS oldCallbacks) {
    POBJECT_TYPE procType = *PsProcessType;
    if (procType && MmIsAddressValid((void*)procType)) {
        __try {
            QWORD callbackListOffset = GetCallbackListOffset();
            if (callbackListOffset && MmIsAddressValid((void*)((QWORD)procType + callbackListOffset))) {
                LIST_ENTRY *callbackList = (LIST_ENTRY*)((QWORD)procType + callbackListOffset);
                if (callbackList->Flink && MmIsAddressValid((void*)callbackList->Flink)) {
                    CALLBACK_ENTRY_ITEM *firstCallback = (CALLBACK_ENTRY_ITEM*)callbackList->Flink;
                    CALLBACK_ENTRY_ITEM *curCallback = firstCallback;
 
                    do {
                        // Make sure the callback is valid.
                        if (curCallback && MmIsAddressValid((void*)curCallback) && MmIsAddressValid((void*)curCallback->CallbackEntry)) {
                            ANSI_STRING altitudeAnsi = { 0 };
                            UNICODE_STRING altitudeUni = curCallback->CallbackEntry->Altitude;
                            RtlUnicodeStringToAnsiString(&altitudeAnsi, &altitudeUni, 1);
 
                            if (!strcmp(altitudeAnsi.Buffer, "363220")) { // Check if this is BattlEye. If it is, disable the callback.
                                if (curCallback->PreOperation) {
                                    oldCallbacks->PreOperationProc = (QWORD)curCallback->PreOperation;
                                    curCallback->PreOperation = DummyObjectPreCallback;
                                }
                                if (curCallback->PostOperation) {
                                    oldCallbacks->PostOperationProc = (QWORD)curCallback->PostOperation;
                                    curCallback->PostOperation = DummyObjectPostCallback;
                                }
                                RtlFreeAnsiString(&altitudeAnsi);
                                break;
                            }
 
                            RtlFreeAnsiString(&altitudeAnsi);
                        }
 
                        // Get the next callback.
                        curCallback = curCallback->CallbackList.Flink;
                    } while (curCallback != firstCallback);
                }
            }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            return;
        }
    }
 
    POBJECT_TYPE threadType = *PsThreadType;
    if (threadType && MmIsAddressValid((void*)threadType)) {
        __try {
            QWORD callbackListOffset = GetCallbackListOffset();
            if (callbackListOffset && MmIsAddressValid((void*)((QWORD)threadType + callbackListOffset))) {
                LIST_ENTRY *callbackList = (LIST_ENTRY*)((QWORD)threadType + callbackListOffset);
                if (callbackList->Flink && MmIsAddressValid((void*)callbackList->Flink)) {
                    CALLBACK_ENTRY_ITEM *firstCallback = (CALLBACK_ENTRY_ITEM*)callbackList->Flink;
                    CALLBACK_ENTRY_ITEM *curCallback = firstCallback;
 
                    do {
                        // Make sure the callback is valid.
                        if (curCallback && MmIsAddressValid((void*)curCallback) && MmIsAddressValid((void*)curCallback->CallbackEntry)) {
                            ANSI_STRING altitudeAnsi = { 0 };
                            UNICODE_STRING altitudeUni = curCallback->CallbackEntry->Altitude;
                            RtlUnicodeStringToAnsiString(&altitudeAnsi, &altitudeUni, 1);
 
                            if (!strcmp(altitudeAnsi.Buffer, "363220")) { // Check if this is BattlEye. If it is, disable the callback.
                                if (curCallback->PreOperation) {
                                    oldCallbacks->PreOperationThread = (QWORD)curCallback->PreOperation;
                                    curCallback->PreOperation = DummyObjectPreCallback;
                                }
                                if (curCallback->PostOperation) {
                                    oldCallbacks->PostOperationThread = (QWORD)curCallback->PostOperation;
                                    curCallback->PostOperation = DummyObjectPostCallback;
                                }
                                RtlFreeAnsiString(&altitudeAnsi);
                                break;
                            }
 
                            RtlFreeAnsiString(&altitudeAnsi);
                        }
 
                        // Get the next callback.
                        curCallback = curCallback->CallbackList.Flink;
                    } while (curCallback != firstCallback);
                }
            }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            return;
        }
    }
}
 
void RestoreBEObjectCallbacks(POLD_CALLBACKS oldCallbacks) {
    POBJECT_TYPE procType = *PsProcessType;
    if (procType && MmIsAddressValid((void*)procType)) {
        __try {
            QWORD callbackListOffset = GetCallbackListOffset();
            if (callbackListOffset && MmIsAddressValid((void*)((QWORD)procType + callbackListOffset))) {
                LIST_ENTRY *callbackList = (LIST_ENTRY*)((QWORD)procType + callbackListOffset);
                if (callbackList->Flink && MmIsAddressValid((void*)callbackList->Flink)) {
                    CALLBACK_ENTRY_ITEM *firstCallback = (CALLBACK_ENTRY_ITEM*)callbackList->Flink;
                    CALLBACK_ENTRY_ITEM *curCallback = firstCallback;
 
                    do {
                        // Make sure the callback is valid.
                        if (curCallback && MmIsAddressValid((void*)curCallback) && MmIsAddressValid((void*)curCallback->CallbackEntry)) {
                            ANSI_STRING altitudeAnsi = { 0 };
                            UNICODE_STRING altitudeUni = curCallback->CallbackEntry->Altitude;
                            RtlUnicodeStringToAnsiString(&altitudeAnsi, &altitudeUni, 1);
 
                            if (!strcmp(altitudeAnsi.Buffer, "363220")) { // Check if this is BattlEye. If it is, restore the callback.
                                if (curCallback->PreOperation && oldCallbacks->PreOperationProc)
                                    curCallback->PreOperation = (POB_PRE_OPERATION_CALLBACK)oldCallbacks->PreOperationProc;
                                if (curCallback->PostOperation && oldCallbacks->PostOperationProc)
                                    curCallback->PostOperation = (POB_POST_OPERATION_CALLBACK)oldCallbacks->PostOperationProc;
                                RtlFreeAnsiString(&altitudeAnsi);
                                break;
                            }
 
                            RtlFreeAnsiString(&altitudeAnsi);
                        }
 
                        // Get the next callback.
                        curCallback = curCallback->CallbackList.Flink;
                    } while (curCallback != firstCallback);
                }
            }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            return;
        }
    }
 
    POBJECT_TYPE threadType = *PsThreadType;
    if (threadType && MmIsAddressValid((void*)threadType)) {
        __try {
            QWORD callbackListOffset = GetCallbackListOffset();
            if (callbackListOffset && MmIsAddressValid((void*)((QWORD)threadType + callbackListOffset))) {
                LIST_ENTRY *callbackList = (LIST_ENTRY*)((QWORD)threadType + callbackListOffset);
                if (callbackList->Flink && MmIsAddressValid((void*)callbackList->Flink)) {
                    CALLBACK_ENTRY_ITEM *firstCallback = (CALLBACK_ENTRY_ITEM*)callbackList->Flink;
                    CALLBACK_ENTRY_ITEM *curCallback = firstCallback;
 
                    do {
                        // Make sure the callback is valid.
                        if (curCallback && MmIsAddressValid((void*)curCallback) && MmIsAddressValid((void*)curCallback->CallbackEntry)) {
                            ANSI_STRING altitudeAnsi = { 0 };
                            UNICODE_STRING altitudeUni = curCallback->CallbackEntry->Altitude;
                            RtlUnicodeStringToAnsiString(&altitudeAnsi, &altitudeUni, 1);
 
                            if (!strcmp(altitudeAnsi.Buffer, "363220")) { // Check if this is BattlEye. If it is, disable the callback.
                                if (curCallback->PreOperation && oldCallbacks->PreOperationThread)
                                    curCallback->PreOperation = (POB_PRE_OPERATION_CALLBACK)oldCallbacks->PreOperationThread;
                                if (curCallback->PostOperation && oldCallbacks->PostOperationThread)
                                    curCallback->PostOperation = (POB_POST_OPERATION_CALLBACK)oldCallbacks->PostOperationThread;
                                RtlFreeAnsiString(&altitudeAnsi);
                                break;
                            }
 
                            RtlFreeAnsiString(&altitudeAnsi);
                        }
 
                        // Get the next callback.
                        curCallback = curCallback->CallbackList.Flink;
                    } while (curCallback != firstCallback);
                }
            }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            return;
        }
    }
}
 
NTSTATUS ioRecieved(PDEVICE_OBJECT pDeviceObject, PIRP IRP) {
    PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(IRP);
    size_t size = 0;
 
    // Handle the I/O request if we need to.
    if (pIoStackLocation->Parameters.DeviceIoControl.IoControlCode == REMOVE_BEOBJECT_CALLBACKS_IOCTL){
        OLD_CALLBACKS oldCallbacks = { 0 };
        DisableBEObjectCallbacks(&oldCallbacks);
        memcpy(IRP->AssociatedIrp.SystemBuffer, &oldCallbacks, sizeof(OLD_CALLBACKS));
        size = sizeof(OLD_CALLBACKS);
    }
    if (pIoStackLocation->Parameters.DeviceIoControl.IoControlCode == RESTORE_BEOBJECT_CALLBACKS_IOCTL) {
        RestoreBEObjectCallbacks((POLD_CALLBACKS)IRP->AssociatedIrp.SystemBuffer);
        size = 0;
    }
 
    // Finish off.
    IRP->IoStatus.Status = STATUS_SUCCESS;
    IRP->IoStatus.Information = size;
    IofCompleteRequest(IRP, IO_NO_INCREMENT);
    return(STATUS_SUCCESS);
}
 
NTSTATUS CatchCreate(PDRIVER_OBJECT pDriverObject) {
    return(STATUS_SUCCESS);
}
 
NTSTATUS CatchClose(PDRIVER_OBJECT pDriverObject) {
    return(STATUS_SUCCESS);
}
 
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) {
    // Create the device and get everything set up.
    UNICODE_STRING deviceNameUnicodeString = { 0 }, deviceSymLinkUnicodeString = { 0 };
    RtlInitUnicodeString(&deviceNameUnicodeString, L"\\Device\\mmarkdrv");
    RtlInitUnicodeString(&deviceSymLinkUnicodeString, L"\\DosDevices\\mmarkdrv");
    IoCreateDevice(pDriverObject, 0, &deviceNameUnicodeString, FILE_DEVICE_KS, FILE_DEVICE_SECURE_OPEN, 0, &deviceObj);
    IoCreateSymbolicLink(&deviceSymLinkUnicodeString, &deviceNameUnicodeString);
 
    // Get all the major functions set up.
    pDriverObject->MajorFunction[IRP_MJ_CREATE] = CatchCreate;
    pDriverObject->MajorFunction[IRP_MJ_CLOSE] = CatchClose;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ioRecieved;
 
    return(STATUS_SUCCESS);
}
 
Moderatörün son düzenlenenleri:
Süper Üye
Katılım
10 Mar 2019
Mesajlar
632
Çözümler
5
Tepki puanı
49
Ödüller
6
Yaş
26
7 HİZMET YILI
this is def not ur work, u stole it from someone on another forum. ( not allowed to mention )
 
Onaylı Üye
Katılım
6 Haz 2020
Mesajlar
51
Tepki puanı
3
Ödüller
3
Yaş
26
5 HİZMET YILI
I also have this doubt, if anyone can help I will be forever grateful
 
Üye
Katılım
31 May 2020
Mesajlar
1
Tepki puanı
0
Ödüller
2
Yaş
36
6 HİZMET YILI
You could of just added it to a source file and upload as a zip instead, but will take a look at this. This will also be detected in a few days just so everyone who doesn't know, knows that now!
 
Onaylı Üye
Katılım
25 Haz 2020
Mesajlar
53
Çözümler
1
Tepki puanı
1
Ödüller
1
Yaş
33
5 HİZMET YILI
thanks for your hardwork will be high used
 
Durum
Üzgünüz bu konu cevaplar için kapatılmıştır...

Benzer Konular

Üst