mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
excellent progress :)
This commit is contained in:
parent
9e6b71e5df
commit
ef4127c167
18 changed files with 884 additions and 15 deletions
138
driver/callbacks.c
Normal file
138
driver/callbacks.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
#include "callbacks.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "driver.h"
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
PQUEUE_HEAD report_queue = NULL;
|
||||
|
||||
VOID InitCallbackReportQueue( PBOOLEAN Status )
|
||||
{
|
||||
report_queue = QueueCreate();
|
||||
|
||||
if ( report_queue == NULL )
|
||||
*Status = FALSE;
|
||||
|
||||
*Status = TRUE;
|
||||
}
|
||||
|
||||
VOID DeleteCallbackReportQueueHead()
|
||||
{
|
||||
ExFreePoolWithTag( report_queue, QUEUE_POOL_TAG );
|
||||
}
|
||||
|
||||
VOID InsertReportToQueue( POPEN_HANDLE_FAILURE_REPORT Report )
|
||||
{
|
||||
QueuePush( report_queue, Report );
|
||||
}
|
||||
|
||||
PVOID PopFirstReportFromQueue( report_queue )
|
||||
{
|
||||
return QueuePop( report_queue );
|
||||
}
|
||||
|
||||
VOID ObPostOpCallbackRoutine(
|
||||
_In_ PVOID RegistrationContext,
|
||||
_In_ POB_POST_OPERATION_INFORMATION OperationInformation
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
OB_PREOP_CALLBACK_STATUS ObPreOpCallbackRoutine(
|
||||
_In_ PVOID RegistrationContext,
|
||||
_In_ POB_PRE_OPERATION_INFORMATION OperationInformation
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER( RegistrationContext );
|
||||
|
||||
/* access mask to completely strip permissions */
|
||||
ACCESS_MASK deny_access = SYNCHRONIZE | PROCESS_TERMINATE;
|
||||
|
||||
/* Access mask to be used for crss / lsass */
|
||||
ACCESS_MASK downgrade_access = 0;
|
||||
|
||||
/*
|
||||
* This callback routine is executed in the context of the thread that
|
||||
* is requesting to open said handle
|
||||
*/
|
||||
PEPROCESS process_creator = PsGetCurrentProcess();
|
||||
PEPROCESS target_process = ( PEPROCESS )OperationInformation->Object;
|
||||
|
||||
LONG target_process_id = PsGetProcessId( target_process );
|
||||
LONG process_creator_id = PsGetProcessId( process_creator );
|
||||
|
||||
LONG protected_process_id;
|
||||
LONG parent_process_id;
|
||||
|
||||
GetProtectedProcessId( &protected_process_id );
|
||||
GetProtectedProcessParentId( &parent_process_id );
|
||||
|
||||
LPCSTR process_creator_name = PsGetProcessImageFileName( process_creator );
|
||||
LPCSTR target_process_name = PsGetProcessImageFileName( target_process );
|
||||
|
||||
if ( protected_process_id == target_process_id)
|
||||
{
|
||||
if ( !strcmp( process_creator_name, "lsass.exe" ) || !strcmp( process_creator_name, "csrss.exe" ) )
|
||||
{
|
||||
/* We will downgrade these handles later */
|
||||
DEBUG_LOG( "Handles created by CSRSS and LSASS are allowed for now..." );
|
||||
}
|
||||
/* NOTE: try allowing only 1 handle from the proc creator */
|
||||
else if ( parent_process_id == process_creator_id )
|
||||
{
|
||||
/* Allow handles created by the protected process' creator i.e explorer, cmd etc. */
|
||||
DEBUG_LOG( "Process creator: %s handles are fine for now...", process_creator_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = deny_access;
|
||||
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = deny_access;
|
||||
DEBUG_LOG( "handle stripped from: %s", process_creator_name );
|
||||
}
|
||||
}
|
||||
|
||||
return OB_PREOP_SUCCESS;
|
||||
}
|
||||
|
||||
VOID ProcessCreateNotifyRoutine(
|
||||
_In_ HANDLE ParentId,
|
||||
_In_ HANDLE ProcessId,
|
||||
_In_ BOOLEAN Create
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PEPROCESS parent_process;
|
||||
PEPROCESS target_process;
|
||||
LONG parent_process_id;
|
||||
LPCSTR target_process_name = NULL;
|
||||
LPCSTR parent_process_name = NULL;
|
||||
|
||||
status = PsLookupProcessByProcessId( ParentId, &parent_process );
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
return;
|
||||
|
||||
status = PsLookupProcessByProcessId( ProcessId, &target_process );
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
return;
|
||||
|
||||
parent_process_name = PsGetProcessImageFileName( parent_process );
|
||||
|
||||
if ( !parent_process_name )
|
||||
return;
|
||||
|
||||
target_process_name = PsGetProcessImageFileName( target_process );
|
||||
|
||||
if ( !target_process_name )
|
||||
return;
|
||||
|
||||
if ( !strcmp( target_process_name, "notepad.exe") )
|
||||
{
|
||||
parent_process_id = PsGetProcessId( target_process );
|
||||
UpdateProtectedProcessId( parent_process_id );
|
||||
LOG_INFO( "Protected process parent proc id: %lx", parent_process_id );
|
||||
}
|
||||
}
|
47
driver/callbacks.h
Normal file
47
driver/callbacks.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef CALLBACKS_H
|
||||
#define CALLBACKS_H
|
||||
|
||||
#include <ntifs.h>
|
||||
#include <wdftypes.h>
|
||||
#include <wdf.h>
|
||||
|
||||
typedef struct _OPEN_HANDLE_FAILURE_REPORT
|
||||
{
|
||||
INT report_code;
|
||||
INT is_kernel_handle;
|
||||
LONG process_id;
|
||||
LONG thread_id;
|
||||
LONG desired_access;
|
||||
CHAR process_name[ 64 ];
|
||||
|
||||
}OPEN_HANDLE_FAILURE_REPORT, *POPEN_HANDLE_FAILURE_REPORT;
|
||||
|
||||
//handle access masks
|
||||
//https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
|
||||
#define PROCESS_CREATE_PROCESS 0x0080
|
||||
#define PROCESS_TERMINATE 0x0001
|
||||
#define PROCESS_CREATE_THREAD 0x0002
|
||||
#define PROCESS_DUP_HANDLE 0x0040
|
||||
#define PROCESS_QUERY_INFORMATION 0x0400
|
||||
#define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
|
||||
#define PROCESS_SET_INFORMATION 0x0200
|
||||
#define PROCESS_SET_QUOTA 0x0100
|
||||
#define PROCESS_SUSPEND_RESUME 0x0800
|
||||
#define PROCESS_VM_OPERATION 0x0008
|
||||
#define PROCESS_VM_READ 0x0010
|
||||
#define PROCESS_VM_WRITE 0x0020
|
||||
|
||||
VOID ObPostOpCallbackRoutine(
|
||||
_In_ PVOID RegistrationContext,
|
||||
_In_ POB_POST_OPERATION_INFORMATION OperationInformation
|
||||
);
|
||||
|
||||
OB_PREOP_CALLBACK_STATUS ObPreOpCallbackRoutine(
|
||||
_In_ PVOID RegistrationContext,
|
||||
_In_ POB_PRE_OPERATION_INFORMATION OperationInformation
|
||||
);
|
||||
|
||||
VOID InitCallbackReportQueue(PBOOLEAN Status);
|
||||
VOID DeleteCallbackReportQueueHead();
|
||||
|
||||
#endif
|
344
driver/common.h
344
driver/common.h
|
@ -116,4 +116,348 @@ Thread Information Block: (GS register)
|
|||
...
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ntifs.h>
|
||||
#include <wdftypes.h>
|
||||
|
||||
typedef struct _OBJECT_TYPE
|
||||
{
|
||||
LIST_ENTRY TypeList;
|
||||
UNICODE_STRING Name;
|
||||
PVOID DefaultObject;
|
||||
UCHAR Index;
|
||||
ULONG TotalNumberOfObjects;
|
||||
ULONG TotalNumberOfHandles;
|
||||
ULONG HighWaterNumberOfObjects;
|
||||
ULONG HighWaterNumberOfHandles;
|
||||
PVOID TypeInfo; //_OBJECT_TYPE_INITIALIZER
|
||||
EX_PUSH_LOCK TypeLock;
|
||||
ULONG Key;
|
||||
LIST_ENTRY CallbackList;
|
||||
|
||||
} OBJECT_TYPE, * POBJECT_TYPE;
|
||||
|
||||
typedef struct _PEB_LDR_DATA {
|
||||
BYTE Reserved1[ 8 ];
|
||||
PVOID Reserved2[ 3 ];
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
} PEB_LDR_DATA, * PPEB_LDR_DATA;
|
||||
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY {
|
||||
PVOID Reserved1[ 2 ];
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
PVOID Reserved2[ 2 ];
|
||||
PVOID DllBase;
|
||||
PVOID Reserved3[ 2 ];
|
||||
UNICODE_STRING FullDllName;
|
||||
BYTE Reserved4[ 8 ];
|
||||
PVOID Reserved5[ 3 ];
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4201) // we'll always use the Microsoft compiler
|
||||
union {
|
||||
ULONG CheckSum;
|
||||
PVOID Reserved6;
|
||||
} DUMMYUNIONNAME;
|
||||
#pragma warning(pop)
|
||||
ULONG TimeDateStamp;
|
||||
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
|
||||
|
||||
typedef struct _PEB {
|
||||
BYTE Reserved1[ 2 ];
|
||||
BYTE BeingDebugged;
|
||||
BYTE Reserved2[ 1 ];
|
||||
PVOID Reserved3[ 2 ];
|
||||
PPEB_LDR_DATA Ldr;
|
||||
PVOID ProcessParameters;
|
||||
PVOID Reserved4[ 3 ];
|
||||
PVOID AtlThunkSListPtr;
|
||||
PVOID Reserved5;
|
||||
ULONG Reserved6;
|
||||
PVOID Reserved7;
|
||||
ULONG Reserved8;
|
||||
ULONG AtlThunkSListPtr32;
|
||||
PVOID Reserved9[ 45 ];
|
||||
BYTE Reserved10[ 96 ];
|
||||
PVOID PostProcessInitRoutine;
|
||||
BYTE Reserved11[ 128 ];
|
||||
PVOID Reserved12[ 1 ];
|
||||
ULONG SessionId;
|
||||
} PEB, * PPEB;
|
||||
|
||||
typedef struct _PEB32 {
|
||||
UCHAR InheritedAddressSpace;
|
||||
UCHAR ReadImageFileExecOptions;
|
||||
UCHAR BeingDebugged;
|
||||
UCHAR BitField;
|
||||
ULONG Mutant;
|
||||
ULONG ImageBaseAddress;
|
||||
ULONG Ldr;
|
||||
ULONG ProcessParameters;
|
||||
ULONG SubSystemData;
|
||||
ULONG ProcessHeap;
|
||||
ULONG FastPebLock;
|
||||
ULONG AtlThunkSListPtr;
|
||||
ULONG IFEOKey;
|
||||
ULONG CrossProcessFlags;
|
||||
ULONG UserSharedInfoPtr;
|
||||
ULONG SystemReserved;
|
||||
ULONG AtlThunkSListPtr32;
|
||||
ULONG ApiSetMap;
|
||||
} PEB32, * PPEB32;
|
||||
|
||||
typedef struct _PEB_LDR_DATA32 {
|
||||
ULONG Length;
|
||||
UCHAR Initialized;
|
||||
ULONG SsHandle;
|
||||
LIST_ENTRY32 InLoadOrderModuleList;
|
||||
LIST_ENTRY32 InMemoryOrderModuleList;
|
||||
LIST_ENTRY32 InInitializationOrderModuleList;
|
||||
} PEB_LDR_DATA32, * PPEB_LDR_DATA32;
|
||||
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY32 {
|
||||
LIST_ENTRY32 InLoadOrderLinks;
|
||||
LIST_ENTRY32 InMemoryOrderLinks;
|
||||
LIST_ENTRY32 InInitializationOrderLinks;
|
||||
ULONG DllBase;
|
||||
ULONG EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STRING32 FullDllName;
|
||||
UNICODE_STRING32 BaseDllName;
|
||||
ULONG Flags;
|
||||
USHORT LoadCount;
|
||||
USHORT TlsIndex;
|
||||
LIST_ENTRY32 HashLinks;
|
||||
ULONG TimeDateStamp;
|
||||
} LDR_DATA_TABLE_ENTRY32, * PLDR_DATA_TABLE_ENTRY32;
|
||||
|
||||
typedef struct _HANDLE_TABLE_ENTRY_INFO
|
||||
{
|
||||
ULONG AuditMask;
|
||||
ULONG MaxRelativeAccessMask;
|
||||
|
||||
} HANDLE_TABLE_ENTRY_INFO, * PHANDLE_TABLE_ENTRY_INFO;
|
||||
|
||||
typedef union _EXHANDLE
|
||||
{
|
||||
struct
|
||||
{
|
||||
int TagBits : 2;
|
||||
int Index : 30;
|
||||
} u;
|
||||
void* GenericHandleOverlay;
|
||||
ULONG_PTR Value;
|
||||
} EXHANDLE, * PEXHANDLE;
|
||||
|
||||
#pragma warning(disable : 4214 4201)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct _POOL_HEADER // Size=16
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned long PreviousSize : 8; // Size=4 Offset=0 BitOffset=0 BitCount=8
|
||||
unsigned long PoolIndex : 8; // Size=4 Offset=0 BitOffset=8 BitCount=8
|
||||
unsigned long BlockSize : 8; // Size=4 Offset=0 BitOffset=16 BitCount=8
|
||||
unsigned long PoolType : 8; // Size=4 Offset=0 BitOffset=24 BitCount=8
|
||||
};
|
||||
unsigned long Ulong1; // Size=4 Offset=0
|
||||
};
|
||||
unsigned long PoolTag; // Size=4 Offset=4
|
||||
union
|
||||
{
|
||||
struct _EPROCESS* ProcessBilled; // Size=8 Offset=8
|
||||
struct
|
||||
{
|
||||
unsigned short AllocatorBackTraceIndex; // Size=2 Offset=8
|
||||
unsigned short PoolTagHash; // Size=2 Offset=10
|
||||
};
|
||||
};
|
||||
} POOL_HEADER, * PPOOL_HEADER;
|
||||
#pragma pack(pop)
|
||||
|
||||
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_FREE_LIST
|
||||
{
|
||||
EX_PUSH_LOCK FreeListLock;
|
||||
PHANDLE_TABLE_ENTRY FirstFreeHandleEntry;
|
||||
PHANDLE_TABLE_ENTRY LastFreeHandleEntry;
|
||||
LONG HandleCount;
|
||||
ULONG HighWaterMark;
|
||||
} HANDLE_TABLE_FREE_LIST, * PHANDLE_TABLE_FREE_LIST;
|
||||
|
||||
typedef struct _HANDLE_TRACE_DB_ENTRY
|
||||
{
|
||||
CLIENT_ID ClientId;
|
||||
PVOID Handle;
|
||||
ULONG Type;
|
||||
PVOID StackTrace[ 16 ];
|
||||
|
||||
} HANDLE_TRACE_DB_ENTRY, * PHANDLE_TRACE_DB_ENTRY;
|
||||
|
||||
|
||||
|
||||
typedef struct _HANDLE_TRACE_DEBUG_INFO
|
||||
{
|
||||
LONG RefCount;
|
||||
ULONG TableSize;
|
||||
ULONG BitMaskFlags;
|
||||
FAST_MUTEX CloseCompactionLock;
|
||||
ULONG CurrentStackIndex;
|
||||
HANDLE_TRACE_DB_ENTRY TraceDb[ 1 ];
|
||||
|
||||
} HANDLE_TRACE_DEBUG_INFO, * PHANDLE_TRACE_DEBUG_INFO;
|
||||
|
||||
typedef struct _HANDLE_TABLE
|
||||
{
|
||||
ULONG NextHandleNeedingPool;
|
||||
LONG ExtraInfoPages;
|
||||
ULONGLONG TableCode;
|
||||
PEPROCESS QuotaProcess;
|
||||
LIST_ENTRY HandleTableList;
|
||||
ULONG UniqueProcessId;
|
||||
union {
|
||||
ULONG Flags;
|
||||
struct {
|
||||
UCHAR StrictFIFO : 1;
|
||||
UCHAR EnableHandleExceptions : 1;
|
||||
UCHAR Rundown : 1;
|
||||
UCHAR Duplicated : 1;
|
||||
UCHAR RaiseUMExceptionOnInvalidHandleClose : 1;
|
||||
};
|
||||
};
|
||||
EX_PUSH_LOCK HandleContentionEvent;
|
||||
EX_PUSH_LOCK HandleTableLock;
|
||||
union {
|
||||
HANDLE_TABLE_FREE_LIST FreeLists[ 1 ];
|
||||
UCHAR ActualEntry[ 32 ];
|
||||
};
|
||||
|
||||
struct _HANDLE_TRACE_DEBUG_INFO* DebugInfo;
|
||||
|
||||
} HANDLE_TABLE, * PHANDLE_TABLE;
|
||||
|
||||
typedef BOOLEAN( *EX_ENUMERATE_HANDLE_ROUTINE )(
|
||||
IN PHANDLE_TABLE_ENTRY HandleTableEntry,
|
||||
IN HANDLE Handle,
|
||||
IN PVOID EnumParameter
|
||||
);
|
||||
|
||||
typedef struct _OBJECT_CREATE_INFORMATION
|
||||
{
|
||||
ULONG Attributes;
|
||||
PVOID RootDirectory;
|
||||
CHAR ProbeMode;
|
||||
ULONG PagedPoolCharge;
|
||||
ULONG NonPagedPoolCharge;
|
||||
ULONG SecurityDescriptorCharge;
|
||||
PVOID SecurityDescriptor;
|
||||
struct _SECURITY_QUALITY_OF_SERVICE* SecurityQos;
|
||||
struct _SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
|
||||
|
||||
} OBJECT_CREATE_INFORMATION, * POBJECT_CREATE_INFORMATION;
|
||||
|
||||
typedef struct _OBJECT_HEADER
|
||||
{
|
||||
LONGLONG PointerCount;
|
||||
union {
|
||||
LONGLONG HandleCount;
|
||||
PVOID NextToFree;
|
||||
};
|
||||
EX_PUSH_LOCK Lock;
|
||||
UCHAR TypeIndex;
|
||||
union {
|
||||
UCHAR TraceFlags;
|
||||
struct {
|
||||
UCHAR DbgRefTrace : 1;
|
||||
UCHAR DbgTracePermanent : 1;
|
||||
};
|
||||
};
|
||||
UCHAR InfoMask;
|
||||
union {
|
||||
UCHAR Flags;
|
||||
struct {
|
||||
UCHAR NewObject : 1;
|
||||
UCHAR KernelObject : 1;
|
||||
UCHAR KernelOnlyAccess : 1;
|
||||
UCHAR ExclusiveObject : 1;
|
||||
UCHAR PermanentObject : 1;
|
||||
UCHAR DefaultSecurityQuota : 1;
|
||||
UCHAR SingleHandleEntry : 1;
|
||||
UCHAR DeletedInline : 1;
|
||||
};
|
||||
};
|
||||
ULONG Reserved;
|
||||
union {
|
||||
POBJECT_CREATE_INFORMATION ObjectCreateInfo;
|
||||
PVOID QuotaBlockCharged;
|
||||
};
|
||||
PVOID SecurityDescriptor;
|
||||
QUAD Body;
|
||||
} OBJECT_HEADER, * POBJECT_HEADER;
|
||||
|
||||
NTKERNELAPI
|
||||
BOOLEAN
|
||||
ExEnumHandleTable(
|
||||
__in PHANDLE_TABLE HandleTable,
|
||||
__in EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
|
||||
__in PVOID EnumParameter,
|
||||
__out_opt PHANDLE Handle
|
||||
);
|
||||
|
||||
NTKERNELAPI
|
||||
POBJECT_TYPE
|
||||
NTAPI
|
||||
ObGetObjectType(
|
||||
_In_ PVOID Object
|
||||
);
|
||||
|
||||
typedef struct _EX_PUSH_LOCK_WAIT_BLOCK* PEX_PUSH_LOCK_WAIT_BLOCK;
|
||||
|
||||
NTKERNELAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
ExfUnblockPushLock(
|
||||
_Inout_ PEX_PUSH_LOCK PushLock,
|
||||
_Inout_opt_ PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock
|
||||
);
|
||||
|
||||
LPCSTR
|
||||
NTSYSAPI
|
||||
NTAPI
|
||||
PsGetProcessImageFileName(
|
||||
PEPROCESS Process
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,49 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "ioctl.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
PVOID callback_registration_handle;
|
||||
|
||||
LONG protected_process_id;
|
||||
LONG protected_process_parent_id;
|
||||
KGUARDED_MUTEX mutex;
|
||||
|
||||
VOID UpdateProtectedProcessId(
|
||||
_In_ LONG NewProcessId
|
||||
)
|
||||
{
|
||||
KeAcquireGuardedMutex( &mutex );
|
||||
protected_process_id = NewProcessId;
|
||||
KeReleaseGuardedMutex( &mutex );
|
||||
}
|
||||
|
||||
VOID GetProtectedProcessId(
|
||||
_Out_ PLONG ProcessId
|
||||
)
|
||||
{
|
||||
KeAcquireGuardedMutex( &mutex );
|
||||
*ProcessId = protected_process_id;
|
||||
KeReleaseGuardedMutex( &mutex );
|
||||
}
|
||||
|
||||
VOID GetProtectedProcessParentId(
|
||||
_Out_ PLONG ProcessId
|
||||
)
|
||||
{
|
||||
KeAcquireGuardedMutex( &mutex );
|
||||
*ProcessId = protected_process_parent_id;
|
||||
KeReleaseGuardedMutex( &mutex );
|
||||
}
|
||||
|
||||
VOID UpdateProtectedProcessParentId(
|
||||
_In_ LONG NewProcessId
|
||||
)
|
||||
{
|
||||
KeAcquireGuardedMutex( &mutex );
|
||||
protected_process_parent_id = NewProcessId;
|
||||
KeReleaseGuardedMutex( &mutex );
|
||||
}
|
||||
|
||||
VOID DriverUnload(
|
||||
_In_ PDRIVER_OBJECT DriverObject
|
||||
|
@ -18,6 +61,7 @@ NTSTATUS DriverEntry(
|
|||
{
|
||||
UNREFERENCED_PARAMETER( RegistryPath );
|
||||
|
||||
BOOLEAN flag;
|
||||
NTSTATUS status;
|
||||
|
||||
status = IoCreateDevice(
|
||||
|
@ -49,6 +93,43 @@ NTSTATUS DriverEntry(
|
|||
DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = DeviceControl;
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
|
||||
KeInitializeGuardedMutex( &mutex );
|
||||
|
||||
InitCallbackReportQueue(&flag);
|
||||
|
||||
if ( !flag )
|
||||
{
|
||||
IoDeleteSymbolicLink( &DEVICE_SYMBOLIC_LINK );
|
||||
IoDeleteDevice( DriverObject->DeviceObject );
|
||||
return STATUS_FAILED_DRIVER_ENTRY;
|
||||
}
|
||||
|
||||
OB_CALLBACK_REGISTRATION callback_registration = { 0 };
|
||||
OB_OPERATION_REGISTRATION operation_registration = { 0 };
|
||||
|
||||
operation_registration.ObjectType = PsProcessType;
|
||||
operation_registration.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
|
||||
operation_registration.PreOperation = ObPreOpCallbackRoutine;
|
||||
operation_registration.PostOperation = ObPostOpCallbackRoutine;
|
||||
|
||||
callback_registration.Version = OB_FLT_REGISTRATION_VERSION;
|
||||
callback_registration.OperationRegistration = &operation_registration;
|
||||
callback_registration.OperationRegistrationCount = 1;
|
||||
callback_registration.RegistrationContext = NULL;
|
||||
|
||||
status = ObRegisterCallbacks(
|
||||
&callback_registration,
|
||||
&callback_registration_handle
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DeleteCallbackReportQueueHead();
|
||||
IoDeleteSymbolicLink( &DEVICE_SYMBOLIC_LINK );
|
||||
IoDeleteDevice( DriverObject->DeviceObject );
|
||||
return STATUS_FAILED_DRIVER_ENTRY;
|
||||
}
|
||||
|
||||
DEBUG_LOG( "DonnaAC Driver Entry Complete. type: %lx", DriverObject->DeviceObject->DeviceType );
|
||||
|
||||
return status;
|
||||
|
|
|
@ -8,4 +8,20 @@
|
|||
UNICODE_STRING DEVICE_NAME = RTL_CONSTANT_STRING( L"\\Device\\DonnaAC" );
|
||||
UNICODE_STRING DEVICE_SYMBOLIC_LINK = RTL_CONSTANT_STRING( L"\\??\\DonnaAC" );
|
||||
|
||||
VOID UpdateProtectedProcessId(
|
||||
_In_ LONG NewProcessId
|
||||
);
|
||||
|
||||
VOID GetProtectedProcessId(
|
||||
_Out_ PLONG ProcessId
|
||||
);
|
||||
|
||||
VOID GetProtectedProcessParentId(
|
||||
_Out_ PLONG ProcessId
|
||||
);
|
||||
|
||||
VOID UpdateProtectedProcessParentId(
|
||||
_In_ LONG NewProcessId
|
||||
);
|
||||
|
||||
#endif
|
|
@ -117,17 +117,21 @@
|
|||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="callbacks.c" />
|
||||
<ClCompile Include="driver.c" />
|
||||
<ClCompile Include="ioctl.c" />
|
||||
<ClCompile Include="modules.c" />
|
||||
<ClCompile Include="nmi.c" />
|
||||
<ClCompile Include="queue.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="callbacks.h" />
|
||||
<ClInclude Include="common.h" />
|
||||
<ClInclude Include="driver.h" />
|
||||
<ClInclude Include="ioctl.h" />
|
||||
<ClInclude Include="modules.h" />
|
||||
<ClInclude Include="nmi.h" />
|
||||
<ClInclude Include="queue.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -36,6 +36,12 @@
|
|||
<ClCompile Include="modules.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="callbacks.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="queue.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="driver.h">
|
||||
|
@ -53,5 +59,11 @@
|
|||
<ClInclude Include="modules.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="callbacks.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="queue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "nmi.h"
|
||||
#include "modules.h"
|
||||
#include "driver.h"
|
||||
|
||||
NTSTATUS DeviceControl(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
|
@ -88,6 +89,13 @@ NTSTATUS DeviceControl(
|
|||
|
||||
break;
|
||||
|
||||
case IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH:;
|
||||
|
||||
PDRIVER_INITIATION_INFORMATION information = ( PDRIVER_INITIATION_INFORMATION )Irp->AssociatedIrp.SystemBuffer;
|
||||
UpdateProtectedProcessId( information->protected_process_id );
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
DEBUG_ERROR( "Invalid IOCTL passed to driver" );
|
||||
break;
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
|
||||
#define IOCCTL_RUN_NMI_CALLBACKS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2001, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_VALIDATE_DRIVER_OBJECTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2002, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2004, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
typedef struct _DRIVER_INITIATION_INFORMATION
|
||||
{
|
||||
LONG protected_process_id;
|
||||
|
||||
} DRIVER_INITIATION_INFORMATION, * PDRIVER_INITIATION_INFORMATION;
|
||||
|
||||
NTSTATUS DeviceControl(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
|
|
70
driver/queue.c
Normal file
70
driver/queue.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include "queue.h"
|
||||
|
||||
PQUEUE_HEAD QueueCreate()
|
||||
{
|
||||
PQUEUE_HEAD head = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( PQUEUE_HEAD ), QUEUE_POOL_TAG );
|
||||
|
||||
if ( !head )
|
||||
return NULL;
|
||||
|
||||
head->end = NULL;
|
||||
head->start = NULL;
|
||||
|
||||
KeInitializeSpinLock( head->lock );
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
VOID QueuePush(
|
||||
_In_ PQUEUE_HEAD Head,
|
||||
_In_ PVOID Data
|
||||
)
|
||||
{
|
||||
KIRQL irql = KeGetCurrentIrql();
|
||||
KeAcquireSpinLock( Head->lock, &irql );
|
||||
|
||||
PQUEUE_NODE temp = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( QUEUE_NODE ), QUEUE_POOL_TAG );
|
||||
|
||||
if ( !temp )
|
||||
goto end;
|
||||
|
||||
temp->data = Data;
|
||||
temp->lock = Head->lock;
|
||||
|
||||
if ( Head->end != NULL )
|
||||
Head->end->next = temp;
|
||||
|
||||
Head->end = temp;
|
||||
|
||||
if ( Head->start == NULL )
|
||||
Head->start = temp;
|
||||
|
||||
end:
|
||||
KeReleaseSpinLock( Head->lock, irql );
|
||||
}
|
||||
|
||||
PVOID QueuePop(
|
||||
_In_ PQUEUE_HEAD Head
|
||||
)
|
||||
{
|
||||
KIRQL irql = KeGetCurrentIrql();
|
||||
KeAcquireSpinLock( Head->lock, &irql );
|
||||
|
||||
PVOID data = NULL;
|
||||
PQUEUE_NODE temp = Head->start;
|
||||
|
||||
if ( temp == NULL )
|
||||
goto end;
|
||||
|
||||
data = temp->data;
|
||||
Head->start = temp->next;
|
||||
|
||||
if ( Head->end == temp )
|
||||
Head->end = NULL;
|
||||
|
||||
ExFreePoolWithTag( temp, QUEUE_POOL_TAG );
|
||||
|
||||
end:
|
||||
KeReleaseSpinLock( Head->lock, irql );
|
||||
return data;
|
||||
}
|
37
driver/queue.h
Normal file
37
driver/queue.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef QUEUE_H
|
||||
#define QUEUE_H
|
||||
|
||||
#include <ntifs.h>
|
||||
|
||||
#define QUEUE_POOL_TAG 'qqqq'
|
||||
|
||||
typedef struct _QUEUE_NODE
|
||||
{
|
||||
struct _QUEUE_NODE* next;
|
||||
PKSPIN_LOCK lock;
|
||||
PVOID data;
|
||||
|
||||
}QUEUE_NODE, *PQUEUE_NODE;
|
||||
|
||||
typedef struct QUEUE_HEAD
|
||||
{
|
||||
struct _QUEUE_NODE* start;
|
||||
struct _QUEUE_NODE* end;
|
||||
PKSPIN_LOCK lock;
|
||||
|
||||
}QUEUE_HEAD, *PQUEUE_HEAD;
|
||||
|
||||
PQUEUE_NODE QueueCreate();
|
||||
|
||||
VOID QueuePush(
|
||||
_In_ PQUEUE_HEAD Head,
|
||||
_In_ PVOID Data
|
||||
);
|
||||
|
||||
PVOID QueuePop(
|
||||
_In_ PQUEUE_HEAD Head
|
||||
);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -10,16 +10,12 @@ namespace service
|
|||
{
|
||||
namespace Types
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct MODULE_VERIFICATION_CHECKSUM_FAILURE
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public int ReportCode;
|
||||
[FieldOffset(0)]
|
||||
public UInt64 ModuleBaseAddress;
|
||||
[FieldOffset(0)]
|
||||
public UInt64 ModuleSize;
|
||||
[FieldOffset(0)]
|
||||
public fixed char ModuleName[512];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO.Pipes;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using service.Types;
|
||||
|
||||
|
@ -193,6 +194,19 @@ namespace service
|
|||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern bool GetNamedPipeClientProcessId(IntPtr Pipe, out uint ClientProcessId);
|
||||
public static uint GetNamedPipeClientProcId(NamedPipeServerStream PipeServer)
|
||||
{
|
||||
UInt32 procId;
|
||||
IntPtr pipeHandle = PipeServer.SafePipeHandle.DangerousGetHandle();
|
||||
|
||||
if (GetNamedPipeClientProcessId(pipeHandle, out procId))
|
||||
return procId;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
|
|
|
@ -130,16 +130,92 @@ void kernelmode::Driver::VerifySystemModules()
|
|||
free( buffer );
|
||||
}
|
||||
|
||||
void kernelmode::Driver::EnableObRegisterCallbacks()
|
||||
/*
|
||||
* HOW THIS WILL WORK:
|
||||
*
|
||||
* 1. On driver initiation, ObRegisterCallbacks will be registered
|
||||
* 2. Each time a process that is not whitelisted tries to open a handle
|
||||
* to our game we will store the report in an a report queue
|
||||
* 3. the user mode app will then periodically query the driver asking
|
||||
* how many pending reports there are
|
||||
* 4. once the number is received, the app will allocate a buffer large enough
|
||||
* for all the reports and once again call CompleteQueuedCallbackReports
|
||||
* 5. This will then retrieve the reports into the buffer and from there
|
||||
* we can iteratively report them the same way as we do with the system
|
||||
* modules.
|
||||
*/
|
||||
|
||||
bool kernelmode::Driver::QueueCallbackReportIrp(PHANDLE Event)
|
||||
{
|
||||
if ( !Event )
|
||||
return false;
|
||||
|
||||
OVERLAPPED io;
|
||||
BOOLEAN status;
|
||||
DWORD bytes_returned;
|
||||
global::report_structures::OPEN_HANDLE_FAILURE_REPORT report;
|
||||
|
||||
io.hEvent = *Event;
|
||||
|
||||
status = DeviceIoControl(
|
||||
this->driver_handle,
|
||||
IOCTL_MONITOR_CALLBACKS_FOR_REPORTS,
|
||||
NULL,
|
||||
NULL,
|
||||
&report,
|
||||
sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT ),
|
||||
&bytes_returned,
|
||||
&io
|
||||
);
|
||||
|
||||
if ( status == NULL )
|
||||
{
|
||||
LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() );
|
||||
return false;
|
||||
}
|
||||
|
||||
WaitForSingleObject( io.hEvent, INFINITE );
|
||||
|
||||
/* we EXPECTED to receive bytes so this is an error */
|
||||
if ( bytes_returned == NULL )
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void kernelmode::Driver::DisableObRegisterCallbacks()
|
||||
void kernelmode::Driver::NotifyDriverOnProcessLaunch()
|
||||
{
|
||||
BOOLEAN status;
|
||||
kernelmode::DRIVER_INITIATION_INFORMATION information;
|
||||
information.protected_process_id = GetCurrentProcessId();
|
||||
|
||||
status = DeviceIoControl(
|
||||
this->driver_handle,
|
||||
IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH,
|
||||
&information,
|
||||
sizeof( kernelmode::DRIVER_INITIATION_INFORMATION ),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if ( status == NULL )
|
||||
LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() );
|
||||
}
|
||||
|
||||
void kernelmode::Driver::CompleteQueuedCallbackReports()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void kernelmode::Driver::EnableProcessLoadNotifyCallbacks()
|
||||
{
|
||||
/*
|
||||
* note: no need for these since when the dll is loaded it will simply
|
||||
* notify the driver.
|
||||
*/
|
||||
}
|
||||
|
||||
void kernelmode::Driver::DisableProcessLoadNotifyCallbacks()
|
||||
|
@ -150,10 +226,6 @@ void kernelmode::Driver::ValidateKPRCBThreads()
|
|||
{
|
||||
}
|
||||
|
||||
void kernelmode::Driver::CheckForHypervisor()
|
||||
{
|
||||
}
|
||||
|
||||
void kernelmode::Driver::CheckDriverHeartbeat()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#define IOCCTL_RUN_NMI_CALLBACKS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2001, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_VALIDATE_DRIVER_OBJECTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2002, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MONITOR_CALLBACKS_FOR_REPORTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2003, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2004, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
namespace kernelmode
|
||||
{
|
||||
|
@ -22,15 +24,20 @@ namespace kernelmode
|
|||
|
||||
void RunNmiCallbacks();
|
||||
void VerifySystemModules();
|
||||
void EnableObRegisterCallbacks();
|
||||
void DisableObRegisterCallbacks();
|
||||
bool QueueCallbackReportIrp( PHANDLE Event );
|
||||
void NotifyDriverOnProcessLaunch();
|
||||
void CompleteQueuedCallbackReports();
|
||||
void EnableProcessLoadNotifyCallbacks();
|
||||
void DisableProcessLoadNotifyCallbacks();
|
||||
void ValidateKPRCBThreads();
|
||||
void CheckForHypervisor();
|
||||
void CheckDriverHeartbeat();
|
||||
/* todo: driver integrity check */
|
||||
};
|
||||
|
||||
struct DRIVER_INITIATION_INFORMATION
|
||||
{
|
||||
LONG protected_process_id;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,3 +15,8 @@ void kernelmode::KManager::VerifySystemModules()
|
|||
{
|
||||
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->VerifySystemModules(); } );
|
||||
}
|
||||
|
||||
void kernelmode::KManager::MonitorCallbackReports()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace kernelmode
|
|||
|
||||
void RunNmiCallbacks();
|
||||
void VerifySystemModules();
|
||||
void MonitorCallbackReports();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace global
|
|||
|
||||
Report( std::shared_ptr<global::ThreadPool> ThreadPool, LPTSTR PipeName );
|
||||
|
||||
/* lock buffer, copy report, send to service then clear buffer */
|
||||
/* lock buffer, attach header, copy report, send to service then clear buffer */
|
||||
template <typename T>
|
||||
void ReportViolation( T* Report )
|
||||
{
|
||||
|
@ -105,6 +105,16 @@ namespace global
|
|||
UINT64 driver_size;
|
||||
CHAR driver_name[ 128 ];
|
||||
};
|
||||
|
||||
struct OPEN_HANDLE_FAILURE_REPORT
|
||||
{
|
||||
INT report_code;
|
||||
INT is_kernel_handle;
|
||||
LONG process_id;
|
||||
LONG thread_id;
|
||||
LONG desired_access;
|
||||
CHAR process_name[ 64 ];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue