Ejemplo n.º 1
0
/* KphpIsAccessAllowed
 * 
 * Checks if the specified access is allowed, according to process 
 * protection rules.
 * 
 * Thread safety: Full
 * IRQL: <= DISPATCH_LEVEL
 */
BOOLEAN KphpIsAccessAllowed(
    __in PVOID Object,
    __in KPROCESSOR_MODE AccessMode,
    __in ACCESS_MASK DesiredAccess
    )
{
    POBJECT_TYPE objectType;
    PEPROCESS processObject;
    BOOLEAN isThread = FALSE;
    
    objectType = KphGetObjectTypeNt(Object);
    /* It doesn't matter if it isn't actually a process because we won't be 
       dereferencing it. */
    processObject = (PEPROCESS)Object;
    isThread = objectType == *PsThreadType;
    
    /* If this is a thread, get its parent process. */
    if (isThread)
        processObject = IoThreadToProcess((PETHREAD)Object);
    
    if (
        processObject != PsGetCurrentProcess() && /* let the caller open its own processes/threads */
        (objectType == *PsProcessType || objectType == *PsThreadType) /* only protect processes and threads */
        )
    {
        KPH_PROCESS_ENTRY processEntry;
        
        /* Search for and copy the corresponding process protection entry. */
        if (KphProtectFindEntry(processObject, NULL, &processEntry))
        {
            ACCESS_MASK mask = 
                isThread ? processEntry.ThreadAllowMask : processEntry.ProcessAllowMask;
            
            /* The process/thread is protected. Check if the requested access is allowed. */
            if (
                /* check if kernel-mode is exempt from protection */
                !(processEntry.AllowKernelMode && AccessMode == KernelMode) && 
                /* allow the creator of the rule to bypass protection */
                processEntry.CreatorProcess != PsGetCurrentProcess() && 
                (DesiredAccess & mask) != DesiredAccess
                )
            {
                /* Access denied. */
                dprintf(
                    "%d: Access denied: 0x%08x (%s)\n",
                    PsGetCurrentProcessId(),
                    DesiredAccess,
                    isThread ? "Thread" : "Process"
                    );
                
                return FALSE;
            }
        }
    }
    
    return TRUE;
}
Ejemplo n.º 2
0
/// <summary>
/// This routine is called by the operating system
/// when a process or thread handle operation occurs.
/// </summary>
OB_PREOP_CALLBACK_STATUS HspObPreCallback(
	_In_ PVOID RegistrationContext,
	_Inout_ POB_PRE_OPERATION_INFORMATION OperationInformation)
{
	PEPROCESS process;
	ACCESS_MASK processAccessBitsToClear;
	ACCESS_MASK threadAccessBitsToClear;

	UNREFERENCED_PARAMETER(RegistrationContext);

	// ObRegisterCallbacks doesn't allow changing access of kernel handles.
	if (OperationInformation->KernelHandle)
		return OB_PREOP_SUCCESS;

	// Get target process.
	if (OperationInformation->ObjectType == *PsProcessType)
		process = OperationInformation->Object;
	else if (OperationInformation->ObjectType == *PsThreadType)
		process = IoThreadToProcess(OperationInformation->Object);
	else
		return OB_PREOP_SUCCESS; // Shouldn't ever happen.

	// Allow process to open itself.
	if (process == IoGetCurrentProcess())
		return OB_PREOP_SUCCESS;

	if (HsIsProcessProtected(process, &processAccessBitsToClear, &threadAccessBitsToClear))
	{
		ACCESS_MASK accessBitsToClear;

		if (OperationInformation->ObjectType == *PsProcessType)
			accessBitsToClear = processAccessBitsToClear;
		else
			accessBitsToClear = threadAccessBitsToClear;

		// Remove access flags.
		if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
		{
			OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~accessBitsToClear;
		}
		else if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
		{
			OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~accessBitsToClear;
		}
	}

	return OB_PREOP_SUCCESS;
}
Ejemplo n.º 3
0
 __checkReturn
 NT_TIB32* GetWow64Teb(
     __in PETHREAD thread
 )
 {
     if(PsGetProcessWow64Process(IoThreadToProcess(thread)))
     {
         NT_TIB* teb = reinterpret_cast<NT_TIB*>(PsGetThreadTeb(thread));
         if (teb)
         {
             NT_TIB32* teb32 = reinterpret_cast<NT_TIB32*>(teb->ExceptionList);
             if (teb32 && ((ULONG_PTR)teb32->Self == (ULONG_PTR)teb32))
                 return teb32;
         }
     }
     return NULL;
 }
