예제 #1
0
NTSTATUS BDKitCloseFile(__in HANDLE hFile)
{
	// 这里防止verifier只能关闭内核态句柄, 驱动在传递给用户态句柄时要注意转换
	if (IsKernelHandle(hFile, KernelMode)) 
	{
		return ZwClose(hFile);
	}

	return STATUS_HANDLE_NOT_CLOSABLE;
}
예제 #2
0
NTSTATUS BDKitTerminateProcessByAPI( __in PEPROCESS EProcess, __in ULONG ExitCode )
{
	NTSTATUS	nsStatus	= STATUS_UNSUCCESSFUL;
	HANDLE		hProcess	= NULL;
	BOOLEAN		bAttach		= FALSE;
	KAPC_STATE	kApcState	= {0x00};

	do 
	{
		if ( bAttach == TRUE )
		{
			_KeStackAttachProcess ((PKPROCESS)EProcess, &kApcState);

			nsStatus = ZwTerminateProcess (0, STATUS_SUCCESS);
		}
		else
		{
			nsStatus = ObOpenObjectByPointer (
				EProcess,
				OBJ_KERNEL_HANDLE, 
				NULL,
				PROCESS_ALL_ACCESS,
				NULL,
				KernelMode,
				&hProcess
				);
			BDKit_If_Not_Break(NT_SUCCESS(nsStatus));

			nsStatus = ZwTerminateProcess (hProcess, ExitCode);
		}
		BDKit_If_Not_Break(NT_SUCCESS(nsStatus));

	} while (FALSE);

	if ( IsKernelHandle(hProcess, KernelMode) )
	{
		BDKitCloseHandle(hProcess);
	}
	//BDKitCloseObject(EProcess);

	return nsStatus;
}
예제 #3
0
파일: obclose.c 프로젝트: mingpen/OpenNT
NTSTATUS
NtClose (
    IN HANDLE Handle
    )

/*++

Routine Description:

    This function is used to close access to the specified handle

Arguments:

    Handle - Supplies the handle being closed

Return Value:

    An appropriate status value

--*/

