ObReferenceObjectByHandle()ソースコード分析



Obreferenceobjectbyhandle Source Code Analysis



まず、コード内の2つの記事を読んだ後、ほとんど理解できます。

https://blog.csdn.net/qq_21000273/article/details/53966150



https://bbs.pediy.com/thread-181544.htm

以下はコメントされたコードです、wrkで



NTSTATUS ObReferenceObjectByHandle ( __in HANDLE Handle, __in ACCESS_MASK DesiredAccess, __in_opt POBJECT_TYPE ObjectType, __in KPROCESSOR_MODE AccessMode, __out PVOID *Object, __out_opt POBJECT_HANDLE_INFORMATION HandleInformation ) /*++ Routine Description: Given a handle to an object this routine returns a pointer to the body of the object with proper ref counts Arguments: Handle - Supplies a handle to the object being referenced. It can also be the result of NtCurrentProcess or NtCurrentThread DesiredAccess - Supplies the access being requested by the caller ObjectType - Optionally supplies the type of the object we are expecting AccessMode - Supplies the processor mode of the access Object - Receives a pointer to the object body if the operation is successful HandleInformation - Optionally receives information regarding the input handle. Return Value: An appropriate NTSTATUS value --*/ { ACCESS_MASK GrantedAccess PHANDLE_TABLE HandleTable POBJECT_HEADER ObjectHeader PHANDLE_TABLE_ENTRY ObjectTableEntry PEPROCESS Process NTSTATUS Status PETHREAD Thread ObpValidateIrql('ObReferenceObjectByHandle') Thread = PsGetCurrentThread () *Object = NULL // // Check is this handle is a kernel handle or one of the two builtin pseudo handles // if ((LONG)(ULONG_PTR) Handle <0) { // // If the handle is equal to the current process handle and the object // type is NULL or type process, then attempt to translate a handle to // the current process. Otherwise, check if the handle is the current // thread handle. // //Translation above // Check if Handle is a kernel handle // (that is, less than 0, that is, the highest bit is marked with KERNEL_HANDLE_MASK). // There are two handles to be treated differently: // Current process handle-1 (0xFFFFFFFF) and current thread handle-2 (0xFFFFFFFE). // if (Handle == NtCurrentProcess()) {//If the handle is equal to the handle of the current process if ((ObjectType == PsProcessType) || (ObjectType == NULL)) { Process = PsGetCurrentProcessByThread(Thread)//Get the current Eprocess object GrantedAccess = Process->GrantedAccess//This field indicates the self-process access permission of the process object if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) || (AccessMode == KernelMode)) {//Agree to access in this case ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process)//Get the Eprocess object header if (ARGUMENT_PRESENT(HandleInformation)) {//If the passed parameter HandleInformation is not NULL, you need to return the relevant OBJECT_HANDLE_INFORMATION structure information. HandleInformation->GrantedAccess = GrantedAccess HandleInformation->HandleAttributes = 0 } ObpIncrPointerCount(ObjectHeader)//Increase the object reference count *Object = Process//Return the object body pointer ASSERT( *Object != NULL ) Status = STATUS_SUCCESS } else { Status = STATUS_ACCESS_DENIED } } else { Status = STATUS_OBJECT_TYPE_MISMATCH } return Status // // If the handle is equal to the current thread handle and the object // type is NULL or type thread, then attempt to translate a handle to // the current thread. Otherwise, the we'll try and translate the // handle // } else if (Handle == NtCurrentThread()) {//if the handle is the current thread if ((ObjectType == PsThreadType) || (ObjectType == NULL)) { GrantedAccess = Thread->GrantedAccess if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) || (AccessMode == KernelMode)) { ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread)//Get the object head of the current thread if (ARGUMENT_PRESENT(HandleInformation)) { HandleInformation->GrantedAccess = GrantedAccess HandleInformation->HandleAttributes = 0 } ObpIncrPointerCount(ObjectHeader)//Increase the count *Object = Thread ASSERT( *Object != NULL ) Status = STATUS_SUCCESS } else { Status = STATUS_ACCESS_DENIED } } else { Status = STATUS_OBJECT_TYPE_MISMATCH } return Status } else if (AccessMode == KernelMode) //If it is called in kernel mode // // Make the handle look like a regular handle // // This is where the kernel handle is actually handled. // Note: The kernel handle can only be accessed in kernel mode. // #define KERNEL_HANDLE_MASK // ((ULONG_PTR)((LONG)0x80000000)) // #define EncodeKernelHandle(H) // (HANDLE)(KERNEL_HANDLE_MASK else { // // The previous mode was user for this kernel handle value. Reject it here. // return STATUS_INVALID_HANDLE } } else { // If Handle is greater than 0 (that is, there is no KERNEL_HANDLE_MASK logo), // Description is not the handle of the System process, // Get EPROCESS from the current ETHREAD to get HandleTable. // //#define PsGetCurrentProcessByThread(xCurrentThread) // (ASSERT((xCurrentThread) == PsGetCurrentThread ()), // CONTAINING_RECORD( // ((xCurrentThread)->Tcb.ApcState.Process), // EPROCESS,Pcb)) // HandleTable = PsGetCurrentProcessByThread(Thread)->ObjectTable//Not a kernel mode call, equal to the handle table of the current calling process } ASSERT(HandleTable != NULL) // // Protect this thread from being suspended while we hold the handle table entry lock // KeEnterCriticalRegionThread(&Thread->Tcb) // // Translate the specified handle to an object table index. // ObjectTableEntry = ExMapHandleToPointerEx (HandleTable, Handle, AccessMode )//Get Handle_Table_Entry structure pointer // // Make sure the object table entry really does exist // if (ObjectTableEntry != NULL) { ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES)//Get the object header // // Optimize for a successful reference by bringing the object header // into the cache exclusive. // ReadForWriteAccess(ObjectHeader) if ((ObjectHeader->Type == ObjectType) || (ObjectType == NULL)) { #if i386 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex ) } else { GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess) } #else GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess) #endif // i386 if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) || (AccessMode == KernelMode)) { PHANDLE_TABLE_ENTRY_INFO ObjectInfo ObjectInfo = ExGetHandleInfo(HandleTable, Handle, TRUE) // // Access to the object is allowed. Return the handle // information is requested, increment the object // pointer count, unlock the handle table and return // a success status. // // Note that this is the only successful return path // out of this routine if the user did not specify // the current process or current thread in the input // handle. // if (ARGUMENT_PRESENT(HandleInformation)) { HandleInformation->GrantedAccess = GrantedAccess HandleInformation->HandleAttributes = ObpGetHandleAttributes(ObjectTableEntry) } // // If this object was audited when it was opened, it may // be necessary to generate an audit now. Check the audit // mask that was saved when the handle was created. // // It is safe to do this check in a non-atomic fashion, // because bits will never be added to this mask once it is // created. // if ( (ObjectTableEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE) && (ObjectInfo != NULL) && (ObjectInfo->AuditMask != 0) && (DesiredAccess != 0)) { ObpAuditObjectAccess( Handle, ObjectInfo, &ObjectHeader->Type->Name, DesiredAccess ) } ObpIncrPointerCount(ObjectHeader) ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry ) KeLeaveCriticalRegionThread(&Thread->Tcb) *Object = &ObjectHeader->Body ASSERT( *Object != NULL ) return STATUS_SUCCESS } else { Status = STATUS_ACCESS_DENIED } } else { Status = STATUS_OBJECT_TYPE_MISMATCH } ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry ) } else { Status = STATUS_INVALID_HANDLE } KeLeaveCriticalRegionThread(&Thread->Tcb) return Status }