Object Hook简单的来说就是Hook对象,这里拿看雪上的一个例子,因为是在win7 32位上的,有些地方做了些修改。
_OBJECT_HEADER:
kd> dt _OBJECT_HEADER
nt!_OBJECT_HEADER
+0x000 PointerCount : Int4B
+0x004 HandleCount : Int4B
+0x004 NextToFree : Ptr32 Void
+0x008 Lock : _EX_PUSH_LOCK
+0x00c TypeIndex : UChar
+0x00d TraceFlags : UChar
+0x00e InfoMask : UChar
+0x00f Flags : UChar
+0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : Ptr32 Void
+0x014 SecurityDescriptor : Ptr32 Void
+0x018 Body : _QUAD
在Win7 Object_Header之TypeIndex解析已经说了怎么通过TypeIndex得到对象类型:
_OBJECT_TYPE:
kd> dt _OBJECT_TYPE
nt!_OBJECT_TYPE
+0x000 TypeList : _LIST_ENTRY
+0x008 Name : _UNICODE_STRING
+0x010 DefaultObject : Ptr32 Void
+0x014 Index : UChar
+0x018 TotalNumberOfObjects : Uint4B
+0x01c TotalNumberOfHandles : Uint4B
+0x020 HighWaterNumberOfObjects : Uint4B
+0x024 HighWaterNumberOfHandles : Uint4B
+0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER
+0x078 TypeLock : _EX_PUSH_LOCK
+0x07c Key : Uint4B
+0x080 CallbackList : _LIST_ENTRY
对象类型结构主要是创建对象类型,比如*IoFileObjectType, *PsProcessType, *PsThreadType 这些。
系统初始化的时候第一个创建的对象类型结构就是TYPE结构,生成对象目录\ObjectTypes 其后面的对象类型直接挂在这个目录上
比如对象类型 \ObjectTypes\File 或者设备类型 \ObjectTypes\Device
最重要的是下面这个结构:
kd> dt _OBJECT_TYPE_INITIALIZER
nt!_OBJECT_TYPE_INITIALIZER
+0x000 Length : Uint2B
+0x002 ObjectTypeFlags : UChar
+0x002 CaseInsensitive : Pos 0, 1 Bit
+0x002 UnnamedObjectsOnly : Pos 1, 1 Bit
+0x002 UseDefaultObject : Pos 2, 1 Bit
+0x002 SecurityRequired : Pos 3, 1 Bit
+0x002 MaintainHandleCount : Pos 4, 1 Bit
+0x002 MaintainTypeList : Pos 5, 1 Bit
+0x002 SupportsObjectCallbacks : Pos 6, 1 Bit
+0x004 ObjectTypeCode : Uint4B
+0x008 InvalidAttributes : Uint4B
+0x00c GenericMapping : _GENERIC_MAPPING
+0x01c ValidAccessMask : Uint4B
+0x020 RetainAccess : Uint4B
+0x024 PoolType : _POOL_TYPE
+0x028 DefaultPagedPoolCharge : Uint4B
+0x02c DefaultNonPagedPoolCharge : Uint4B
+0x030 DumpProcedure : Ptr32 void
+0x034 OpenProcedure : Ptr32 long
+0x038 CloseProcedure : Ptr32 void
+0x03c DeleteProcedure : Ptr32 void
+0x040 ParseProcedure : Ptr32 long
+0x044 SecurityProcedure : Ptr32 long
+0x048 QueryNameProcedure : Ptr32 long
+0x04c OkayToCloseProcedure : Ptr32 unsigned char
后面这几个函数决定对象的一些操作,例如 打开、创建、删除,不同对象类型(OBJECT_TYPE)的操作也不同,所以要清楚知道对象是什么类型。
当你调用NtCreateFile->IoCreateFile->ObOpenObjectByName->ObpLookupObjectName->IopParseFile->IopParseDevice
IopParseFile最终也会调用IopParseDevice
ObjectHook其实就是比如你要HOOK 创建打开就是OBJECT_TYPE_INITIALIZER->ParseProcedure。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #include <ntddk.h> typedef PULONG (NTAPI *OBGETOBJECTTYPE)(PVOID); OBGETOBJECTTYPE OBGetObjectType; 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; ULONG Index; ULONG TotalNumberOfObjects; ULONG TotalNumberOfHandles; ULONG HighWaterNumberOfObjects; ULONG HighWaterNumberOfHandles; OBJECT_TYPE_INITIALIZER TypeInfo ; ULONG TypeLock; ULONG Key; LIST_ENTRY CallbackList; } OBJECT_TYPE, *POBJECT_TYPE; POBJECT_TYPE pType = NULL; PVOID OldParseProcedure = NULL; NTSTATUS NewParseProcedure(IN PVOID ParseObject, IN PVOID ObjectType, IN OUT PACCESS_STATE AccessState, IN KPROCESSOR_MODE AccessMode, IN ULONG Attributes, IN OUT PUNICODE_STRING CompleteName, IN OUT PUNICODE_STRING RemainingName, IN OUT PVOID Context OPTIONAL, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, OUT PVOID *Object) { NTSTATUS Status; KdPrint(("object is hook\n")); __asm { push eax push Object push SecurityQos push Context push RemainingName push CompleteName push Attributes movzx eax, AccessMode push eax push AccessState push ObjectType push ParseObject call OldParseProcedure mov Status, eax pop eax } return Status; } VOID GetObGetObjectTypeAddress() { PUCHAR addr; UNICODE_STRING pslookup; RtlInitUnicodeString(&pslookup,L"ObGetObjectType"); addr=(PUCHAR)MmGetSystemRoutineAddress(&pslookup); OBGetObjectType=(OBGETOBJECTTYPE )addr; } NTSTATUS Hook() { NTSTATUS Status; HANDLE hFile; UNICODE_STRING Name; OBJECT_ATTRIBUTES Attr; IO_STATUS_BLOCK ioStaBlock; PVOID pObject = NULL; RtlInitUnicodeString(&Name,L"\\Device\\HarddiskVolume1\\1.txt"); //C:\1.txt InitializeObjectAttributes(&Attr,&Name,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE ,\ 0,NULL); Status = ZwOpenFile(&hFile,GENERIC_ALL,&Attr,&ioStaBlock,\ 0,FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS(Status)) { KdPrint(("File is Null\n")); return Status; } Status = ObReferenceObjectByHandle(hFile,GENERIC_ALL,NULL,KernelMode,&pObject,NULL); if (!NT_SUCCESS(Status)) { KdPrint(("Object is Null\n")); return Status; } KdPrint(("pobject is %08X\n",pObject)); //win7 获取objecttype更加方便了。。。 pType = (POBJECT_TYPE)OBGetObjectType(pObject); KdPrint(("pType is %08X\n",pType)); OldParseProcedure = pType->TypeInfo.ParseProcedure; KdPrint(("OldParseProcedure addrs is %08X\n",OldParseProcedure)); //这里最好检查一下OldParseProcedure,是否为0 pType->TypeInfo.ParseProcedure = NewParseProcedure;//hook 因为object原本就是是可写的,所以不用特意去除内存保护 Status = ZwClose(hFile); return Status; } NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) { NTSTATUS Status = STATUS_SUCCESS; GetObGetObjectTypeAddress(); Status=Hook(); return Status; } |
效果: