Esempio n. 1
0
VOID
CreateAllDirectories(PFLT_INSTANCE pInstance, 
				PUNICODE_STRING pRootDirectory, 
				PUNICODE_STRING pDirectory)
{
	UNICODE_STRING totalDirectory;
	UNICODE_STRING path;
	USHORT dirSeperator = 0x005C; // Search for \ as a 16-bit unicode char
	USHORT i = 0;
	USHORT length = pDirectory->Length/2;
	USHORT prevDirPosition = 0;

	//RtlUnicodeStringInit(&path, L"\\??\\I:\\logs\\");

	totalDirectory.Length = 0;
	totalDirectory.MaximumLength = pRootDirectory->MaximumLength + pDirectory->MaximumLength + 2;
	totalDirectory.Buffer = ExAllocatePoolWithTag(NonPagedPool, totalDirectory.MaximumLength, FILE_POOL_TAG);
	
	if(totalDirectory.Buffer == NULL)
	{
		return;
	}
	//RtlAppendUnicodeString(
	//RtlUnicodeStringCatString(&totalDirectory, L"\\??\\I:\\logs\\");
	RtlUnicodeStringCat(&totalDirectory,pRootDirectory);

	for(i = 0; i < length; i++)
	{
		USHORT tempChar = pDirectory->Buffer[i];
		if(dirSeperator == tempChar)
		{
			if(i != 0)
			{
				USHORT size = (i) - (prevDirPosition);
				
				PWSTR dir = ExAllocatePoolWithTag(NonPagedPool, sizeof(WCHAR)*(size+1), FILE_POOL_TAG);

				if(dir == NULL)
				{
					break;
				}

				RtlZeroMemory(dir, sizeof(WCHAR)*(size+1));
				RtlCopyMemory(dir,  pDirectory->Buffer+((prevDirPosition)), size*sizeof(WCHAR));
				dir[size] = '\0';
				RtlUnicodeStringCatString(&totalDirectory, dir);
				//DbgPrint("Creating dir: %wZ\n", &totalDirectory);

				CreateADirectory(pInstance, &totalDirectory);
				
				//RtlUnicodeStringCatString(&totalDirectory, L"\\");

				ExFreePoolWithTag(dir, FILE_POOL_TAG);
				
				prevDirPosition = i;
			}		
		}
	}
	ExFreePoolWithTag(totalDirectory.Buffer, FILE_POOL_TAG);
}
NTSTATUS RegistryCallback(
	_In_      PVOID CallbackContext,
	_In_opt_  PVOID Argument1,
	_In_opt_  PVOID Argument2
)
{
	NTSTATUS			status = STATUS_SUCCESS;
	ULONG				ulCallbackCtx;
	REG_NOTIFY_CLASS	ulType = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
	UNICODE_STRING		usRegistryPath = { 0 };
	BOOLEAN				bSuccess = FALSE;
	LARGE_INTEGER		unCurrentSystemTime;
	LARGE_INTEGER		unCurrentLocalTime;
	PVOID				pData = NULL;
	ULONG				ulDataSize = 0;
	ULONG				ulKeyValueType = REG_NONE;
	WCHAR				wzProcessPath[MAX_STRING_LENGTH] = { 0 };

	// 时间
	KeQuerySystemTime(&unCurrentSystemTime);
	ExSystemTimeToLocalTime(&unCurrentSystemTime, &unCurrentLocalTime);

	ulCallbackCtx = (ULONG)(ULONG_PTR)CallbackContext;

	usRegistryPath.Length = 0;
	usRegistryPath.MaximumLength = 2048 * sizeof(WCHAR);
	usRegistryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, usRegistryPath.MaximumLength, MEM_TAG);
	if (NULL == usRegistryPath.Buffer)
	{
		KdPrint(("[RegistryCallback] Failed to call ExAllocPollWithTag.\r\n"));
		return status;
	}

	switch (ulType)
	{
	case RegNtPreCreateKeyEx:
		{
			PREG_CREATE_KEY_INFORMATION_V1	pCreateInfo = (PREG_CREATE_KEY_INFORMATION_V1)Argument2;
			UNICODE_STRING					usFilter = { 0 };
			BOOLEAN							bEqual = FALSE;
			WCHAR							*wzFilters[] =
			{
				L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\DeviceClasses",
				L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses",
				L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters",
				L"\\REGISTRY\\MACHINE\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
			};

			bSuccess = GetRegistryObjectCompleteName(
				&usRegistryPath,
				pCreateInfo->CompleteName,
				pCreateInfo->RootObject);
			
			if (bSuccess)
			{
				for (size_t nCount = 0; nCount < sizeof(wzFilters) / sizeof(ULONG_PTR); nCount++)
				{
					RtlInitUnicodeString(&usFilter, wzFilters[nCount]);
					if (RtlEqualUnicodeString(&usRegistryPath, &usFilter, TRUE))
					{
						bEqual = TRUE;
					}
				}
				if (!bEqual)
				{
					//WCHAR wzProcessPath[MAX_STRING_LENGTH] = { 0 };
					//GetProcessPathBySectionObject(PsGetCurrentProcessId(), wzProcessPath);
					//KdPrint(("[RegNtPreCreateKeyEx] [%ws] %wZ\r\n", wzProcessPath, &usRegistryPath));
				}
				else
				{
					usRegistryPath.Length = 0;
				}
			}
		}
		break;
	case RegNtPreDeleteKey:
		{
			PREG_DELETE_KEY_INFORMATION pDeleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2;
			bSuccess = GetRegistryObjectCompleteName(
				&usRegistryPath, 
				NULL, 
				pDeleteKey->Object);
			if (bSuccess)
			{
				// KdPrint(("[RegNtPreDeleteKey]: %wZ\r\n", &usRegistryPath));
			}
		}
		break;
	case RegNtPreSetValueKey:
		{
			PREG_SET_VALUE_KEY_INFORMATION	pSetKeyValue = (PREG_SET_VALUE_KEY_INFORMATION)Argument2;
			bSuccess = GetRegistryObjectCompleteName(
				&usRegistryPath,
				NULL,
				pSetKeyValue->Object);
			if (bSuccess && pSetKeyValue->ValueName->Length > 0 && 
				(REG_SZ == pSetKeyValue->Type || REG_DWORD == pSetKeyValue->Type || REG_QWORD == pSetKeyValue->Type))
			{
				RtlUnicodeStringCatString(&usRegistryPath, L"\\");
				RtlUnicodeStringCat(&usRegistryPath, pSetKeyValue->ValueName);

				ulKeyValueType = pSetKeyValue->Type;
				ulDataSize = pSetKeyValue->DataSize;
				pData = pSetKeyValue->Data;
			}
			else
			{
				usRegistryPath.Length = 0;
			}
		}
		break;
	case RegNtPreDeleteValueKey:
		{
			PREG_DELETE_VALUE_KEY_INFORMATION pDeleteValueKey = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2;
			bSuccess = GetRegistryObjectCompleteName(&usRegistryPath, NULL, pDeleteValueKey->Object);
			if (bSuccess && (pDeleteValueKey->ValueName->Length > 0))
			{
				RtlUnicodeStringCatString(&usRegistryPath, L"\\");
				RtlUnicodeStringCat(&usRegistryPath, pDeleteValueKey->ValueName);
			}
		}
		break;
	default:
		break;
	}

	// 创建数据链表
	if (usRegistryPath.Length != 0)
	{
		PEVENT_DATA_NODE	pNode = InitListNode();
		HANDLE				hProcessId = NULL;

		hProcessId = PsGetCurrentProcessId();
		GetProcessPathBySectionObject(hProcessId, wzProcessPath);

		ULONG				ulProcessPathLength = (ULONG)(wcslen(wzProcessPath) * sizeof(WCHAR) + sizeof(WCHAR));					// 进程的长度
		ULONG				ulRegistryPathLength = usRegistryPath.Length + sizeof(WCHAR);											// 注册表路径的长度
		SIZE_T				ulNumberOfBytes = sizeof(REGISTRY_EVENT) + ulProcessPathLength + ulRegistryPathLength + ulDataSize;		// 总长度=进程+注册表+数据
																																	// 进程路径
		pNode->pstRegistryEvent = ExAllocatePoolWithTag(NonPagedPool, ulNumberOfBytes, MEM_TAG);

		// 给各节点数据赋值
		pNode->pstRegistryEvent->hProcessId					= hProcessId;
		pNode->pstRegistryEvent->enRegistryNotifyClass		= ulType;
		pNode->pstRegistryEvent->ulDataLength				= ulDataSize;
		pNode->pstRegistryEvent->ulProcessPathLength		= ulProcessPathLength;
		pNode->pstRegistryEvent->ulRegistryPathLength		= ulRegistryPathLength;
		pNode->pstRegistryEvent->ulKeyValueType				= ulKeyValueType;
		
		RtlTimeToTimeFields(&unCurrentLocalTime, &pNode->pstRegistryEvent->time);											// 时间信息

		RtlCopyBytes(pNode->pstRegistryEvent->uData,						wzProcessPath, ulProcessPathLength);			// 拷贝进程信息
		RtlCopyBytes(pNode->pstRegistryEvent->uData + ulProcessPathLength,	usRegistryPath.Buffer, usRegistryPath.Length);	// 追加注册表路径信息
		pNode->pstRegistryEvent->uData[ulProcessPathLength + usRegistryPath.Length + 0] = '\0';								// 给注册表路径后面添加 \0 结束符
		pNode->pstRegistryEvent->uData[ulProcessPathLength + usRegistryPath.Length + 1] = '\0';
		RtlCopyBytes(pNode->pstRegistryEvent->uData + ulProcessPathLength + ulRegistryPathLength, pData, ulDataSize);		// 追加修改的数据信息(如果不是修改值,这里可能为空)

		ExInterlockedInsertTailList(&g_ListHead, (PLIST_ENTRY)pNode, &g_Lock);
		KeSetEvent(&g_Event, 0, FALSE);

		KdPrint(("hProcessId = %ld", hProcessId));
	}

	if (NULL != usRegistryPath.Buffer)
	{
		ExFreePoolWithTag(usRegistryPath.Buffer, MEM_TAG);
	}

	return status;
}
BOOLEAN GetRegistryObjectCompleteName(
	PUNICODE_STRING pRegistryPath, 
	PUNICODE_STRING pPartialRegistryPath, 
	PVOID pRegistryObject
)
{
	NTSTATUS		status;
	BOOLEAN			bFoundCompleteName = FALSE;
	ULONG			ulReturLength;
	PUNICODE_STRING	pObjectName = NULL;

	if ((!MmIsAddressValid(pRegistryObject)) || (pRegistryObject == NULL))
	{
		return FALSE;
	}

	/* 如果 pPartialRegistryPath 不为 NULL,且符合绝对路径规则,则直接返回给外部使用*/
	if (pPartialRegistryPath != NULL && pPartialRegistryPath->Length >= 4)
	{
		if ((((pPartialRegistryPath->Buffer[0] == '\\') || (pPartialRegistryPath->Buffer[0] == '%')) ||
			((pPartialRegistryPath->Buffer[0] == 'T') && (pPartialRegistryPath->Buffer[1] == 'R') &&
			(pPartialRegistryPath->Buffer[2] == 'Y') && (pPartialRegistryPath->Buffer[3] == '\\'))))
		{
			RtlCopyUnicodeString(pRegistryPath, pPartialRegistryPath);
			bFoundCompleteName = TRUE;
		}
	}

	/* 如果不符合绝对路径规则,则查询 pRegistryObject 对应的注册表对象和 pPartialRegistryPath 拼接 */
	if (!bFoundCompleteName)
	{
		status = ObQueryNameString(pRegistryObject, NULL, 0, &ulReturLength);
		if (status == STATUS_INFO_LENGTH_MISMATCH)
		{
			pObjectName = ExAllocatePoolWithTag(NonPagedPool, ulReturLength, MEM_TAG);
			status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, ulReturLength, &ulReturLength);
			if (NT_SUCCESS(status))
			{
				/* 将查询到的注册表对象拷贝到传出参数中 */
				RtlCopyUnicodeString(pRegistryPath, pObjectName);

				/* 如果 pPartialRegistryPath 不为 NULL,则是新建的项名 */
				/* 如果为 NULL,则是删除项名,不用拷贝到路径后面。*/
				if (NULL != pPartialRegistryPath)
				{
					status = RtlUnicodeStringCatString(pRegistryPath, L"\\");
					if (!NT_SUCCESS(status))
					{
						KdPrint(("Failed to call RtlUnicodeStringCatString, error code = 0x%08X\r\n", status));
					}
					RtlUnicodeStringCat(pRegistryPath, pPartialRegistryPath);
					if (!NT_SUCCESS(status))
					{
						KdPrint(("Failed to call RtlUnicodeStringCat, error code = 0x%08X\r\n", status));
					}
				}
				bFoundCompleteName = TRUE;
			}
			ExFreePoolWithTag(pObjectName, MEM_TAG);
		}
	}

	return bFoundCompleteName;
}
Esempio n. 4
0
NTSTATUS
RegistryCallback(
_In_ PVOID CallbackContext,
_In_opt_ PVOID Argument1,
_In_opt_ PVOID Argument2
)
{

	REG_NOTIFY_CLASS Operation = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
	ULONG_PTR arg2= (ULONG_PTR)Argument2;
	switch (Operation)
	{
	case RegNtPreCreateKeyEx:
	{
								PREG_CREATE_KEY_INFORMATION CallbackData = (PREG_CREATE_KEY_INFORMATION)arg2;
								if (CallbackData->CompleteName->Length == 0 || *CallbackData->CompleteName->Buffer != OBJ_NAME_PATH_SEPARATOR)
								{
									SendRegistryOperationToUserland(REG_PRE_CREATE, CallbackData->CompleteName);
									DbgPrint("RegNtPreCreateKeyEx %wZ", CallbackData->CompleteName);
								}
	}
		break;
	case RegNtPreOpenKeyEx:
		break;
	{
							  PREG_OPEN_KEY_INFORMATION CallbackData = (PREG_OPEN_KEY_INFORMATION)arg2;
							  if (CallbackData->CompleteName->Length == 0 || *CallbackData->CompleteName->Buffer != OBJ_NAME_PATH_SEPARATOR)
							  { 
								  //Get the name of the rootObject where the stuff is done.
								  ULONG allocatedSTRSize = 1024 * sizeof(UNICODE_STRING);
								  PUNICODE_STRING root_name = ExAllocatePoolWithTag(NonPagedPool, 1024 * sizeof(UNICODE_STRING), SPY_TAG);
								  ULONG returnedLength;
								  //CAll obQueryNAmeString.
								  NTSTATUS obQueryStatus = ObQueryNameString(CallbackData->RootObject
									  , (POBJECT_NAME_INFORMATION)root_name
									  , allocatedSTRSize
									  , &returnedLength);

								  if (obQueryStatus == STATUS_SUCCESS)
								  {
									  if (root_name != NULL)
									  {
										  ULONG newSize = CallbackData->CompleteName->Length + root_name->Length + 1/*bonus for the backslash*/;
										  if (newSize < allocatedSTRSize)
										  {
											  //Add the backslash
											  RtlUnicodeStringCat(root_name, "\\");
											  //Add at the end of the stuff the complete name.
											  RtlUnicodeStringCat(root_name, CallbackData->CompleteName);
										  }
										  SendRegistryOperationToUserland(REG_PRE_OPEN, root_name);
										  DbgPrint("RegNtPreOpenKeyEx: %wZ", root_name);
									  }
									  else
										  DbgPrint("RegNtPreOpenKeyEx NAME %wZ || ROOT NOT PRESENT!", CallbackData->CompleteName, root_name);
								  }
								  else
								  {
									  DbgPrint("RegNtPreOpenKeyEx -> Unable to recover the object name.");
								  }
								  //Free the AllocatedPool
								  if (root_name != NULL)
									  ExFreePoolWithTag(root_name, SPY_TAG);
							  }
	}
		break;
	case RegNtDeleteKey:
	{
						   PREG_DELETE_KEY_INFORMATION CallbackData = (PREG_DELETE_KEY_INFORMATION)arg2;
						   //In this case use the ObQueryNameString
						   //TODO -> Determine if Paged should work here.
						   ULONG allocatedSTRSize = 1024 * sizeof(UNICODE_STRING);
						   PUNICODE_STRING object_name = ExAllocatePoolWithTag(NonPagedPool, 1024 * sizeof(UNICODE_STRING), SPY_TAG);
						   ULONG returnedLength;
						   //CAll obQueryNAmeString.
						   NTSTATUS obQueryStatus = ObQueryNameString(CallbackData->Object
							   , (POBJECT_NAME_INFORMATION)object_name
							   , allocatedSTRSize
							   , &returnedLength);

						   if (obQueryStatus == STATUS_SUCCESS)
						   {
							   DbgPrint("RegNtDeleteKey -> %wZ", object_name);
							   SendRegistryOperationToUserland(REG_DELETE_KEY, object_name);
						   }
						   else
						   {
							   DbgPrint("RegNtDeleteKey -> Unable to recover the object name.");
						   }
						   //Free the AllocatedPool
						   if (object_name != NULL)
							   ExFreePoolWithTag(object_name, SPY_TAG);
	}
		break;
	case RegNtDeleteValueKey:
	{
								PREG_DELETE_VALUE_KEY_INFORMATION CallbackData = (PREG_DELETE_VALUE_KEY_INFORMATION)arg2;
								//In this case use the ObQueryNameString
								//TODO -> Determine if Paged should work here.
								ULONG allocatedSTRSize = 1024 * sizeof(UNICODE_STRING);
								PUNICODE_STRING object_name = ExAllocatePoolWithTag(NonPagedPool, 1024 * sizeof(UNICODE_STRING), SPY_TAG);
								ULONG returnedLength;
								//CAll obQueryNAmeString.
								NTSTATUS obQueryStatus = ObQueryNameString(CallbackData->Object
									, (POBJECT_NAME_INFORMATION)object_name
									, allocatedSTRSize
									, &returnedLength);

								if (obQueryStatus == STATUS_SUCCESS)
								{
									DbgPrint("RegNtDeleteValueKey -> %wZ", object_name);
									SendRegistryOperationToUserland(REG_DELETE_VALUE, object_name);
								}
								else
								{
									DbgPrint("RegNtDeleteValueKey -> Unable to recover the object name.");
								}
								//Free the AllocatedPool
								if (object_name != NULL)
									ExFreePoolWithTag(object_name, SPY_TAG);

	}
		break;
	case RegNtSetValueKey:
	{

							 PREG_SET_VALUE_KEY_INFORMATION CallbackData = (PREG_SET_VALUE_KEY_INFORMATION)arg2;
							 //In this case use the ObQueryNameString
							 //TODO -> Determine if Paged should work here.
							 ULONG allocatedSTRSize = 1024 * sizeof(UNICODE_STRING);
							 PUNICODE_STRING root_name = ExAllocatePoolWithTag(NonPagedPool, 1024 * sizeof(UNICODE_STRING), SPY_TAG);
							 ULONG returnedLength;
							 //CAll obQueryNAmeString.
							 NTSTATUS obQueryStatus = ObQueryNameString(CallbackData->Object
								 , (POBJECT_NAME_INFORMATION)root_name
								 , allocatedSTRSize
								 , &returnedLength);

							 if (obQueryStatus == STATUS_SUCCESS)
							 {								 
								 ULONG newSize = CallbackData->ValueName->Length + root_name->Length + 1;
								 if (newSize < allocatedSTRSize)
								 {
									 RtlUnicodeStringCat(root_name, "\\");
									 RtlUnicodeStringCat(root_name, CallbackData->ValueName);
									 //Use CallbackData->Data and DataSize to detect wich is the new data to modify
									 SendRegistryOperationToUserland(REG_SET_VALUE, root_name);
									 DbgPrint("RegNtSetValueKey -> %wZ", root_name);
								 }
							 }
							 else
							 {
								 DbgPrint("RegNtSetValueKey -> Unable to recover the object name.");
							 }
							 //Free the AllocatedPool
							 if (root_name != NULL)
								 ExFreePoolWithTag(root_name, SPY_TAG);


	}
		break;
	}
	return STATUS_SUCCESS;
}
Esempio n. 5
0
NTSTATUS RegistryCallback(IN PVOID CallbackContext, 
IN PVOID Argument1, 
IN PVOID Argument2)
{  
	NTSTATUS st=STATUS_SUCCESS;
    BOOLEAN exception = FALSE;  
	BOOLEAN flag;
    int type;
    UNICODE_STRING registryPath;
    UCHAR* registryData = NULL;
    ULONG registryDataLength = 0;
    ULONG registryDataType = 0;
    /* Allocate a large 64kb string ... maximum path name allowed in windows */
    registryPath.Length = 0;
    registryPath.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR);
    registryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, registryPath.MaximumLength, REGISTRY_POOL_TAG); 
    if(registryPath.Buffer == NULL)
	{
     return STATUS_SUCCESS;
	}

    //registryEvent.eventType = (REG_NOTIFY_CLASS)Argument1;
    type = (REG_NOTIFY_CLASS)Argument1;
    try
	{
       /* Large switch statement for all registry events ... fairly easy to understand */
       switch(type)
	   {
		  case RegNtPreDeleteKey:
		{
			PREG_DELETE_KEY_INFORMATION deleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2;
			PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)deleteKey->Object;
		   GetProcessName(aProcessName);
			flag=GetRegistryObjectCompleteName(&registryPath, NULL, deleteKey->Object);
			if(flag) 
			{
				RtlUnicodeStringToAnsiString(&astr,&registryPath,TRUE);
				DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer);
				st=WaitForUserAnswer();
				if (!NT_SUCCESS(st))
					return STATUS_INVALID_PARAMETER;
				RtlFreeAnsiString(&astr);
			}
		    break;		 
		}
		  case RegNtPreDeleteValueKey:
		{
			
			PREG_DELETE_VALUE_KEY_INFORMATION deleteValueKey = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2;
			PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)deleteValueKey->Object;
			GetProcessName(aProcessName);
			flag=GetRegistryObjectCompleteName(&registryPath, NULL, deleteValueKey->Object);
			if((flag) && (deleteValueKey->ValueName->Length > 0)) 
			{
				RtlUnicodeStringCatString(&registryPath,L"\\");
				RtlUnicodeStringCat(&registryPath, deleteValueKey->ValueName);
				RtlUnicodeStringToAnsiString(&astr,&registryPath,TRUE);
				DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer);
				st=WaitForUserAnswer();
				if (!NT_SUCCESS(st))
				       return STATUS_INVALID_PARAMETER;
				RtlFreeAnsiString(&astr);
			}
				  break;
		}
		  case RegNtPreSetValueKey:
		{
			PREG_SET_VALUE_KEY_INFORMATION setValueKey = (PREG_SET_VALUE_KEY_INFORMATION)Argument2;
			PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)setValueKey->Object;
		    GetProcessName(aProcessName);
			flag = GetRegistryObjectCompleteName(&registryPath, NULL, setValueKey->Object);
			if((flag) && (setValueKey->ValueName->Length > 0)) 
			{
				registryDataType = setValueKey->Type;
				registryDataLength = setValueKey->DataSize;
				registryData = ExAllocatePoolWithTag(NonPagedPool, registryDataLength, REGISTRY_POOL_TAG);
				if(registryData != NULL)
				{
					RtlCopyBytes(registryData,setValueKey->Data,setValueKey->DataSize);
				} else {
					DbgPrint("RegistryMonitor: ERROR can't allocate memory for setvalue data\n");
				}
				RtlUnicodeStringCatString(&registryPath,L"\\");
				RtlUnicodeStringCat(&registryPath, setValueKey->ValueName);
				RtlUnicodeStringToAnsiString(&astr,&registryPath,TRUE);
				DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer);
				  if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"))
				  {
					   st=WaitForUserAnswer();
				       if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServices"))
				  {
                      st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				           return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer," \\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer," \\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
                  else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				   RtlFreeAnsiString(&astr);
			}
				  break;		 
		}
	    
		  default:
			  break;
	   }
	   } except( EXCEPTION_EXECUTE_HANDLER ) {
		   /* Do nothing if an exception occured ... event won't be queued */
		   exception = TRUE;
	   }
	  
	   if(registryPath.Buffer != NULL)
	   {
		   ExFreePoolWithTag(registryPath.Buffer, REGISTRY_POOL_TAG);
	   }
       /* Always return a success ... we aren't doing any filtering, just monitoring */
       return STATUS_SUCCESS;
}
Esempio 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;
	}

    
}
Esempio n. 7
0
VOID
CopyFileIfBeingDeleted(
						PFLT_CALLBACK_DATA Data,
						__in PCFLT_RELATED_OBJECTS FltObjects,
						PFLT_FILE_NAME_INFORMATION pFileNameInformation
						)
{
	NTSTATUS status;
	BOOLEAN isDirectory;
	FltIsDirectory(Data->Iopb->TargetFileObject,FltObjects->Instance,&isDirectory);
	if(isDirectory)
	{
		return;
	}
	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 && FltIsOperationSynchronous(Data))
			{
				//pFileEvent->majorFileEventType = 0x99;
				status = FltParseFileNameInformation(pFileNameInformation);
				
				if(NT_SUCCESS(status))
				{
					if(fileManager.bCollectDeletedFiles)
					{
						UNICODE_STRING completeFilePath;
						//UNICODE_STRING logDirectory;
						UNICODE_STRING fileDirectory;
						UNICODE_STRING fileDosDrive;

						//DbgPrint("On Delete: IoStatus - %08x\n", Data->IoStatus.Status);
						//DbgPrint("On Delete: FinalStatus - %08x\n", Data->Iopb->TargetFileObject->FinalStatus);

						
						//RtlUnicodeStringInit(&logDirectory, L"\\??\\I:\\logs\\deleted_files");

						/* Get the Dos drive name this file event was initiated on */
						GetDosDeviceName(Data->Iopb->TargetFileObject->DeviceObject, &pFileNameInformation->Share, &fileDosDrive);
						
						//DbgPrint("DosDrive: %wZ\n", &fileDosDrive);

						/* Allocate enough room to hold to whole path to the copied file */
						/* <CAPTURE LOG DIRECTORY>\<DOS DRIVE>\<FILE DIRECTORY>\<FILE NAME> */
						completeFilePath.Length = 0;
						completeFilePath.MaximumLength = fileManager.logDirectory.MaximumLength + fileDosDrive.MaximumLength + pFileNameInformation->FinalComponent.MaximumLength + 
							pFileNameInformation->ParentDir.MaximumLength + 2;
						completeFilePath.Buffer = ExAllocatePoolWithTag(NonPagedPool, completeFilePath.MaximumLength, FILE_POOL_TAG);

						if(completeFilePath.Buffer != NULL)
						{
							/* Construct complete file path of where the copy of the deleted file is to be put */
							RtlUnicodeStringCat(&completeFilePath, &fileManager.logDirectory);
							RtlUnicodeStringCat(&completeFilePath, &fileDosDrive);
							RtlUnicodeStringCat(&completeFilePath, &pFileNameInformation->ParentDir);
							RtlUnicodeStringCat(&completeFilePath, &pFileNameInformation->FinalComponent);
						}

						//DbgPrint("ParentDir: %wZ\n", &pFileNameInformation->ParentDir);
						//DbgPrint("FinalComponent: %wZ\n", &pFileNameInformation->FinalComponent);
						//DbgPrint("CompleteFilePath: %wZ\n", &completeFilePath);

						/* Allocate space for the file directory */
						fileDirectory.Length = 0;
						fileDirectory.MaximumLength = pFileNameInformation->ParentDir.MaximumLength + fileDosDrive.MaximumLength + 2;
						fileDirectory.Buffer = ExAllocatePoolWithTag(NonPagedPool, fileDirectory.MaximumLength, FILE_POOL_TAG);					
						
						if(fileDirectory.Buffer != NULL)
						{
							/* Append the dos drive name, and then the directory */
							RtlUnicodeStringCat(&fileDirectory, &fileDosDrive);
							RtlUnicodeStringCat(&fileDirectory, &pFileNameInformation->ParentDir);
						
							//DbgPrint("FileDirectory: %wZ\n", &fileDirectory);
						}

						/* Create all the directories in the fileDirectory string */
						CreateAllDirectories(FltObjects->Instance, &fileManager.logDirectory, &fileDirectory);
						
						/* Path should exist now so copy the file */
						CopyFile(Data, FltObjects, &completeFilePath);
						
						/* Free all the UNICODE_STRING we allocated space for */
						if(completeFilePath.Buffer != NULL)
							ExFreePoolWithTag(completeFilePath.Buffer, FILE_POOL_TAG);
						if(fileDirectory.Buffer != NULL)
							ExFreePoolWithTag(fileDirectory.Buffer, FILE_POOL_TAG);
						if(fileDosDrive.Buffer != NULL)
							ExFreePoolWithTag(fileDosDrive.Buffer, FILE_POOL_TAG);
					}
				} else {
					DbgPrint("CaptureFileMonitor: ERROR - FltParseFileNameInformation - %08x\n", status);
				}
			}	
		}
	}
}
Esempio n. 8
0
NTSTATUS
NdasPortFdoGetExtendedInterface(
	CONST GUID* ExternalTypeGuid,
	PFILE_OBJECT* ExternalFileObject,
	PDEVICE_OBJECT* ExternalDeviceObject,
	PNDAS_LU_QUERY_NDAS_LOGICALUNIT_INTERFACE* LogicalUnitInterface)
{
	NTSTATUS status;
	UNICODE_STRING externalDeviceTypeGuidString;
	WCHAR externalDeviceNameBuffer[64];
	UNICODE_STRING externalDeviceName;
	PIRP irp;
	KEVENT event;
	IO_STATUS_BLOCK ioStatus;
	NDASPORT_EXTERNAL_TYPE_GET_INTERFACE externalTypeGetInterface;

	PAGED_CODE();

	*ExternalFileObject = NULL;
	*ExternalDeviceObject = NULL;

	RtlInitEmptyUnicodeString(
		&externalDeviceName,
		externalDeviceNameBuffer,
		sizeof(externalDeviceNameBuffer));

	status = RtlStringFromGUID(
		ExternalTypeGuid,
		&externalDeviceTypeGuidString);

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

	status = RtlUnicodeStringCopyString(
		&externalDeviceName,
		L"\\Device\\NdasPort_");

	ASSERT(NT_SUCCESS(status));
	if (!NT_SUCCESS(status))
	{
		return status;
	}

	status = RtlUnicodeStringCat(
		&externalDeviceName,
		&externalDeviceTypeGuidString);

	RtlFreeUnicodeString(&externalDeviceTypeGuidString);

	ASSERT(NT_SUCCESS(status));
	if (!NT_SUCCESS(status))
	{
		return status;
	}

	status = IoGetDeviceObjectPointer(
		&externalDeviceName,
		FILE_ALL_ACCESS,
		ExternalFileObject,
		ExternalDeviceObject);

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

	KeInitializeEvent(&event, NotificationEvent, FALSE);

	externalTypeGetInterface.Size = sizeof(NDASPORT_EXTERNAL_TYPE_GET_INTERFACE);
	externalTypeGetInterface.Version = NDASPORT_EXTERNAL_TYPE_GET_INTERFACE_VERSION;
	externalTypeGetInterface.ExternalTypeGuid = *ExternalTypeGuid;
	externalTypeGetInterface.GetInterfaceFunction = NULL;
	
	irp = IoBuildDeviceIoControlRequest(
		NDASPORTEXT_IOCTL_GET_LOGICALUNIT_INTERFACE,
		*ExternalDeviceObject,
		&externalTypeGetInterface, sizeof(NDASPORT_EXTERNAL_TYPE_GET_INTERFACE),
		&externalTypeGetInterface, sizeof(NDASPORT_EXTERNAL_TYPE_GET_INTERFACE),
		TRUE,
		&event,
		&ioStatus);

	if (NULL == irp)
	{
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto error1;
	}

	status = IoCallDriver(*ExternalDeviceObject, irp);

	if (!NT_SUCCESS(status))
	{
		goto error2;
	}

	KeWaitForSingleObject(
		&event, 
		Executive, 
		KernelMode, 
		FALSE, 
		NULL);

	status = ioStatus.Status;

	if (!NT_SUCCESS(status))
	{
		goto error3;
	}
	
	*LogicalUnitInterface = externalTypeGetInterface.GetInterfaceFunction;

	return status;

error3:
error2:
error1:

	ObDereferenceObject(*ExternalFileObject);
	*ExternalDeviceObject = NULL;
	*ExternalFileObject = NULL;

	return status;
}