/*
win7 32
windows 对象管理相关部分学习小结,
可以结合winobj,windbg等工具来查看及验证相关数据
*/
#include "ntddk.h"
//extern ObTypeIndexTable;
#define NUMBER_HASH_BUCKETS 37
#define OBJECT_TO_OBJECT_HEADER(O) CONTAINING_RECORD((O),OBJECT_HEADER,Body)
#define OBJECT_TO_OBJECT_HEADER_NAME_INFO(o) CONTAINING_RECORD((o),OBJECT_HEADER_NAME_INFO,Directory)
//#define CONTAINING_RECORD(address,type,field) ((type*)(((ULONG_PTR)address)-(ULONG_PTR)(&(((type*)0)->field))))
typedef ULONG DEVICE_MAP;
typedef ULONG EX_PUSH_LOCK;
typedef struct _OBJECT_DIRECTORY
{
struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[NUMBER_HASH_BUCKETS];
EX_PUSH_LOCK Lock;
DEVICE_MAP DeviceMap;
ULONG SessionId;
PVOID NamespaceEntry;
ULONG Flags;
}OBJECT_DIRECTORY,*POBJECT_DIRECTORY;
typedef struct _OBJECT_DIRECTORY_ENTRY{
struct _OBJECT_DIRECTORY_ENTRY *ChainLink;
PVOID Object;
ULONG HashValue;
}OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;
typedef struct _OBJECT_CREATE_INFORMATION
{
ULONG Attributes;
PVOID RootDirectory;
CHAR ProbeMode;
ULONG PagedPoolCharge;
ULONG NonPagedPoolCharge;
ULONG SecurityDescriptorCharge;
PVOID SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQos;
SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
}OBJECT_CREATE_INFORMATION,*POBJECT_CREATE_INFORMATION;
typedef struct _OBJECT_HEADER
{
LONG PointerCount;
union
{
LONG HandleCount;
volatile PVOID NextToFree;
};
EX_PUSH_LOCK Lock;
UCHAR TypeIndex;
UCHAR TraceFlags;
UCHAR InfoMask;
UCHAR Flags;
union
{
POBJECT_CREATE_INFORMATION ObjectCreateInfo;
PVOID QuotaBlockCharged;
};
PVOID SecurityDescriptor;
QUAD Body;
}OBJECT_HEADER,*POBJECT_HEADER;
typedef struct _OBJECT_HEADER_NAME_INFO
{
POBJECT_DIRECTORY Directory;
UNICODE_STRING Name;
ULONG ReferenceCount;
}OBJECT_HEADER_NAME_INFO,*POBJECT_HEADER_NAME_INFO;
typedef struct _OBJECT_TYPE_INITIALIZER {
USHORT Length ;
UCHAR ObjectTypeFlags ;
UCHAR CaseInsensitive ;
UCHAR UnnamedObjectsOnly ;
UCHAR UseDefaultObject ;
UCHAR SecurityRequired ;
UCHAR MaintainHandleCount ;
UCHAR MaintainTypeList ;
UCHAR SupportsObjectCallbacks ;
UCHAR CacheAligned ;
ULONG ObjectTypeCode ;
BOOLEAN InvalidAttributes ;
GENERIC_MAPPING GenericMapping ;
BOOLEAN ValidAccessMask ;
BOOLEAN RetainAccess ;
POOL_TYPE PoolType ;
BOOLEAN DefaultPagedPoolCharge ;
BOOLEAN DefaultNonPagedPoolCharge ;
PVOID DumpProcedure ;
ULONG OpenProcedure ;
PVOID CloseProcedure ;
PVOID DeleteProcedure ;
ULONG ParseProcedure ;
ULONG SecurityProcedure;
ULONG QueryNameProcedure;
UCHAR OkayToCloseProcedure ;
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
typedef struct _OBJECT_TYPE
{
LIST_ENTRY TypeList;
UNICODE_STRING Name;
PVOID DefaultObject;
UCHAR Index;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
OBJECT_TYPE_INITIALIZER TypeInfo;
EX_PUSH_LOCK TypeLock;
ULONG Key;
LIST_ENTRY CallbackList;
}OBJECT_TYPE,*POBJECT_TYPE;
NTSTATUS
ZwOpenDirectoryObject(
__out PHANDLE DirectoryHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes
);
NTSTATUS
ObQueryNameString(
IN PVOID Object,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
IN ULONG Length,
OUT PULONG ReturnLength
);
NTSTATUS ObReferenceObjectByHandle(IN HANDLE Handle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_TYPE ObjectType OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
OUT PVOID* Object,
OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL);
VOID DriverUnload(PDRIVER_OBJECT driver)
{
DbgPrint("goodbye!\n");
}
VOID ListObjectType(POBJECT_DIRECTORY Type)//列出对象类型
{
ULONG BucketIndex=0;
POBJECT_TYPE temp=NULL;
POBJECT_DIRECTORY_ENTRY CurrentEntry=NULL;
DbgPrint("Index TypeNames\n");
do
{
if((CurrentEntry=Type->HashBuckets[BucketIndex]))//not (&RootDirectoryObject->HashBuckets[]),pay attention to the use of pointer and '&'
{
do//search the whole queue
{
temp=(POBJECT_TYPE)CurrentEntry->Object;
DbgPrint("0x%2x %wZ",temp->Index,&temp->Name);
CurrentEntry=CurrentEntry->ChainLink;//链表中下一个
}while(CurrentEntry);
}
BucketIndex++;
}while(BucketIndex<NUMBER_HASH_BUCKETS);
}
NTSTATUS object()
{
UNICODE_STRING Name;
NTSTATUS status=STATUS_SUCCESS;
HANDLE Handle;
OBJECT_ATTRIBUTES ObjectAttributes;
POBJECT_DIRECTORY RootDirectoryObject=NULL;
POBJECT_TYPE ObjectType=NULL;
POBJECT_HEADER ObjectHeader;
POBJECT_HEADER_NAME_INFO NameInfo;
POBJECT_NAME_INFORMATION name;
POBJECT_DIRECTORY_ENTRY CurrentEntry;
ULONG uRet,BucketIndex=0;
name=(POBJECT_NAME_INFORMATION)ExAllocatePool(NonPagedPool,1024);
RtlInitUnicodeString(&Name,L"\\");//ObpRootDirectoryObject,'\\'是对象管理的根目录
InitializeObjectAttributes(&ObjectAttributes,&Name,OBJ_CASE_INSENSITIVE|OBJ_PERMANENT,NULL,/*SePublicDefaultUnrestrictedSd*/NULL);
status=ZwOpenDirectoryObject(&Handle,DIRECTORY_ALL_ACCESS,&ObjectAttributes);//打开目录对象
if(!NT_SUCCESS(status))
{
KdPrint(("ZwOpenDirectoryObject fail!\n"));
return STATUS_UNSUCCESSFUL;
}
//通过对象句柄得到对象指针
status=ObReferenceObjectByHandle(Handle,0,NULL,KernelMode,(PVOID*)&RootDirectoryObject,NULL);
if(!NT_SUCCESS(status))
{
KdPrint((" ObReferenceObjectByName Failure! status=0x%08x\n",status));
return STATUS_UNSUCCESSFUL;
}
do
{
if((CurrentEntry=RootDirectoryObject->HashBuckets[BucketIndex]))//not (&RootDirectoryObject->HashBuckets[]),pay attention to the use of pointer and '&'
{
//KdPrint(("ObjectHeader TypeIdex HashValue name\n"));
do//search the whole queue
{
ObjectHeader=OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object);
status=ObQueryNameString(CurrentEntry->Object,name,1024,&uRet);
if(!NT_SUCCESS(status))
{
KdPrint(("ObQueryNameString fails\n"));
return STATUS_UNSUCCESSFUL;
}
//KdPrint(("0x%08x 0x%2x 0x%8x %wZ\n",ObjectHeader,ObjectHeader->TypeIndex,CurrentEntry->HashValue,&name->Name));
if(ObjectHeader->TypeIndex==0x3)
{
if(name->Name.Length==RtlCompareMemory(name->Name.Buffer,L"\\ObjectTypes",name->Name.Length))
{
DbgPrint("find ObjectTypes!\n");
ListObjectType((POBJECT_DIRECTORY)CurrentEntry->Object);
}
}
CurrentEntry=CurrentEntry->ChainLink;
if(!MmIsAddressValid(CurrentEntry))
{
break;
}
RtlZeroMemory(name,uRet);
}while(CurrentEntry);
}
BucketIndex++;
}while(BucketIndex<NUMBER_HASH_BUCKETS);
ObDereferenceObject(RootDirectoryObject);
ZwClose(Handle);
ExFreePool(name);
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
DbgPrint("enter DriverEntry!\n");
object();
driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
结果图:
202301052120
对象通知
参考:windows内核编程
内核提供这样一种机制,它能够在试图打开或者复制特定对象类型的句柄时通知感兴趣的驱动程序。正式支持的对象类型有进程和线程(上图中的文件,可能还有其它的),对Windows10来说,还有桌面对象。
相关函数和数据结构:
NTSTATUS ObRegisterCallbacks(
_In_ POB_CALLBACK_REGISTRATION CallbackRegistration,
_Outptr_ PVOID *RegistrationHandle);
typedef struct _OB_CALLBACK_REGISTRATION{
_In_ USHORT Version;
_In_ USHORT OperationRegistrationCount;
_In_ UNICODE_STRING Altitude;
_In_ PVOID RegistrationContext;//驱动程序定义的值,会原样传递给回调函数
_In_ OB_OPERATION_REGISTRATION *OperationRegistration;
}OB_CALLBACK_REGISTRATION,*POB_CALLBACK_REGISTRATION;
typedef struct _OB_OPERATION_REGISTRATION{
_In_ POBJECT_TYPE *ObjectType;
_In_ OB_OPERATION Operations;
_In_ POB_PRE_OPERATION_CALLBACK PreOperation;
_In_ POB_POST_OPERATION_CALLBACK PostOperation;
}OB_OPERATION_REGISTRATION,*POB_OPERATION_REGISTRATION;
ObjectType是一个指向这个实例注册的对象类型(进程,线程或桌面)的指针。这些指针被分别输出为全局内核变量:PsProcessType,PsThreadType和ExDesktopObjectType.
Operations字段是一个位标识枚举类型,用来选择创建/打开操作(OB_OPERATION_HANDLE_CREATE)和复制操作(OB_OPERATION_HANDLE_DUPLICATE)。
OB_OPERATION_HANDLE_CREATE针对用户模式函数CreateProcess、OpenProcess、CreateThread、OpenThread、CreateDesktop、OpenDesktop和针对这些对象类型的相似函数的调用。OB_OPERATION_HANDLE_DUPLICATE指这些对象类型的句柄复制操作(用户模式DuplicateHandle API)。
操作前回调
操作前回调是在实际的创建/打开/复制操作完成之前被调用,给驱动程序一个对操作结果进行修改的机会。操作前回调接受一个OB_PRE_OPERATION_INFORMATION结构,其定义如下:
typedef struct _OB_PRE_OPREATION_INFORMATION{
_In_ OB_OPERATION Operation;
union {
_In_ ULONG Flags;
struct {
_In_ ULONG KernelHandle:1;
_In_ ULONG Reserved:31;
};
_In_ PVOID Object;
_In_ POBJECT_TYPE ObjectType;
_Out_ PVOID CallContext;
_In_ POB_PRE_OPERATION_PARAMETERS Parameters;
}OB_PRE_OPERATION_INFORMATION,*POB_PRE_OPERATION_INFORMATION;
typedef union _OB_PRE_OPERATION_PARAMETERS{
_Inout_ OB_PRE_CREATE_HANDLE_INFORMATION CreateHandleInformation;
_Inout_ OB_PRE_DUPLICATE_HANDLE_INFORMATION DuplicateHandleInformation;
}OB_PRE_OPERATION_PARAMETERS,*POB_PRE_OPERATION_PARAMETERS;
typedef struct _OB_PRE_CREATE_HANDLE_INFORMATION{
_Inout_ ACCESS_MASK DesiredAccdess;//可以被驱动程序修改的掩码值,只能减,不能加
_In_ ACCESS_MASK OriginalDesiredAccess;//原始的掩码值
}OB_PRE_CREATE_HANDLE_INFORMATION,*POB_PRE_CREATE_HANDLE_INFORMATION;
typedef struct _OB_PRE_DUPICATE_HADNLE_INFORMATION{
_Inout_ ACCESS_MASK DesiredAccess;
_In_ ACCESS_MASK OriginalDesiredAccess;
_In_ PVOID SourceProcess;
_In_ PVOID TargetProcess;
}OB_PRE_DUPLICATE_HANDLE_INFORMATION,*POB_PRE_DUPLICATE_HANDLE_INFORMATION;
操作后回调
操作后回调是在操作完成之后被调用。此时驱动程序不能进行任何修改,只能查看结果。