Пример #1
1
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Description :
//		Generates a message using "pid", "message" and "parameter" and sends it back to userland throught
//		a filter communication port.
//	Parameters :
//		_in_opt_ ULONG pid :		Process ID from which the logs are produced.
//		_in_opt_ PWCHAR message :	Message (function name most of the time).
//		_in_opt_ PWCHAR parameter :	Function args.
//	Return value :
//		NTSTATUS : FltSendMessage return value.
//	Process :
//		- Retrieves the process name from the pid and saves the whole data into an ANSI string.
//		- Generates an ANSI string with the message, with the process name, pid, and function name, and the
//		- generic "parameter" parameter. The resulting output will basically follow this scheme:
//			"pid","proces_name","function_name","FAILED/SUCCESS(0/1)","return_value","number_of_arguments","argument1->value","argument2->value"...
//		- Uses the "mutex" mutex to avoid concurrency when using the FltSendMessage() function.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS sendLogs(ULONG pid, PWCHAR message, PWCHAR parameter)
{
	NTSTATUS status = STATUS_SUCCESS;
	CHAR buf[MAXSIZE];
	UNICODE_STRING processName;
	ULONG sizeBuf;
	
	LARGE_INTEGER timeout;
	timeout.QuadPart = -((LONGLONG)0.5*10*1000*1000);
	
	if(message == NULL)
		return STATUS_INVALID_PARAMETER;

    #ifdef DEBUG
    DbgPrint("SendLogs\n");
    #endif

	processName.Length = 0;
	processName.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR);
	processName.Buffer = ExAllocatePoolWithTag(NonPagedPool, processName.MaximumLength, PROCNAME_TAG);
	if(!processName.Buffer)
	{
		KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
		status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, &timeout);
		KeReleaseMutex(&mutex, FALSE);
		return STATUS_NO_MEMORY;
	}
	
	status = getProcNameByPID(pid, &processName);
	if(!NT_SUCCESS(status))
	{
		KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
		status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, &timeout);
		KeReleaseMutex(&mutex, FALSE);
		ExFreePool(processName.Buffer);
		return status;
	}
	
	status = RtlStringCbPrintfA(buf, MAXSIZE, "%d,%wZ,%ws,%ws\n", pid, &processName, message, parameter);
	if(!NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW)
	{
		KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
		status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, &timeout);
		KeReleaseMutex(&mutex, FALSE);
		ExFreePool(processName.Buffer);
		return status;
	}
	
	status = RtlStringCbLengthA(buf, MAXSIZE, &sizeBuf);
	if(!NT_SUCCESS(status))
	{
		KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
		status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, &timeout);
		KeReleaseMutex(&mutex, FALSE);
		ExFreePool(processName.Buffer);
		return status;
	}
	

	KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
	#ifdef DEBUG
	DbgPrint("\tmsg : %s\n", buf);
	#endif
    
    status = FltSendMessage(filter, &clientPort, buf, sizeBuf, NULL, 0, NULL);
	if(status == STATUS_TIMEOUT)
		DbgPrint("STATUS_TIMEOUT !!\n");
	KeReleaseMutex(&mutex, FALSE);
	ExFreePool(processName.Buffer);
	
	#ifdef DEBUG
	if(!NT_SUCCESS(status))
		DbgPrint("return : 0x%08x\n", status);
	#endif DEBUG	
	
	return status;
}
Пример #2
0
FLT_POSTOP_CALLBACK_STATUS
claimsmanPostOperation(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_opt_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
/*++

Routine Description:

This routine is the post-operation completion routine for this
miniFilter.

This is non-pageable because it may be called at DPC level.

Arguments:

Data - Pointer to the filter callbackData that is passed to us.

FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
opaque handles to this filter, instance, its associated volume and
file object.

CompletionContext - The completion context set in the pre-operation routine.

Flags - Denotes whether the completion is successful or is being drained.

Return Value:

The return value is the status of the operation.

--*/
{
	UNREFERENCED_PARAMETER(Data);
	UNREFERENCED_PARAMETER(CompletionContext);
	UNREFERENCED_PARAMETER(Flags);
	NTSTATUS status;
	PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
	PUNICODE_STRING fileName = NULL;
	PTOKEN_USER pTokenUser = NULL;
	UNICODE_STRING sidString;
	
	LARGE_INTEGER Timeout;
	Timeout.QuadPart = (LONGLONG)1 * 10 * 1000 * 1000;
	
	// If there is no client registered, bail out immediately!
	// If the event is from kernel, bail out immediately!
	// If the event check for existence of file, bail out immediately!
	if (
		(ClaimsmanData.ClientPort == NULL) || 
		(Data->RequestorMode == KernelMode) ||
		(Data->IoStatus.Information == FILE_DOES_NOT_EXIST) ||
		(Data->IoStatus.Information == FILE_EXISTS)
		) {
		return FLT_POSTOP_FINISHED_PROCESSING;
	}

	//  We got a log record, if there is a file object, get its name.

	if (FltObjects->FileObject != NULL) {
		status = FltGetFileNameInformation(Data,
			FLT_FILE_NAME_NORMALIZED |
			FLT_FILE_NAME_QUERY_DEFAULT,
			&nameInfo);
	}
	else {
		//  Can't get a name when there's no file object
		status = STATUS_UNSUCCESSFUL;
	}

	if (NT_SUCCESS(status)) {
		FltParseFileNameInformation(nameInfo);
		fileName = &nameInfo->Name;
		// Produces way too much logging
		//PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
		//	("claimsman!claimsmanPostOperation: fileName=%wZ\n", fileName));
	}
	else
	{
		// No point continuing because we obviously did not get a filename anyways
		return FLT_POSTOP_FINISHED_PROCESSING;
	}

	//The only IRP you can trust for user information is IRP_MJ_CREATE. Things 
	//like write can be in arbitrary thread context, and even if the call works
	//you can get the wrong SID.

	status = SeQueryInformationToken(SeQuerySubjectContextToken(&(Data->Iopb->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext)), TokenUser, &pTokenUser);
	if (STATUS_SUCCESS == status && RtlValidSid(pTokenUser->User.Sid))
	{
		// Interesting extension?
		if (ClaimsmanCheckExtension(&nameInfo->Extension)) {
			CLAIMSMAN_MESSAGE msg;

			status = RtlConvertSidToUnicodeString(&sidString, pTokenUser->User.Sid, TRUE);

			if (NT_SUCCESS(status)) {
				PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
					("claimsman!claimsmanPostOperation: SID=%wZ\n", &sidString));
			}
			else {
				// No point continuing because we obviously did not get a valid SID
				FltReleaseFileNameInformation(nameInfo);
				ExFreePool(pTokenUser);
				return FLT_POSTOP_FINISHED_PROCESSING;
			}

			if (ClaimsmanCheckUserIgnore(&sidString)) {
				// Ignored user! Bail out!
				FltReleaseFileNameInformation(nameInfo);
				ExFreePool(pTokenUser);
				RtlFreeUnicodeString(&sidString);
				return FLT_POSTOP_FINISHED_PROCESSING;
			}

			LONGLONG size;
			LONGLONG modified;
			getSizeModified(FltObjects->Instance, fileName, &size, &modified);

			InitializeMessage(&msg, &sidString, fileName, FltObjects->FileObject->ReadAccess, FltObjects->FileObject->WriteAccess, FltObjects->FileObject->DeleteAccess, size, modified, Data->IoStatus.Status);

			// Ready, send the message!
			// But only if there's a client connected
			if (ClaimsmanData.ClientPort != NULL) {

				FltSendMessage(ClaimsmanData.Filter,
					&ClaimsmanData.ClientPort,
					&msg,
					sizeof(msg),
					NULL,
					0,
					&Timeout
					);
				PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
					("claimsman!claimsmanPostOperation: sent message=%d\n", status));
			}
			else {
				PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
					("claimsman!claimsmanPostOperation: no client connected!"));
			}
			RtlFreeUnicodeString(&sidString);
		}
	}

	FltReleaseFileNameInformation(nameInfo);
	if (pTokenUser != NULL) {
		ExFreePool(pTokenUser);
	}
	return FLT_POSTOP_FINISHED_PROCESSING;
}
Пример #3
0
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Description :
//		Generates a message using "pid", "message" and "parameter" and sends it back to userland throught
//		a filter communication port.
//	Parameters :
//		_in_opt_ ULONG pid :		Process ID from which the logs are produced.
//		_in_opt_ PWCHAR message :	Message (function name most of the time).
//		_in_opt_ PWCHAR parameter :	Function args.
//	Return value :
//		NTSTATUS : FltSendMessage return value.
//	Process :
//		- Retrieves the process name from the pid and saves the whole data into an ANSI string.
//		- Generates an ANSI string with the message, with the process name, pid, and function name, and the
//		- generic "parameter" parameter. The resulting output will basically follow this scheme:
//			"pid","process_name","function_name","FAILED/SUCCESS/BLOCKED(0/1/2)","return_value","number_of_arguments","argument1->value","argument2->value"...
//		- Uses the "mutex" mutex to avoid concurrency when using the FltSendMessage() function.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS sendLogs(ULONG pid, PWCHAR message, PWCHAR parameter)
{
	NTSTATUS status = STATUS_SUCCESS;
	CHAR buf[MAXSIZE];
	UNICODE_STRING processName;
	ULONG sizeBuf;
	
	if(message == NULL)
		return STATUS_INVALID_PARAMETER;
	
	processName.Length = 0;
	processName.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR);
	processName.Buffer = ExAllocatePoolWithTag(NonPagedPool, processName.MaximumLength, PROCNAME_TAG);
	if(!processName.Buffer)
	{
		DbgPrint("ProcessName.Buffer error\n");
		KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
		status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, NULL);
		KeReleaseMutex(&mutex, FALSE);
		return STATUS_NO_MEMORY;
	}

	status = getProcNameByPID(pid, &processName);
	if(!NT_SUCCESS(status))
	{
		DbgPrint("getProcNameByPID() error\n");
		KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
		status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, NULL);
		KeReleaseMutex(&mutex, FALSE);
		ExFreePool(processName.Buffer);
		return status;
	}
	
	status = RtlStringCbPrintfA(buf, MAXSIZE, "%d,%wZ,%ws,%ws\n", pid, &processName, message, parameter);
	if(!NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW)
	{
		DbgPrint("RtlStringCbPrintfA() error\n");
		KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
		status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, NULL);
		KeReleaseMutex(&mutex, FALSE);
		ExFreePool(processName.Buffer);
		return status;
	}
	
	status = RtlStringCbLengthA(buf, MAXSIZE, &sizeBuf);
	if(!NT_SUCCESS(status))
	{
		DbgPrint("RtlStringCbLengthA() error\n");
		KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
		status = FltSendMessage(filter, &clientPort, "0,error,error,error\n", 20, NULL, 0, NULL);
		KeReleaseMutex(&mutex, FALSE);
		ExFreePool(processName.Buffer);
		return status;
	}
	

	KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
	status = FltSendMessage(filter, &clientPort, buf, sizeBuf, NULL, 0, NULL);
	KeReleaseMutex(&mutex, FALSE);
	ExFreePool(processName.Buffer);

	return status;
}
Пример #4
0
NTSTATUS SendScanOrder( _In_ PFLT_FILTER FilterHandle, PUNICODE_STRING FilePath ,  _Out_ SCAN_RESULT * AnswerMessage) {

	NTSTATUS ntStatus = STATUS_SUCCESS;
	SCAN_RESULT replyMessage = NONE;
	PMESSAGE_CONTEXT scanMessage = NULL;
	LARGE_INTEGER liTimeOut;
	LARGE_INTEGER timeOut = {0};
	ANSI_STRING AnsiString;
	ULONG replyLength =0;
	LONGLONG _1ms = 10000;
	LONGLONG localScanTimeout = 1000;



	RtlZeroMemory(&AnsiString, sizeof(ANSI_STRING));
	
	// Check parameters.
	if (FilterHandle == NULL) {
		DbgPrint("[-] Error :: ArmaditoGuard!SendScanOrder :: Invalid filter handle parameter !! \n");
		return STATUS_INVALID_PARAMETER;
	}

	if (gClientComPort == NULL) {
		DbgPrint("[-] Error :: ArmaditoGuard!SendScanOrder :: Scan service not connected yet !! \n");
		return STATUS_INVALID_PARAMETER;
	}

	if (FilePath == NULL) {
		DbgPrint("[-] Error :: ArmaditoGuard!SendScanOrder :: Invalid FilePath parameter !! \n");
		return STATUS_INVALID_PARAMETER;
	}

	if (AnswerMessage == NULL) {
		DbgPrint("[-] Error :: ArmaditoGuard!SendScanOrder :: Invalid AnswerMessage parameter !! \n");
		return STATUS_INVALID_PARAMETER;
	}


	__try {

		// Allocate memory and initialize the scan struct.
		scanMessage = (PMESSAGE_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, sizeof(MESSAGE_CONTEXT), MESSAGE_CONTEXT_BUF);
		if (scanMessage == NULL) {
			ntStatus = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}
		RtlZeroMemory(scanMessage, sizeof(MESSAGE_CONTEXT));

		// Convert unicode string to ansi string for ring 3 process.		
		ntStatus = RtlUnicodeStringToAnsiString(&AnsiString, (PCUNICODE_STRING)FilePath, TRUE);
		if(!NT_SUCCESS(ntStatus)){
			DbgPrint("[-] Error :: ArmaditoGuard!SendScanOrder :: RtlUnicodeStringToAnsiString() routine failed !! \n");
			__leave;
		}

		// Fill the SCAN_MESSAGE_CONTEXT struct.
		RtlCopyMemory(&(scanMessage->FileName), AnsiString.Buffer, AnsiString.Length);
		scanMessage->FileNameLength = AnsiString.Length;
		scanMessage->scan_result = NONE;


		// Set timeout (1second).
		liTimeOut.QuadPart = -100000000LL;
		//liTimeOut.QuadPart = -50000000LL; // 0.1 sec
		//timeOut = &liTimeOut;
		timeOut.QuadPart = -(localScanTimeout * _1ms);


		//replyLength = sizeof(FILTER_REPLY_HEADER) + sizeof(SCAN_RESULT);
		replyLength = sizeof(SCAN_RESULT);
		// Send message to the scan process throught the communication port.
		ntStatus = FltSendMessage(FilterHandle, &gClientComPort, (PVOID)scanMessage, sizeof(MESSAGE_CONTEXT), (PVOID)&replyMessage, &replyLength, &timeOut);
		if (!NT_SUCCESS(ntStatus)) {
			DbgPrint("[-] Error :: ArmaditoGuard!SendScanOrder :: FltSendMessage() routine failed !! \n");
			__leave;
		}


		if(ntStatus == STATUS_TIMEOUT){
			//DbgPrint("[-] Warning :: ArmaditoGuard!SendScanOrder :: FltSendMessage() returned with timeout status !! \n");
			*AnswerMessage = TIMEOUT;
		}
		else {
			*AnswerMessage = replyMessage;
			//DbgPrint("[+] Debug :: ArmaditoGuard!SendScanOrder :: FltSendMessage() executed successfully !! :: Scan Result = [TODO] \n");
			if (replyMessage != NONE) {
				;//DbgPrint("[+] DEBUG :: ArmaditoGuard!SendScanOrder :: Reply message received successfully from the scan service :: Scan Result = [DBG_FLAG] \n");
			}
			else {
				DbgPrint("[+] Warning :: ArmaditoGuard!SendScanOrder :: Reply message not received completly...\n");
			}
		}
		
	}
	__finally {
		
		//
		//	Whatever happens, this buffer is not required anymore after this routine.
		//
		if(scanMessage != NULL){
			ExFreePoolWithTag(scanMessage, MESSAGE_CONTEXT_BUF);
			scanMessage = NULL;
		}

		//
		//	Free ansi string if this one has been allocated.
		//
		if(AnsiString.Buffer != NULL){
			RtlFreeAnsiString(&AnsiString);
		}


	}
	


	
	return ntStatus;

}