Ejemplo n.º 4
0
NTSTATUS HwlTerminateProcess64(PEPROCESS Process)
{
	//get pspterminatethreadbypointer
	ULONG32 callcode=0;
	ULONG64 AddressOfPspTTBP=0, AddressOfPsTST=0, i=0;
	PETHREAD Thread=NULL;
	PEPROCESS tProcess=NULL;
	NTSTATUS status=0;
	if(PspTerminateThreadByPointer==NULL)
	{
		AddressOfPsTST=(ULONG64)GetFunctionAddr(L"PsTerminateSystemThread");
		if(AddressOfPsTST==0)
			return STATUS_UNSUCCESSFUL;
		for(i=1;i<0xff;i++)
		{
			if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
			{
				if(*(BYTE *)(AddressOfPsTST+i)==0x01 && *(BYTE *)(AddressOfPsTST+i+1)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址
				{
					RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+2),4);
					AddressOfPspTTBP=(ULONG64)callcode + 5 + AddressOfPsTST+i+1;
				}
			}
		}
		PspTerminateThreadByPointer=(PSPTERMINATETHREADBYPOINTER)AddressOfPspTTBP;
	}
	//loop call pspterminatethreadbypointer
	for(i=4;i<0x40000;i+=4)
	{
		status=PsLookupThreadByThreadId((HANDLE)i, &Thread);
		if(NT_SUCCESS(status))
		{
			tProcess=IoThreadToProcess(Thread);
			if(tProcess==Process)
				PspTerminateThreadByPointer(Thread,0,1);
			ObDereferenceObject(Thread);
		}
	}
	//return status
	return STATUS_SUCCESS;
}
Ejemplo n.º 5
0
NTSTATUS 
FakeObReferenceObjectByHandle(
                          IN HANDLE  Handle,
                          IN ACCESS_MASK  DesiredAccess,
                          IN POBJECT_TYPE  ObjectType  OPTIONAL,
                          IN KPROCESSOR_MODE  AccessMode,
                          OUT PVOID  *Object,
                          OUT POBJECT_HANDLE_INFORMATION  HandleInformation  OPTIONAL
                          )
{
    NTSTATUS status;
    KIRQL oldIrql;

    __asm {
        push HandleInformation;
        push Object;
        movzx eax, AccessMode;
        push eax;
        push ObjectType;
        push DesiredAccess;
        push Handle;
        lea eax, ObReferenceObjectByHandleJmpBack;
        call eax;
        mov status, eax;
    }

    if(!NT_SUCCESS(status))
        return status;

    if(!IsProcessObject(*Object) &&
        !IsThreadObject(*Object))
        return status;

    if(IsProcessObject(*Object)) {
        KeAcquireSpinLock(&ProtectObjectLock, &oldIrql);
        if(PsGetCurrentProcess() == *Object ||
           PsGetCurrentProcess() == CsrssProcess ||
           !HashTableCheck(&ProtectObject, (ULONG)*Object))
        {
           KeReleaseSpinLock(&ProtectObjectLock, oldIrql);
           return status;
        }

        KeReleaseSpinLock(&ProtectObjectLock, oldIrql);
        ObDereferenceObject(*Object);
        *Object = NULL;
        return STATUS_ACCESS_DENIED;
    }
    else if(IsThreadObject(*Object)) {
        KeAcquireSpinLock(&ProtectObjectLock, &oldIrql);
        if(PsGetCurrentProcess() == IoThreadToProcess(*Object) ||
           PsGetCurrentProcess() == CsrssProcess ||
           !HashTableCheck(&ProtectObject, (ULONG)*Object))
        {
           KeReleaseSpinLock(&ProtectObjectLock, oldIrql);
           return status;
        }

        KeReleaseSpinLock(&ProtectObjectLock, oldIrql);
        ObDereferenceObject(*Object);
        *Object = NULL;
        return STATUS_ACCESS_DENIED;
    }

    return status;
}
Ejemplo n.º 6
0
FLT_PREOP_CALLBACK_STATUS
PreFileOperationCallback (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext
    )
{
	NTSTATUS status;
	PFLT_FILE_NAME_INFORMATION pFileNameInformation;
	PFILE_EVENT pFileEvent;
	LARGE_INTEGER CurrentSystemTime;
	LARGE_INTEGER CurrentLocalTime;
	ULONG returnedLength;
	//HANDLE hThread;
	//HANDLE handle5;
	TIME_FIELDS TimeFields;
	BOOLEAN pathNameFound = FALSE;
	UNICODE_STRING filePath;
	
	FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
	
	/* If this is a callback for a FS Filter driver then we ignore the event */
	if(FLT_IS_FS_FILTER_OPERATION(Data))
	{
		return FLT_PREOP_SUCCESS_NO_CALLBACK;
	}

	/* Allocate a large 64kb string ... maximum path name allowed in windows */
	filePath.Length = 0;
	filePath.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR);
	filePath.Buffer = ExAllocatePoolWithTag(NonPagedPool, filePath.MaximumLength, FILE_POOL_TAG); 

	if(filePath.Buffer == NULL)
	{
		return FLT_PREOP_SUCCESS_NO_CALLBACK;
	}

	if (FltObjects->FileObject != NULL && Data != NULL) {
		status = FltGetFileNameInformation( Data,
											FLT_FILE_NAME_NORMALIZED |
											FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
											&pFileNameInformation );
		if(NT_SUCCESS(status))
		{
			if(pFileNameInformation->Name.Length > 0)
			{
				RtlUnicodeStringCopy(&filePath, &pFileNameInformation->Name);
				//RtlStringCbCopyUnicodeString(pFileEvent->filePath, 1024, &pFileNameInformation->Name);
				pathNameFound = TRUE;
			}
			/* Backup the file if it is marked for deletion */
			CopyFileIfBeingDeleted (Data,FltObjects,pFileNameInformation);

			/* Release the file name information structure if it was used */
			if(pFileNameInformation != NULL)
			{
				FltReleaseFileNameInformation(pFileNameInformation);
			}
		} else {
			NTSTATUS lstatus;
            PFLT_FILE_NAME_INFORMATION pLFileNameInformation;
            lstatus = FltGetFileNameInformation( Data,
				FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
				&pLFileNameInformation);
			if(NT_SUCCESS(lstatus))
			{
				if(pLFileNameInformation->Name.Length > 0)
				{
					RtlUnicodeStringCopy(&filePath, &pLFileNameInformation->Name);
					//RtlStringCbCopyUnicodeString(pFileEvent->filePath, 1024, &pLFileNameInformation->Name);
					pathNameFound = TRUE;
				}
				/* Backup the file if it is marked for deletion */
				CopyFileIfBeingDeleted (Data,FltObjects,pFileNameInformation);

				/* Release the file name information structure if it was used */
				if(pLFileNameInformation != NULL)
				{
					FltReleaseFileNameInformation(pLFileNameInformation);
				}
			}
		}
	}

	/* If path name could not be found the file monitor uses the file name stored
	   in the FileObject. The documentation says that we shouldn't use this info
	   as it may not be correct. It does however allow us get some nice file events
	   such as the system process writing to the $MFT file etc. Remove this code if
	   problems start to occur */
	if( (pathNameFound == FALSE) && 
		(FltObjects->FileObject != NULL) &&
		(FltObjects->FileObject->RelatedFileObject == NULL) &&
		(FltObjects->FileObject->FileName.Length > 0))
	{
		NTSTATUS status;
		ULONG size;
		UNICODE_STRING szTempPath;
		UNICODE_STRING szDevice;
		UNICODE_STRING szFileNameDevice;

		/* Check the FileObject->FileName isn't already a complete filepath */
		szFileNameDevice.Length = FltObjects->FileObject->FileName.Length;
		szFileNameDevice.MaximumLength = FltObjects->FileObject->FileName.MaximumLength;
		szFileNameDevice.Buffer = ExAllocatePoolWithTag(NonPagedPool, szFileNameDevice.MaximumLength, FILE_POOL_TAG);
		RtlInitUnicodeString(&szDevice, L"\\Device");
		if(FltObjects->FileObject->FileName.Length >= szDevice.Length)
		{
			RtlUnicodeStringCchCopyN(&szFileNameDevice, &FltObjects->FileObject->FileName, 7);
		}

		if(RtlEqualUnicodeString(&szDevice, &szFileNameDevice, TRUE))
		{
			RtlUnicodeStringCopy(&filePath, &FltObjects->FileObject->FileName);
			pathNameFound = TRUE;
		} else {
			szTempPath.Length = 0;
			szTempPath.MaximumLength = FltObjects->FileObject->FileName.MaximumLength + 2;

			/* Get the volume name of where the event came from */
			status = FltGetVolumeName(
						FltObjects->Volume,
						NULL,
						&size
						);
			if(status == STATUS_BUFFER_TOO_SMALL)
			{
				szTempPath.MaximumLength += (USHORT)size;
				szTempPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, szTempPath.MaximumLength, FILE_POOL_TAG);
				
				if(szTempPath.Buffer != NULL)
				{
					status = FltGetVolumeName(
							FltObjects->Volume,
							&szTempPath,
							&size
							);
					if(NT_SUCCESS(status))
					{
						/* Append the file event to the volume name */
						RtlUnicodeStringCat(&szTempPath, &FltObjects->FileObject->FileName);
						RtlUnicodeStringCopy(&filePath, &szTempPath);
						pathNameFound = TRUE;
					}
					ExFreePoolWithTag(szTempPath.Buffer, FILE_POOL_TAG);
				}
			}
		}
		ExFreePoolWithTag(szFileNameDevice.Buffer, FILE_POOL_TAG);
	}

	if(!pathNameFound)
	{
		RtlUnicodeStringCatString(&filePath, L"UNKNOWN"); 
	}

	/* Allocate file event and put the values into it */
	/* NOTE this is freed in the post op callback (which should always get called) */
	pFileEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_EVENT)+filePath.Length+sizeof(WCHAR), FILE_POOL_TAG);
	
	if(pFileEvent == NULL)
	{
		ExFreePoolWithTag(filePath.Buffer, FILE_POOL_TAG);
		return FLT_PREOP_SUCCESS_NO_CALLBACK;
	}

	/* Copy file path into file event */
	pFileEvent->filePathLength = filePath.Length+sizeof(WCHAR);
	RtlStringCbCopyUnicodeString(pFileEvent->filePath, pFileEvent->filePathLength, &filePath);
	/* Free the allocated storage for a filepath */
	ExFreePoolWithTag(filePath.Buffer, FILE_POOL_TAG);

	pFileEvent->majorFileEventType = Data->Iopb->MajorFunction;
	pFileEvent->minorFileEventType = Data->Iopb->MinorFunction;
	pFileEvent->processId = 0;

	if (FltObjects->FileObject != NULL)
	{
		pFileEvent->flags = FltObjects->FileObject->Flags;
	}

	if(Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION)
	{
		if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation)
		{
			PFILE_DISPOSITION_INFORMATION pFileInfo = (PFILE_DISPOSITION_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
			/* If the file is marked for deletion back it up */
			if(pFileInfo->DeleteFile)
			{
				pFileEvent->majorFileEventType = 0x99;
			}
		}
	}

	/* Get the process id of the file event */
	/* NOTE we are kinda using an undocumented function here but its all available
	   on the interweb. Plus its much better than accessing the PETHREAD structure
	   which could change at any time. Also, this one is available to userspace
	   programs so it should be safe to use. We have to use this function because
	   a file I/O may either be processed in the context of the userspace program
	   or the system context. This uses the thread data from FLT_CALLBACK_DATA to
	   determine which process it actually came from. We default back to getting
	   the current process id if all else fails. */
	/* SECOND NOTE FltGetRequestorProcessId does not get the correct process id, it
	   looks like it still get the proces id of the context the pre callback gets
	   called in */
	/*
	status = ObOpenObjectByPointer(Data->Thread, 
		OBJ_KERNEL_HANDLE, 
		NULL, 
		0, 
		0, 
		KernelMode, 
		&hThread);
	if(NT_SUCCESS(status))
	{
		THREAD_BASIC_INFORMATION threadBasicInformation;

		status = ZwQueryInformationThread(hThread, 
			ThreadBasicInformation, 
			&threadBasicInformation, 
			sizeof(THREAD_BASIC_INFORMATION), 
			&returnedLength );
		if(NT_SUCCESS(status))
		{
			pFileEvent->processId = (HANDLE)threadBasicInformation.UniqueProcessId;
			handle5 = pFileEvent->processId;
			//DbgPrint("Process4: %i\n", pFileEvent->processId);
		} else {		
			DbgPrint("ZwQueryInformationThread FAILED: %08x\n", status);
		}
		ZwClose(hThread);
	} else {		
		DbgPrint("ObOpenObjectByPointer FAILED: %08x\n", status);
	}
	*/

	/* New safe get correct process id. One above causes blue screen in some cases */
	if(Data->Thread != NULL)
	{
		PEPROCESS pProcess = IoThreadToProcess( Data->Thread );
		pFileEvent->processId = PsGetProcessId(pProcess);
	} else {
		pFileEvent->processId = PsGetCurrentProcessId();
		DbgPrint("CaptureFileMonitor: Process id may be incorrect\n");
	}
