使用 ObRegisterCallbacks 实现保护进程,其实稍微 PATCH 下内核,这个函数还能实现文件操作监视。但可惜只能在 WIN7X64 上用。因为在 WIN7X64 上 PATCH 对象结构的成员(ObjectType->TypeInfo.SupportsObjectCallbacks)是合法的,在 WIN8X64 以及之后系统上会触发 PATCHGUARD。但是经过实际测试,我手里的Win7 64 是可以在不修改myobtype->TypeInfo.SupportsObjectCallbacks = 1;的前提下直接注册回调,但是win8 64不行,win8 64 修改了myobtype->TypeInfo.SupportsObjectCallbacks = 1;之后发现没有蓝屏并且目前可以成功进行回调处理(只测试了手里的一台win8 64)。文件回调容易出问题,频率非常高。使用的时候建议使用成熟的文件过滤框架。
使用的时候和进程线程的回调句柄处理一样,需要修改标记使得无签名可以正常注册回调,然后在修改文件的myobtype->TypeInfo.SupportsObjectCallbacks = 1;然后在进行回调注册就行了。
注册:
// init callbacks
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");
obReg.OperationRegistration = &opReg;
memset(&opReg, 0, sizeof(opReg));
opReg.ObjectType = IoFileObjectType;
opReg.Operations = OB_OPERATION_HANDLE_CREATE|OB_OPERATION_HANDLE_DUPLICATE;
opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall;
//opReg.PostOperation = (POB_POST_OPERATION_CALLBACK)&postCall;//不需要
// register callbacks
status = ObRegisterCallbacks(&obReg, &obHandle);
注销:
ObUnRegisterCallbacks(obHandle);
回调函数:
PVOID obHandle;
OB_PREOP_CALLBACK_STATUS preCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
UNICODE_STRING DosName;
PFILE_OBJECT fileo = OperationInformation->Object;
HANDLE CurrentProcessId = PsGetCurrentProcessId();
UNREFERENCED_PARAMETER(RegistrationContext);
if( OperationInformation->ObjectType!=*IoFileObjectType )
return OB_PREOP_SUCCESS;
//过滤无效指针
if( fileo->FileName.Buffer==NULL ||
!MmIsAddressValid(fileo->FileName.Buffer) ||
fileo->DeviceObject==NULL ||
!MmIsAddressValid(fileo->DeviceObject) )
return OB_PREOP_SUCCESS;
//过滤无效路径
if( !_wcsicmp(fileo->FileName.Buffer,L"\\Endpoint") ||
!_wcsicmp(fileo->FileName.Buffer,L"?") ||
!_wcsicmp(fileo->FileName.Buffer,L"\\.\\.") ||
!_wcsicmp(fileo->FileName.Buffer,L"\\"))
return OB_PREOP_SUCCESS;
//阻止访问readme.txt
if(wcsstr(_wcslwr(fileo->FileName.Buffer),L"xxxx.txt"))
{
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
}
if(OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
{
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess=0;
}
}
RtlVolumeDeviceToDosName(fileo->DeviceObject, &DosName);
DbgPrint("[FILE_MONITOR_X64][PID]%ld [File]%wZ%wZ\n", (ULONG64)CurrentProcessId, &DosName, &fileo->FileName);
return OB_PREOP_SUCCESS;
}
文件标记处理相关结构体:
typedef struct _OBJECT_TYPE_INITIALIZER // 25 elements, 0x70 bytes (sizeof)
{
/*0x000*/ UINT16 Length;
union // 2 elements, 0x1 bytes (sizeof)
{
/*0x002*/ UINT8 ObjectTypeFlags;
struct // 7 elements, 0x1 bytes (sizeof)
{
/*0x002*/ UINT8 CaseInsensitive : 1; // 0 BitPosition
/*0x002*/ UINT8 UnnamedObjectsOnly : 1; // 1 BitPosition
/*0x002*/ UINT8 UseDefaultObject : 1; // 2 BitPosition
/*0x002*/ UINT8 SecurityRequired : 1; // 3 BitPosition
/*0x002*/ UINT8 MaintainHandleCount : 1; // 4 BitPosition
/*0x002*/ UINT8 MaintainTypeList : 1; // 5 BitPosition
/*0x002*/ UINT8 SupportsObjectCallbacks : 1; // 6 BitPosition
};
};
/*0x004*/ ULONG32 ObjectTypeCode;
/*0x008*/ ULONG32 InvalidAttributes;
/*0x00C*/ struct _GENERIC_MAPPING GenericMapping; // 4 elements, 0x10 bytes (sizeof)
/*0x01C*/ ULONG32 ValidAccessMask;
/*0x020*/ ULONG32 RetainAccess;
/*0x024*/ enum _POOL_TYPE PoolType;
/*0x028*/ ULONG32 DefaultPagedPoolCharge;
/*0x02C*/ ULONG32 DefaultNonPagedPoolCharge;
/*0x030*/ PVOID DumpProcedure;
/*0x038*/ PVOID OpenProcedure;
/*0x040*/ PVOID CloseProcedure;
/*0x048*/ PVOID DeleteProcedure;
/*0x050*/ PVOID ParseProcedure;
/*0x058*/ PVOID SecurityProcedure;
/*0x060*/ PVOID QueryNameProcedure;
/*0x068*/ PVOID OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
typedef struct _EX_PUSH_LOCK // 7 elements, 0x8 bytes (sizeof)
{
union // 3 elements, 0x8 bytes (sizeof)
{
struct // 5 elements, 0x8 bytes (sizeof)
{
/*0x000*/ UINT64 Locked : 1; // 0 BitPosition
/*0x000*/ UINT64 Waiting : 1; // 1 BitPosition
/*0x000*/ UINT64 Waking : 1; // 2 BitPosition
/*0x000*/ UINT64 MultipleShared : 1; // 3 BitPosition
/*0x000*/ UINT64 Shared : 60; // 4 BitPosition
};
/*0x000*/ UINT64 Value;
/*0x000*/ VOID* Ptr;
};
}EX_PUSH_LOCK, *PEX_PUSH_LOCK;
typedef struct _MY_OBJECT_TYPE // 12 elements, 0xD0 bytes (sizeof)
{
/*0x000*/ struct _LIST_ENTRY TypeList; // 2 elements, 0x10 bytes (sizeof)
/*0x010*/ struct _UNICODE_STRING Name; // 3 elements, 0x10 bytes (sizeof)
/*0x020*/ VOID* DefaultObject;
/*0x028*/ UINT8 Index;
/*0x029*/ UINT8 _PADDING0_[0x3];
/*0x02C*/ ULONG32 TotalNumberOfObjects;
/*0x030*/ ULONG32 TotalNumberOfHandles;
/*0x034*/ ULONG32 HighWaterNumberOfObjects;
/*0x038*/ ULONG32 HighWaterNumberOfHandles;
/*0x03C*/ UINT8 _PADDING1_[0x4];
/*0x040*/ struct _OBJECT_TYPE_INITIALIZER TypeInfo; // 25 elements, 0x70 bytes (sizeof)
/*0x0B0*/ struct _EX_PUSH_LOCK TypeLock; // 7 elements, 0x8 bytes (sizeof)
/*0x0B8*/ ULONG32 Key;
/*0x0BC*/ UINT8 _PADDING2_[0x4];
/*0x0C0*/ struct _LIST_ENTRY CallbackList; // 2 elements, 0x10 bytes (sizeof)
}MY_OBJECT_TYPE, *PMY_OBJECT_TYPE;
处理文件标记:
VOID EnableObType(POBJECT_TYPE ObjectType)
{
PMY_OBJECT_TYPE myobtype = (PMY_OBJECT_TYPE)ObjectType;
myobtype->TypeInfo.SupportsObjectCallbacks = 1;
}
EnableObType(*IoFileObjectType);
结果:
Win7 64
Win8 64