建立對象的三大步驟:安全
1.經過ObCreateObject函數建立目標對象。ide
2.目標對象自己的初始化函數
3.經過ObInsertObject將目標對象插入對象目錄和句柄表,並返回句柄。ui
ObCreateObject函數用來建立一個指定類型的內核對象。spa
NTSTATUS ObCreateObject(IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object) { ObjectCreateInfo = ObpAllocateObjectCreateInfoBuffer(LookasideCreateInfoList); Status = ObpCaptureObjectCreateInformation(ObjectAttributes,FALSE,ObjectCreateInfo, &ObjectName);//提取ObjectAttributes中的字段 if (!PagedPoolCharge) PagedPoolCharge = Type->TypeInfo.DefaultPagedPoolCharge; if (!NonPagedPoolCharge) NonPagedPoolCharge = Type->TypeInfo.DefaultNonPagedPoolCharge; ObjectCreateInfo->PagedPoolCharge = PagedPoolCharge; ObjectCreateInfo->NonPagedPoolCharge = NonPagedPoolCharge; //從對應池中分配內存,建立對應的對象 Status = ObpAllocateObject(ObjectCreateInfo,&ObjectName,Type,ObjectSize,AccessMode, &Header); return Status; }
其實真正的工做函數是ObpAllocateObject,它內部調用ExAllocatePoolWithTag(ObjectType->PoolType, 可選頭總大小+ ObjectSize, Tag)分配對象內存,而後初始化設置頭部中的Flags等其餘工做。(絕大多數內核對象都分配在非分頁池中)orm
ObCreateObject函數的第二個參數指向一個_OBJECT_ATTRIBUTES結構,這是一個很是重要的結構。對象
typedef struct _OBJECT_ATTRIBUTES { ULONG Length;//本結構體的長度 HANDLE RootDirectory;//相對目錄(不必定是父目錄) PUNICODE_STRING ObjectName;//相對RootDirectory這個目錄的剩餘路徑 或者 全路徑 //上面兩個字段一塊兒間接構成對象的全路徑 ULONG Attributes;//打開屬性,對象屬性與句柄屬性的混合 PVOID SecurityDescriptor;// SD安全描述符 PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;
建立對象、打開對象時都會用到這個結構。blog
OBJECT_ATTRIBUTES結構體中的Attributes字段是個混合成員,由句柄屬性、對象屬性、打開屬性複合而成,能夠取下面的組合繼承
OBJ_INHERIT://句柄屬性,表示句柄是否可繼承給子進程進程
OBJ_PERMANENT://指該對象是否永久存在於對象目錄中直到對象銷燬.(目錄\符號連接\設備\文件 都是)
OBJ_EXLUSIVE://對象屬性,指該對象同一時刻只能被一個進程獨佔打開
OBJ_CASE_INSENSITIVE://打開屬性,表示本次打開操做查找比較對象名時大小寫不敏感
OBJ_OPENIF://打開屬性,表示if對象存在就打開
OBJ_OPENLINK://打開屬性,表示本次打開是否能夠直接打開符號連接
OBJ_KERNEL_HANDLE://句柄屬性,表示要求獲得一個內核句柄
而對象頭中的Flags字段則徹底表示對象的一些屬性標誌
OB_FLAG_CREATE_INFO;//表示頭部中含有建立時的屬性信息
OB_FLAG_CREATOR_INFO;//表示含有建立者進程信息
OB_FLAG_KERNEL_MODE://表示PreviousMode是內核模式的代碼建立的本對象
OB_FLAG_EXCLUSIVE://表示同一時刻只能被一個進程獨佔打開
OB_FLAG_PERMANET://永久性對象,直到對象徹底銷燬時才脫離對象目錄
OB_FLAG_SINGLE_PROCESS://表示含有每進程的句柄統計信息
OB_FLAG_DEFER_DELETE;//標記本對象被延遲刪除了
建立的對象,若是有名字,就須要插入到對象目錄和句柄表中。即便沒有名字,也須要插入到句柄表中,這樣才能讓應用程序得以找到該對象以進行訪問。這就是ObInsertObject函數的功能:
NTSTATUS ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, OUT PHANDLE Handle)//返回獲得的句柄 { ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); ObjectCreateInfo = ObjectHeader->ObjectCreateInfo; ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader); ObjectType = ObjectHeader->Type; ObjectName = NULL; if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) ObjectName = &ObjectNameInfo->Name; PreviousMode = KeGetPreviousMode(); //無名對象(而且不須要安全控制)就不掛入對象目錄,僅僅插入句柄表中 if ( (ObjectName==NULL) && !(ObjectType->TypeInfo.SecurityRequired)) { ObjectHeader->ObjectCreateInfo = NULL; Status = ObpCreateUnnamedHandle(Object,DesiredAccess,ObjectCreateInfo->Attributes, PreviousMode,Handle); return Status; } InsertObject = Object; if (ObjectName)//如果一個有名對象 { //這個函數有兩種用途。 //當Object不爲NULL表示將Object插入到對象目錄中的指定位置 //當Object爲NULL表示查找指定的對象目錄位置處的對象 //兩種用途都將指定目錄位置處的對象返回到InsertObject中 Status = ObpLookupObjectName(ObjectCreateInfo->RootDirectory, ObjectName, ObjectCreateInfo->Attributes, ObjectType, ObjectCreateInfo->ParseContext, Object,//要插入的對象 &InsertObject);//返回最終那個位置處的對象 //若是原位置處已有同名對象,插入失敗 if ((NT_SUCCESS(Status)) && (InsertObject) && (Object != InsertObject)) { OpenReason = ObOpenHandle;//既然插入失敗了,那就是要打開對象,得到句柄 if (ObjectCreateInfo->Attributes & OBJ_OPENIF)//檢查本次打開操做的要求 { if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type) Status = STATUS_OBJECT_TYPE_MISMATCH; else Status = STATUS_OBJECT_NAME_EXISTS;//看到沒,應用層常常返回這個出錯值 } else { Status = STATUS_OBJECT_NAME_COLLISION; } return Status; } } if (InsertObject == Object)//if 插入成功 OpenReason = ObCreateHandle;//只有第一次建立對象的時候纔會插入對象目錄中 ObjectHeader->ObjectCreateInfo = NULL;//再也不須要了 if (Handle)//若是用戶要求插入句柄表,就插入句柄表,獲得一個句柄 { Status = ObpCreateHandle(OpenReason,InsertObject,AccessState, ObjectCreateInfo->Attributes, PreviousMode,Handle); } return Status; }