/*
	DbgPrint("%i [%i %i] %s %i %i (%i, %i, %i) %i %i %i %i %i : %ls\n", 
			KeGetCurrentIrql(),
			PsIsSystemThread(Data->Thread),
			PsIsSystemThread(PsGetCurrentThread()),
			FltGetIrpName(Data->Iopb->MajorFunction),
			Data->Iopb->MajorFunction,
			Data->Iopb->MinorFunction,
			pFileEvent->processId,
			PsGetCurrentProcessId(),
			FltGetRequestorProcessId(Data),
			FLT_IS_FASTIO_OPERATION(Data),
			FLT_IS_FS_FILTER_OPERATION(Data),
			FLT_IS_IRP_OPERATION(Data),
			FLT_IS_REISSUED_IO(Data),
			FLT_IS_SYSTEM_BUFFER(Data),
			pFileEvent->filePath);
*/			
	//ASSERT(pFileEvent->processId != 0);

	/* Get the time this event occured */
	KeQuerySystemTime(&CurrentSystemTime);
	ExSystemTimeToLocalTime(&CurrentSystemTime,&CurrentLocalTime);
	RtlTimeToTimeFields(&CurrentLocalTime,&TimeFields);
	pFileEvent->time = TimeFields;



	/* Pass the created file event to the post operation of this pre file operation */
	if (Data->Iopb->MajorFunction == IRP_MJ_SHUTDOWN)
	{
		PostFileOperationCallback( Data,
						FltObjects,
						pFileEvent,
						0 );
		return FLT_PREOP_SUCCESS_NO_CALLBACK;
	} else {
		*CompletionContext = pFileEvent;
		return FLT_PREOP_SUCCESS_WITH_CALLBACK;
	}

    
}
Ejemplo n.º 7
0
PEPROCESS GetProcessObjectbyThreadObject(PETHREAD Thread) { return IoThreadToProcess(Thread); }