{
    PHANDLE_TABLE ObjectTable;
    PHANDLE_TABLE_ENTRY ObjectTableEntry;
    PVOID Object;
    ULONG CapturedGrantedAccess;
    ULONG CapturedAttributes;
    POBJECT_HEADER ObjectHeader;
    POBJECT_TYPE ObjectType;
    NTSTATUS Status;
    BOOLEAN AttachedToProcess = FALSE;
    KAPC_STATE ApcState;

    //
    //  Protect ourselves from being interrupted while we hold a handle table
    //  entry lock
    //

    KeEnterCriticalRegion();

    try {

    #if DBG
        KIRQL SaveIrql;
    #endif // DBG

        ObpValidateIrql( "NtClose" );

        ObpBeginTypeSpecificCallOut( SaveIrql );

    #if DBG

        //
        //  On checked builds, check that if the Kernel handle bit is set, then
        //  we're coming from Kernel mode. We should probably fail the call if
        //  bit set && !Kmode
        //

        if ((Handle != NtCurrentThread()) && (Handle != NtCurrentProcess())) {

            ASSERT((Handle < 0 ) ? (KeGetPreviousMode() == KernelMode) : TRUE);
        }

    #endif
        //
        //  For the current process we will grab its handle/object table and
        //  translate the handle to its corresponding table entry.  If the
        //  call is successful it also lock down the handle table.  But first
        //  check for a kernel handle and attach and use that table if so.
        //

        if (IsKernelHandle( Handle, KeGetPreviousMode() ))  {

            Handle = DecodeKernelHandle( Handle );

            ObjectTable = ObpKernelHandleTable;

            //
            //  Go to the system process if we have to
            //
            if (PsGetCurrentProcess() != PsInitialSystemProcess) {
               KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState);
               AttachedToProcess = TRUE;
            }

        } else {

            ObjectTable = ObpGetObjectTable();
        }

        ObjectTableEntry = ExMapHandleToPointer( ObjectTable,
                                                 Handle );

        //
        //  Check that the specified handle is legitimate otherwise we can
        //  assume the caller just passed in some bogus handle value
        //

        if (ObjectTableEntry != NULL) {

            //
            //  From the object table entry we can grab a pointer to the object
            //  header, get its type and its body
            //

            ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
            ObjectType = ObjectHeader->Type;
            Object = &ObjectHeader->Body;

            //
            //  If the object type specifies an okay to close procedure then we
            //  need to invoke that callback.  If the callback doesn't want us to
            //  close handle then unlock the object table and return the error
            //  to our caller
            //

            if (ObjectType->TypeInfo.OkayToCloseProcedure != NULL) {

                if (!(*ObjectType->TypeInfo.OkayToCloseProcedure)( PsGetCurrentProcess(), Object, Handle )) {

                    ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object );

                    ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

                    //
                    //  If we are attached to the system process then return
                    //  back to our caller
                    //

                    if (AttachedToProcess) {

                        KeUnstackDetachProcess(&ApcState);
                        AttachedToProcess = FALSE;
                    }

                    Status = STATUS_HANDLE_NOT_CLOSABLE;
                    leave;
                }
            }

            CapturedAttributes = ObjectTableEntry->ObAttributes;

            //
            //  If the previous mode was user and the handle is protected from
            //  being closed, then we'll either raise or return an error depending
            //  on the global flags and debugger port situation.
            //

            if ((CapturedAttributes & OBJ_PROTECT_CLOSE) != 0) {

                if (KeGetPreviousMode() != KernelMode) {

                    ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

                    if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
                        (PsGetCurrentProcess()->DebugPort != NULL)) {

                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE);
                        leave;

                    } else {

                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = STATUS_HANDLE_NOT_CLOSABLE;
                        leave;
                    }

                } else {

                    if ((!PsIsThreadTerminating(PsGetCurrentThread())) &&
                        (PsGetCurrentProcess()->Peb != NULL)) {

                        ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

    #if DBG
                        //
                        //  bugcheck here on checked builds if kernel mode code is
                        //  closing a protected handle and process is not exiting.
                        //  Ignore if no PEB as this occurs if process is killed
                        //  before really starting.
                        //

                        KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 0, 0, 0);
    #else
                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = STATUS_HANDLE_NOT_CLOSABLE;
                        leave;
    #endif // DBG

                    }
                }
            }

            //
            //  Get the granted access for the handle
            //

    #if defined(_X86_) && !FPO

            if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {

                CapturedGrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );

            } else {

                CapturedGrantedAccess = ObjectTableEntry->GrantedAccess;
            }

    #else

            CapturedGrantedAccess = ObjectTableEntry->GrantedAccess;

    #endif // _X86_ && !FPO

            //
            //  Now remove the handle from the handle table
            //

            ExDestroyHandle( ObjectTable,
                             Handle,
                             ObjectTableEntry );

            //
            //  perform any auditing required
            //

            //
            //  Extract the value of the GenerateOnClose bit stored
            //  after object open auditing is performed.  This value
            //  was stored by a call to ObSetGenerateOnClosed.
            //

            if (CapturedAttributes & OBJ_AUDIT_OBJECT_CLOSE) {

                if ( SepAdtAuditingEnabled ) {

                    SeCloseObjectAuditAlarm( Object,
                                             (HANDLE)((ULONG_PTR)Handle & ~OBJ_HANDLE_TAGBITS),  // Mask off the tagbits defined for OB objects.
                                             TRUE );
                }
            }

            //
            //  Since we took the handle away we need to decrement the objects
            //  handle count, and remove a reference
            //

            ObpDecrementHandleCount( PsGetCurrentProcess(),
                                     ObjectHeader,
                                     ObjectHeader->Type,
                                     CapturedGrantedAccess );

            ObDereferenceObject( Object );

            ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object );

            //
            //  If we are attached to the system process then return
            //  back to our caller
            //

            if (AttachedToProcess) {
                KeUnstackDetachProcess(&ApcState);
                AttachedToProcess = FALSE;
            }

            //
            //  And return to our caller
            //

            Status = STATUS_SUCCESS;
            leave;

        } else {

            //
            //  At this point the input handle did not translate to a valid
            //  object table entry
            //

            ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObpTypeObjectType, Handle );

            //
            //  If we are attached to the system process then return
            //  back to our caller
            //

            if (AttachedToProcess) {
                KeUnstackDetachProcess(&ApcState);
                AttachedToProcess = FALSE;
            }

            //
            //  Now if the handle is not null and it does not represent the
            //  current thread or process then if we're user mode we either raise
            //  or return an error
            //

            if ((Handle != NULL) &&
                (Handle != NtCurrentThread()) &&
                (Handle != NtCurrentProcess())) {

                if (KeGetPreviousMode() != KernelMode) {

                    if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
                        (PsGetCurrentProcess()->DebugPort != NULL)) {

                        Status = KeRaiseUserException(STATUS_INVALID_HANDLE);
                        leave;

                    } else {

                        Status = STATUS_INVALID_HANDLE;
                        leave;
                    }

                } else {

                    //
                    //  bugcheck here if kernel debugger is enabled and if kernel mode code is
                    //  closing a bogus handle and process is not exiting.  Ignore
                    //  if no PEB as this occurs if process is killed before
                    //  really starting.
                    //

                    if (( !PsIsThreadTerminating(PsGetCurrentThread())) &&
                        (PsGetCurrentProcess()->Peb != NULL)) {

                        if (KdDebuggerEnabled) {
                            KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 1, 0, 0);
                        }
                    }

                }
            }

            Status = STATUS_INVALID_HANDLE;
            leave;
        }

    } finally {

        KeLeaveCriticalRegion();
    }

    return Status;
}
예제 #4
0
파일: ObHandle.c 프로젝트: Moteesh/reactos
static
VOID
TestDuplicate(
    _In_ HANDLE Handle)
{
    NTSTATUS Status;
    HANDLE NewHandle;
    struct
    {
        ACCESS_MASK DesiredAccess;
        ULONG RequestedAttributes;
        ULONG Options;
        ACCESS_MASK GrantedAccess;
        ULONG ExpectedAttributes;
    } Tests[] =
    {
        { DIRECTORY_ALL_ACCESS, 0,                  0,
          DIRECTORY_ALL_ACCESS, 0 },
        { DIRECTORY_ALL_ACCESS, OBJ_KERNEL_HANDLE,  0,
          DIRECTORY_ALL_ACCESS, 0 },
        { DIRECTORY_QUERY,      0,                  0,
          DIRECTORY_QUERY,      0 },
        { DIRECTORY_QUERY,      OBJ_INHERIT,        0,
          DIRECTORY_QUERY,      OBJ_INHERIT },
        { DIRECTORY_QUERY,      OBJ_INHERIT,        DUPLICATE_SAME_ACCESS,
          DIRECTORY_ALL_ACCESS, OBJ_INHERIT },
        /* 5 */
        { DIRECTORY_QUERY,      OBJ_INHERIT,        DUPLICATE_SAME_ATTRIBUTES,
          DIRECTORY_QUERY,      0 },
        { DIRECTORY_QUERY,      OBJ_INHERIT,        DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES,
          DIRECTORY_ALL_ACCESS, 0 },
    };
    ULONG i;

    for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
    {
        trace("Test %lu\n", i);
        Status = ZwDuplicateObject(ZwCurrentProcess(),
                                   Handle,
                                   ZwCurrentProcess(),
                                   &NewHandle,
                                   Tests[i].DesiredAccess,
                                   Tests[i].RequestedAttributes,
                                   Tests[i].Options);
        ok_eq_hex(Status, STATUS_SUCCESS);
        if (!skip(NT_SUCCESS(Status), "DuplicateHandle failed\n"))
        {
            ok(IsUserHandle(NewHandle), "New handle = %p\n", NewHandle);
            CheckObject(NewHandle, 3UL, 2UL, Tests[i].ExpectedAttributes, Tests[i].GrantedAccess);
            CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS);

            Status = ObCloseHandle(NewHandle, UserMode);
            ok_eq_hex(Status, STATUS_SUCCESS);
            CheckObject(Handle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS);
        }
    }

    /* If TargetProcess is the System process, we do get a kernel handle */
    Status = ZwDuplicateObject(ZwCurrentProcess(),
                               Handle,
                               SystemProcessHandle,
                               &NewHandle,
                               DIRECTORY_ALL_ACCESS,
                               OBJ_KERNEL_HANDLE,
                               0);
    ok_eq_hex(Status, STATUS_SUCCESS);
    if (!skip(NT_SUCCESS(Status), "DuplicateHandle failed\n"))
    {
        ok(IsKernelHandle(NewHandle), "New handle = %p\n", NewHandle);
        CheckObject(NewHandle, 3UL, 2UL, 0, DIRECTORY_ALL_ACCESS);
        CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS);

        Status = ObCloseHandle(NewHandle, UserMode);
        ok_eq_hex(Status, STATUS_INVALID_HANDLE);
        CheckObject(NewHandle, 3UL, 2UL, 0, DIRECTORY_ALL_ACCESS);
        CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS);

        if (IsKernelHandle(NewHandle))
        {
            Status = ObCloseHandle(NewHandle, KernelMode);
            ok_eq_hex(Status, STATUS_SUCCESS);
            CheckObject(Handle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS);
        }
    }
}