ObReferenceObjectByHandle() 源代碼分析

首先代碼有兩篇文章閱讀後就懂得差不多了

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.
        //
        //以上翻譯
        // 檢查Handle是不是內核句柄
        // (即小於0,也就是最高位帶KERNEL_HANDLE_MASK標識)。
        // 這裏有兩個句柄要區別處理:
        // 當前進程句柄-1(0xFFFFFFFF)和當前線程句柄-2(0xFFFFFFFE)。
        //

        if (Handle == NtCurrentProcess()) {//如果句柄等於當前進程的句柄

            if ((ObjectType == PsProcessType) || (ObjectType == NULL)) {

                Process = PsGetCurrentProcessByThread(Thread);//得到當前Eprocess對象
                GrantedAccess = Process->GrantedAccess;//這個字段表示進程對象的自我進程訪問權限

                if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
                    (AccessMode == KernelMode)) {//這種情況同意訪問

                    ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);//得到Eprocess對象頭

                    if (ARGUMENT_PRESENT(HandleInformation)) {//假如傳遞的參數 HandleInformation 不爲 NULL 時,需要返回相關的 OBJECT_HANDLE_INFORMATION 結構信息。

                        HandleInformation->GrantedAccess = GrantedAccess;
                        HandleInformation->HandleAttributes = 0;
                    }

                    ObpIncrPointerCount(ObjectHeader);//增加對象引用計數
                    *Object = Process;//返回對象體指針

                    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 ((ObjectType == PsThreadType) || (ObjectType == NULL)) {

                GrantedAccess = Thread->GrantedAccess;

                if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
                    (AccessMode == KernelMode)) {

                    ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);//得到當前線程的對象頭

                    if (ARGUMENT_PRESENT(HandleInformation)) {

                        HandleInformation->GrantedAccess = GrantedAccess;
                        HandleInformation->HandleAttributes = 0;
                    }

                    ObpIncrPointerCount(ObjectHeader);//增加計數
                    *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) {//如果是在內核模式調用的
            //
            //  Make the handle look like a regular handle
            //
            // 這裏纔是真正處理內核句柄的地方。
            // 注意:內核句柄只能在內核模式訪問。
            // #define KERNEL_HANDLE_MASK\
            // ((ULONG_PTR)((LONG)0x80000000))
            // #define EncodeKernelHandle(H) \
            //  (HANDLE)(KERNEL_HANDLE_MASK | (ULONG_PTR)(H))
            // #define DecodeKernelHandle(H) \
            //  (HANDLE)(KERNEL_HANDLE_MASK ^ (ULONG_PTR)(H))
            // 內核句柄是還KERNEL_HANDLE_MASK標識的(即最高位爲1)。
            // 記住,這裏的Handle不是一個真正的Handle,
            // 在使用前必須轉化成正規Handle。
            // 這裏的DecodeKernelHandle就是將最高位的標識去除。
            // 
            Handle = DecodeKernelHandle( Handle );

            //
            //  The global kernel handle table
            //  這裏得到的句柄表就是全局的內核句柄表ObpKernelHandleTable。
            //
            HandleTable = ObpKernelHandleTable;
        } else {
            //
            // The previous mode was user for this kernel handle value. Reject it here.
            //

            return STATUS_INVALID_HANDLE;
        }

    } else {

        // 如果Handle大於0(即沒有KERNEL_HANDLE_MASK標識),
        // 說明不是System進程的句柄,
        // 就從當前ETHREAD得到EPROCESS,從而得到HandleTable。
        //
        //#define PsGetCurrentProcessByThread(xCurrentThread) \
        //  (ASSERT((xCurrentThread) == PsGetCurrentThread ()),\
        //  CONTAINING_RECORD(\
        //  ((xCurrentThread)->Tcb.ApcState.Process),\
        //  EPROCESS,Pcb))
        // 
        HandleTable = PsGetCurrentProcessByThread(Thread)->ObjectTable;//不是內核模式調用,等於當前調用進程的句柄表
    }

    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 );//得到Handle_Table_Entry結構指針


    //
    //  Make sure the object table entry really does exist
    //

    if (ObjectTableEntry != NULL) {

        ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);//得到對象頭

        //
        // 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;
}

 

發佈了168 篇原創文章 · 獲贊 17 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章