/*
目的:演示ObCreateObjectType的用法(XP到WIN10)。
注意:编译的平台和运行的平台。
made by correy
made at 2016.05.30.
homepage:http://correy.webs.com
*/
#include <ntifs.h>
#include <windef.h>
#include <ntddk.h>
#include <ntstrsafe.h>
#include <intrin.h> //VS2012编译。
#include <immintrin.h>//VS2012编译。
//#include <mmintrin.h> //WDK 编译。
//#include <emmintrin.h>//WDK 编译。
//#include <xmmintrin.h>//WDK 编译。
#pragma warning(disable:4100) //未引用的形参
#pragma warning(disable:4214) //整形以外的位域类型
#pragma warning(disable:4121) //封装要区分成员对齐方式
typedef struct _OBJECT_DUMP_CONTROL {
PVOID Stream;
ULONG Detail;
} OB_DUMP_CONTROL, *POB_DUMP_CONTROL;
typedef VOID(*OB_DUMP_METHOD)(
IN PVOID Object,
IN POB_DUMP_CONTROL Control OPTIONAL
);
typedef enum _OB_OPEN_REASON {
ObCreateHandle,
ObOpenHandle,
ObDuplicateHandle,
ObInheritHandle,
ObMaxOpenReason
} OB_OPEN_REASON;
typedef NTSTATUS(*OB_OPEN_METHOD)(
IN OB_OPEN_REASON OpenReason,
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG HandleCount
);
typedef BOOLEAN(*OB_OKAYTOCLOSE_METHOD)(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN HANDLE Handle,
IN KPROCESSOR_MODE PreviousMode
);
typedef VOID(*OB_CLOSE_METHOD)(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG_PTR ProcessHandleCount,
IN ULONG_PTR SystemHandleCount
);
typedef VOID(*OB_DELETE_METHOD)(
IN PVOID Object
);
typedef NTSTATUS(*OB_PARSE_METHOD)(
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
);
typedef NTSTATUS(*OB_SECURITY_METHOD)(
IN PVOID Object,
IN SECURITY_OPERATION_CODE OperationCode,
IN PSECURITY_INFORMATION SecurityInformation,
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
IN OUT PULONG CapturedLength,
IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
IN POOL_TYPE PoolType,
IN PGENERIC_MAPPING GenericMapping
);
typedef NTSTATUS(*OB_QUERYNAME_METHOD)(
IN PVOID Object,
IN BOOLEAN HasObjectName,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
IN ULONG Length,
OUT PULONG ReturnLength,
IN KPROCESSOR_MODE Mode
);
#if (NTDDI_VERSION < NTDDI_VISTA)
typedef struct _OBJECT_TYPE_INITIALIZER {
USHORT Length;
BOOLEAN UseDefaultObject;
BOOLEAN CaseInsensitive;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccessMask;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
BOOLEAN MaintainTypeList;
POOL_TYPE PoolType;
ULONG DefaultPagedPoolCharge;
ULONG DefaultNonPagedPoolCharge;
OB_DUMP_METHOD DumpProcedure;
OB_OPEN_METHOD OpenProcedure;
OB_CLOSE_METHOD CloseProcedure;
OB_DELETE_METHOD DeleteProcedure;
OB_PARSE_METHOD ParseProcedure;
OB_SECURITY_METHOD SecurityProcedure;
OB_QUERYNAME_METHOD QueryNameProcedure;
OB_OKAYTOCLOSE_METHOD OkayToCloseProcedure;
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
#else
__declspec(align(2))
//#pragma pack(2)
#pragma warning(push)
#pragma warning(disable: 4201) //NAMELESS_STRUCT_UNION
typedef struct _OBJECT_TYPE_INITIALIZER {
USHORT Length;
union //这里是不是一个联合还有待考察。可怀疑ObjectTypeFlags和下面的一个位结构构成两个字节。
{
UCHAR ObjectTypeFlags;//ObjectTypeFlags就是下面的位结构,总共占用2字节,但是只用一字节。
struct
{
unsigned char CaseInsensitive : 1;
unsigned char UnnamedObjectsOnly : 1;
unsigned char UseDefaultObject : 1;
unsigned char SecurityRequired : 1;
unsigned char MaintainHandleCount : 1;
unsigned char MaintainTypeList : 1;
unsigned char SupportsObjectCallbacks : 1;
unsigned char CacheAligned : 1;
};
}ObjectTypeFlags;
ULONG ObjectTypeCode;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccessMask;
ULONG RetainAccess;
POOL_TYPE PoolType;
ULONG DefaultPagedPoolCharge;
ULONG DefaultNonPagedPoolCharge;
OB_DUMP_METHOD DumpProcedure;
OB_OPEN_METHOD OpenProcedure;
OB_CLOSE_METHOD CloseProcedure;
OB_DELETE_METHOD DeleteProcedure;
OB_PARSE_METHOD ParseProcedure;
OB_SECURITY_METHOD SecurityProcedure;
OB_QUERYNAME_METHOD QueryNameProcedure;
OB_OKAYTOCLOSE_METHOD OkayToCloseProcedure;
#if 0 //WIN 10 特有的。因为编译环境是VS2012,所以就不再做特别的处理了。
ULONG WaitObjectFlagMask;
USHORT WaitObjectFlagOffset;
USHORT WaitObjectPointerOffset;
#endif
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
#pragma warning(pop)
#endif
/*
WIN10 64
1: kd> dt _OBJECT_TYPE_INITIALIZER
ntdll!_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
+0x002 CacheAligned : Pos 7, 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 : Ptr64 void
+0x038 OpenProcedure : Ptr64 long
+0x040 CloseProcedure : Ptr64 void
+0x048 DeleteProcedure : Ptr64 void
+0x050 ParseProcedure : Ptr64 long
+0x058 SecurityProcedure : Ptr64 long
+0x060 QueryNameProcedure : Ptr64 long
+0x068 OkayToCloseProcedure : Ptr64 unsigned char
+0x070 WaitObjectFlagMask : Uint4B
+0x074 WaitObjectFlagOffset : Uint2B
+0x076 WaitObjectPointerOffset : Uint2B
ObCreateObjectTypeEx中有如下的代码:
if ( !TypeName
|| (Length = TypeName->Length) == 0
|| Length & 1
|| !ObjectTypeInitializer
|| ObjectTypeInitializer->InvalidAttributes & 0xFFFEE00D
|| ObjectTypeInitializer->Length != 120
|| (ObjectTypeFlags = ObjectTypeInitializer->ObjectTypeFlags, ObjectTypeFlags & 0x10) && !ObjectTypeInitializer->OpenProcedure && !ObjectTypeInitializer->CloseProcedure
|| !(ObjectTypeFlags & 4) && ObjectTypeInitializer->PoolType & 0xFFFFFDFF && !((unsigned __int8)ObjectType & 1) )
{
DbgPrintEx(0i64, 0i64, "Error creating object type\n");
__debugbreak();
JUMPOUT(loc_1405CF068);
}
而WRK中是这样的:
PoolType = ObjectTypeInitializer->PoolType;
if ((!TypeName) || (!TypeName->Length) || (TypeName->Length % sizeof( WCHAR )) ||
(ObjectTypeInitializer == NULL) ||
(ObjectTypeInitializer->InvalidAttributes & ~OBJ_ALL_VALID_ATTRIBUTES) ||
(ObjectTypeInitializer->Length != sizeof( *ObjectTypeInitializer )) ||
(ObjectTypeInitializer->MaintainHandleCount && (ObjectTypeInitializer->OpenProcedure == NULL && ObjectTypeInitializer->CloseProcedure == NULL )) ||
((!ObjectTypeInitializer->UseDefaultObject) && (PoolType != NonPagedPool)))
{
return( STATUS_INVALID_PARAMETER );
}
而XP32上是这样的:
0: kd> dt _OBJECT_TYPE_INITIALIZER
ntdll!_OBJECT_TYPE_INITIALIZER
+0x000 Length : Uint2B
+0x002 UseDefaultObject : UChar
+0x003 CaseInsensitive : UChar
+0x004 InvalidAttributes : Uint4B
+0x008 GenericMapping : _GENERIC_MAPPING
+0x018 ValidAccessMask : Uint4B
+0x01c SecurityRequired : UChar
+0x01d MaintainHandleCount : UChar
+0x01e MaintainTypeList : UChar
+0x020 PoolType : _POOL_TYPE
+0x024 DefaultPagedPoolCharge : Uint4B
+0x028 DefaultNonPagedPoolCharge : Uint4B
+0x02c DumpProcedure : Ptr32 void
+0x030 OpenProcedure : Ptr32 long
+0x034 CloseProcedure : Ptr32 void
+0x038 DeleteProcedure : Ptr32 void
+0x03c ParseProcedure : Ptr32 long
+0x040 SecurityProcedure : Ptr32 long
+0x044 QueryNameProcedure : Ptr32 long
+0x048 OkayToCloseProcedure : Ptr32 unsigned char
自己定义的结构如下:
1: kd> dt test!_OBJECT_TYPE_INITIALIZER ffffd001`310a68c0
+0x000 Length : 0x78
+0x002 ObjectTypeFlags : <unnamed-tag>
+0x004 ObjectTypeCode : 0
+0x008 InvalidAttributes : 0x100
+0x00c GenericMapping : _GENERIC_MAPPING
+0x01c ValidAccessMask : 0xf0001
+0x020 RetainAccess : 0
+0x024 PoolType : 0 ( NonPagedPool )
+0x028 DefaultPagedPoolCharge : 0
+0x02c DefaultNonPagedPoolCharge : 0
+0x030 DumpProcedure : (null)
+0x038 OpenProcedure : (null)
+0x040 CloseProcedure : (null)
+0x048 DeleteProcedure : (null)
+0x050 ParseProcedure : (null)
+0x058 SecurityProcedure : (null)
+0x060 QueryNameProcedure : (null)
+0x068 OkayToCloseProcedure : (null)
+0x070 WaitObjectFlagMask : 0
+0x074 WaitObjectFlagOffset : 0
+0x076 WaitObjectPointerOffset : 0
不过要定义和系统的结构(显示)一样的结构也是可以,重在内在的一样。
经验证:ObjectTypeFlags就是下面的位结构,总共占用2字节,但是只用一字节。
而且偏移的第二字节和第三字节的内容是不一样的,大多偏移的第三自己的内容是0.
kd> dt _OBJECT_TYPE_INITIALIZER fffff800`ff4b5220 -b
nt!_OBJECT_TYPE_INITIALIZER
+0x000 Length : 0x78
+0x002 ObjectTypeFlags : 0x24 '$'
+0x002 CaseInsensitive : 0y0
+0x002 UnnamedObjectsOnly : 0y0
+0x002 UseDefaultObject : 0y1
+0x002 SecurityRequired : 0y0
+0x002 MaintainHandleCount : 0y0
+0x002 MaintainTypeList : 0y1
+0x002 SupportsObjectCallbacks : 0y0
+0x002 CacheAligned : 0y0
+0x004 ObjectTypeCode : 0
+0x008 InvalidAttributes : 0x100
+0x00c GenericMapping : _GENERIC_MAPPING
+0x000 GenericRead : 0x20000
+0x004 GenericWrite : 0x20000
+0x008 GenericExecute : 0x20000
+0x00c GenericAll : 0xf0001
+0x01c ValidAccessMask : 0xf0001
+0x020 RetainAccess : 0
+0x024 PoolType : 200 ( NonPagedPoolNx )
+0x028 DefaultPagedPoolCharge : 0
+0x02c DefaultNonPagedPoolCharge : 0xd8
+0x030 DumpProcedure : (null)
+0x038 OpenProcedure : (null)
+0x040 CloseProcedure : (null)
+0x048 DeleteProcedure : (null)
+0x050 ParseProcedure : (null)
+0x058 SecurityProcedure : (null)
+0x060 QueryNameProcedure : (null)
+0x068 OkayToCloseProcedure : (null)
+0x070 WaitObjectFlagMask : 0
+0x074 WaitObjectFlagOffset : 0
+0x076 WaitObjectPointerOffset : 0
kd> .formats 24
Evaluate expression:
Hex: 00000000`00000024
Decimal: 36
Octal: 0000000000000000000044
Binary: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00100100
Chars: .......$
Time: Thu Jan 01 08:00:36 1970
Float: low 5.04467e-044 high 0
Double: 1.77864e-322
2008 X64的测试效果:
0: kd> dt nt!_OBJECT_TYPE_INITIALIZER -b
+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
+0x002 CacheAligned : Pos 7, 1 Bit
+0x004 ObjectTypeCode : Uint4B
+0x008 InvalidAttributes : Uint4B
+0x00c GenericMapping : _GENERIC_MAPPING
+0x000 GenericRead : Uint4B
+0x004 GenericWrite : Uint4B
+0x008 GenericExecute : Uint4B
+0x00c GenericAll : Uint4B
+0x01c ValidAccessMask : Uint4B
+0x020 RetainAccess : Uint4B
+0x024 PoolType :
NonPagedPool = 0n0
PagedPool = 0n1
NonPagedPoolMustSucceed = 0n2
DontUseThisType = 0n3
NonPagedPoolCacheAligned = 0n4
PagedPoolCacheAligned = 0n5
NonPagedPoolCacheAlignedMustS = 0n6
MaxPoolType = 0n7
NonPagedPoolSession = 0n32
PagedPoolSession = 0n33
NonPagedPoolMustSucceedSession = 0n34
DontUseThisTypeSession = 0n35
NonPagedPoolCacheAlignedSession = 0n36
PagedPoolCacheAlignedSession = 0n37
NonPagedPoolCacheAlignedMustSSession = 0n38
+0x028 DefaultPagedPoolCharge : Uint4B
+0x02c DefaultNonPagedPoolCharge : Uint4B
+0x030 DumpProcedure : Ptr64
+0x038 OpenProcedure : Ptr64
+0x040 CloseProcedure : Ptr64
+0x048 DeleteProcedure : Ptr64
+0x050 ParseProcedure : Ptr64
+0x058 SecurityProcedure : Ptr64
+0x060 QueryNameProcedure : Ptr64
+0x068 OkayToCloseProcedure : Ptr64
0: kd> dt test!_OBJECT_TYPE_INITIALIZER -b
+0x000 Length : Uint2B
+0x002 ObjectTypeFlags : <unnamed-tag>
+0x000 ObjectTypeFlags : UChar
+0x000 CaseInsensitive : Pos 0, 1 Bit
+0x000 UnnamedObjectsOnly : Pos 1, 1 Bit
+0x000 UseDefaultObject : Pos 2, 1 Bit
+0x000 SecurityRequired : Pos 3, 1 Bit
+0x000 MaintainHandleCount : Pos 4, 1 Bit
+0x000 MaintainTypeList : Pos 5, 1 Bit
+0x000 SupportsObjectCallbacks : Pos 6, 1 Bit
+0x000 CacheAligned : Pos 7, 1 Bit
+0x004 ObjectTypeCode : Uint4B
+0x008 InvalidAttributes : Uint4B
+0x00c GenericMapping : _GENERIC_MAPPING
+0x000 GenericRead : Uint4B
+0x004 GenericWrite : Uint4B
+0x008 GenericExecute : Uint4B
+0x00c GenericAll : Uint4B
+0x01c ValidAccessMask : Uint4B
+0x020 RetainAccess : Uint4B
+0x024 PoolType :
NonPagedPool = 0n0
NonPagedPoolExecute = 0n0
PagedPool = 0n1
NonPagedPoolMustSucceed = 0n2
DontUseThisType = 0n3
NonPagedPoolCacheAligned = 0n4
PagedPoolCacheAligned = 0n5
NonPagedPoolCacheAlignedMustS = 0n6
MaxPoolType = 0n7
NonPagedPoolBase = 0n0
NonPagedPoolBaseMustSucceed = 0n2
NonPagedPoolBaseCacheAligned = 0n4
NonPagedPoolBaseCacheAlignedMustS = 0n6
NonPagedPoolSession = 0n32
PagedPoolSession = 0n33
NonPagedPoolMustSucceedSession = 0n34
DontUseThisTypeSession = 0n35
NonPagedPoolCacheAlignedSession = 0n36
PagedPoolCacheAlignedSession = 0n37
NonPagedPoolCacheAlignedMustSSession = 0n38
NonPagedPoolNx = 0n512
NonPagedPoolNxCacheAligned = 0n516
NonPagedPoolSessionNx = 0n544
+0x028 DefaultPagedPoolCharge : Uint4B
+0x02c DefaultNonPagedPoolCharge : Uint4B
+0x030 DumpProcedure : Ptr64
+0x038 OpenProcedure : Ptr64
+0x040 CloseProcedure : Ptr64
+0x048 DeleteProcedure : Ptr64
+0x050 ParseProcedure : Ptr64
+0x058 SecurityProcedure : Ptr64
+0x060 QueryNameProcedure : Ptr64
+0x068 OkayToCloseProcedure : Ptr64
*/
NTSTATUS ObCreateObjectType(__in PUNICODE_STRING TypeName, __in POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, __in_opt PSECURITY_DESCRIPTOR SecurityDescriptor, __out POBJECT_TYPE *ObjectType);
POBJECT_TYPE MyObjectType;
//DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
//MyObjectType创建了,如何删除呢?
ObDereferenceObject(MyObjectType);//不行,依然存在。
}
//DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING TypeName;
const GENERIC_MAPPING ExpEventMapping = {
STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
GENERIC_ALL
};
//KdBreakPoint();
__debugbreak();
DriverObject->DriverUnload = Unload;
RtlInitUnicodeString(&TypeName, L"Correy");// Initialize string descriptor.
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
ObjectTypeInitializer.GenericMapping = ExpEventMapping;
ObjectTypeInitializer.PoolType = NonPagedPool;
ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
//这里还可以定义八个方法/函数。
Status = ObCreateObjectType(&TypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR) NULL, &MyObjectType);//XP成功,Win10 64返回参数错误。
#if (NTDDI_VERSION > NTDDI_VISTA)
//XXX
#endif
return Status;//在XP上的另一个验证办法:!object \ObjectTypes\Correy
}
没有评论:
发表评论