⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pathproc.c

📁 臭氧层主动防御系统驱动源代码!臭氧层主动防御系统驱动源代码!
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2004 Security Architects Corporation. All rights reserved.
 *
 * Module Name:
 *
 *		pathproc.c
 *
 * Abstract:
 *
 *		This module implements various pathname handling routines.
 *
 * Author:
 *
 *		Eugene Tsyrklevich 19-Feb-2004
 *
 * Revision History:
 *
 *		None.
 */


#include "pathproc.h"
#include "procname.h"
#include "policy.h"
#include "learn.h"
#include "log.h"


/*
 * ResolveFilename() XXX rewrite
 *
 * Description:
 *		Get canonical name for a file by resolving symbolic links.
 *
 * Parameters:
 *		szFileName - filename to resolve.
 *		szResult - output buffer.
 *		szResultSize - size of an output buffer.
 *
 * Returns:
 *		TRUE to indicate success, FALSE if failed.
 */

BOOLEAN
ResolveFilename(IN PCHAR szFileName, OUT PCHAR szResult, IN USHORT szResultSize)
{
	CHAR				*p, c;
	OBJECT_ATTRIBUTES	oa;
	ANSI_STRING			FileNameAnsi;
	UNICODE_STRING		FileNameUnicode;
	HANDLE				hLink;
	NTSTATUS			rc;
	int					NumberOfLinks = 0;
	WCHAR				buffer[chMAX_PATH];
	CHAR				buffer2[chMAX_PATH];


restart:

	*szResult = '\0';

	if (szFileName[0] == '\\' && szFileName[1] == '\\')
		szFileName++;

	/* move to the end of the object name */
	for (p = szFileName; *p != '\0'; p++)
		;

	/* process the object name from end to the beginning */
	while (p != szFileName)
	{
		/* find the last slash */
		if (*p != '\\' && *p != '\0')
		{
			p--;
			continue;
		}

		c = *p;
		*p = '\0';


		RtlInitAnsiString(&FileNameAnsi, szFileName);
		RtlAnsiStringToUnicodeString(&FileNameUnicode, &FileNameAnsi, TRUE);

		InitializeObjectAttributes(&oa, &FileNameUnicode, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL);

		rc = ZwOpenSymbolicLinkObject(&hLink, GENERIC_READ, &oa);

		if (NT_SUCCESS(rc))
		{
			UNICODE_STRING	target;
			ANSI_STRING		targeta;


			target.Buffer = buffer;
			target.MaximumLength = bMAX_PATH;
			target.Length = 0;

			rc = ZwQuerySymbolicLinkObject(hLink, &target, NULL);

			ZwClose(hLink);


			if (NT_SUCCESS(rc))
			{
				targeta.Length = 0;
				targeta.MaximumLength = szResultSize;
				targeta.Buffer = szResult;

				RtlUnicodeStringToAnsiString(&targeta, &target, FALSE);
				targeta.Buffer[targeta.Length] = '\0';

//XXX				szResultSize -= targeta.Length;

				RtlFreeUnicodeString(&FileNameUnicode);
				*p = c;

//XXX can we have circular links?
				if (NumberOfLinks++ < MAX_NUMBER_OF_LINKS)
				{
					strncat(szResult, p, szResultSize);

//					if (NumberOfLinks > 1)
//						LOG(LOG_SS_PATHPROC, LOG_PRIORITY_DEBUG, ("ResolveFilename: NumberOfLinks=%d. Resolved %s to %s. Restarting.\n", NumberOfLinks, szFileName, szResult));

					/*
					 * switch szFileName to a different buffer. we cannot reuse szFileName buffer
					 * since the resolved link might end up being longer than the original buffer
					 */

					szFileName = (PCHAR) buffer2;
					strcpy(szFileName, szResult);

					goto restart;
				}

				LOG(LOG_SS_PATHPROC, LOG_PRIORITY_DEBUG, ("ResolveFilename: NumberOfLinks=%d. bailing out. %s\n", NumberOfLinks, szResult));

				break;
			}
		}

		RtlFreeUnicodeString(&FileNameUnicode);

		*p-- = c;
	}

	strncat(szResult, p, szResultSize);


//	LOG(LOG_SS_PATHPROC, LOG_PRIORITY_VERBOSE, ("ResolveFilename: name=%s number of links=%d\n", szResult, NumberOfLinks));


	return TRUE;
}



BOOLEAN
ResolveFilenameW(IN PUNICODE_STRING szFileName, OUT PCHAR szResult, IN USHORT szResultSize)
{
	WCHAR				*p, c;
	OBJECT_ATTRIBUTES	oa;
	ANSI_STRING			FileNameAnsi;
	UNICODE_STRING		FileNameUnicode;
	HANDLE				hLink;
	NTSTATUS			rc;
	int					NumberOfLinks = 0;
	WCHAR				buffer[chMAX_PATH];
	USHORT				OriginalLength;
	UNICODE_STRING		target;
	ANSI_STRING			targeta;



	ASSERT(szFileName);
	ASSERT(szResult);

	OriginalLength = szFileName->Length;


restart:

	*szResult = '\0';

	/* move to the end of the object name */
	p = (PWCHAR) ((PCHAR)szFileName->Buffer + szFileName->Length);

	/* process the object name from end to the beginning */
	while (p != szFileName->Buffer)
	{
		/* find the last slash */
//		p = wcsrchr(p, L'\\');
/*
		if (p == NULL)
		{
			p = szFileName->Buffer;
			break;
		}
*/
		if (*p != L'\\' && *p != L'\0')
		{
			p--;
			continue;
		}


		c = *p;
		*p = L'\0';
//		szFileName->Length = OriginalLength - (p - szFileName->Buffer);


//		RtlInitAnsiString(&FileNameAnsi, szFileName);
//		RtlAnsiStringToUnicodeString(&FileNameUnicode, &FileNameAnsi, TRUE);
//		InitializeObjectAttributes(&oa, &FileNameUnicode, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL);

		InitializeObjectAttributes(&oa, szFileName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL);

		rc = ZwOpenSymbolicLinkObject(&hLink, GENERIC_READ, &oa);

		if (! NT_SUCCESS(rc))
		{
			*p-- = c;
			continue;
		}

		target.Buffer = buffer;
		target.MaximumLength = bMAX_PATH;
		target.Length = 0;

		rc = ZwQuerySymbolicLinkObject(hLink, &target, NULL);

		ZwClose(hLink);


		if (! NT_SUCCESS(rc))
		{
			*p-- = c;
			continue;
		}


		*p = c;

		
//XXX can we have circular links?
		if (NumberOfLinks++ < MAX_NUMBER_OF_LINKS)
		{
			wcscat(buffer, p);
			RtlInitUnicodeString(szFileName, buffer);

			goto restart;
		}

		LOG(LOG_SS_PATHPROC, LOG_PRIORITY_DEBUG, ("ResolveFilename: NumberOfLinks=%d. bailing out. %s\n", NumberOfLinks, szResult));

		break;
	}


//	wcscat(szResult, p);


//	LOG(LOG_SS_PATHPROC, LOG_PRIORITY_VERBOSE, ("ResolveFilename: name=%s number of links=%d\n", szResult, NumberOfLinks));


	return TRUE;
}



/*
 * GetPathFromOA()
 *
 * Description:
 *		Resolve an object handle to an object name.
 *
 * Parameters:
 *		ObjectAttributes - opaque structure describing an object handle.
 *		OutBuffer - output buffer where an object name will be saved to.
 *		OutBufferSize - size of an output buffer.
 *		ResolveLinks - do symbolic links need to be resolved?
 *
 * Returns:
 *		TRUE to indicate success, FALSE if failed.
 */

#define	FINISH_GetPathFromOA(msg)										\
	do {																\
		LOG(LOG_SS_PATHPROC, LOG_PRIORITY_DEBUG, msg);					\
		return FALSE;													\
	} while(0)

BOOLEAN
GetPathFromOA(IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PCHAR OutBuffer, IN USHORT OutBufferSize, IN BOOLEAN ResolveLinks)
{
	NTSTATUS					rc;
	PVOID						Object = NULL;
	ULONG						len;
	CHAR						Buffer[sizeof(OBJECT_NAME_INFORMATION) + bMAX_PATH];
	POBJECT_NAME_INFORMATION	pONI = (POBJECT_NAME_INFORMATION) Buffer;
	BOOLEAN						ret = FALSE;
    UNICODE_STRING				ObjectName;

	PUNICODE_STRING				pusFilename = NULL;
	ANSI_STRING					name;


	if (! ARGUMENT_PRESENT(ObjectAttributes) || OutBuffer == NULL)

		return(FALSE);


	try
	{
		if (KeGetPreviousMode() != KernelMode)

			ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));


		if (ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES))

			FINISH_GetPathFromOA(("GetPathFromOA: Invalid ObjectAttributes length %d\n", ObjectAttributes->Length));


		if (! ARGUMENT_PRESENT(ObjectAttributes->ObjectName) )

			return FALSE;


		if (KeGetPreviousMode() != KernelMode)
		{
			ProbeForRead(ObjectAttributes->ObjectName, sizeof(UNICODE_STRING), sizeof(ULONG));

			ObjectName = ProbeAndReadUnicodeString(ObjectAttributes->ObjectName);
		}
		else
		{
			ObjectName = *ObjectAttributes->ObjectName;
		}


		if (ObjectName.Length == 0)

			return FALSE;


		if (((ObjectName.Length & (sizeof(WCHAR) - 1)) != 0) ||
			(ObjectName.Length > bMAX_PATH - sizeof(WCHAR)) )

			FINISH_GetPathFromOA(("GetPathFromOA: invalid wchar string length = %d\n", ObjectName.Length));


		if (KeGetPreviousMode() != KernelMode)

			ProbeForRead(ObjectName.Buffer, ObjectName.Length, sizeof(WCHAR));
	}

	except(EXCEPTION_EXECUTE_HANDLER)
	{
		NTSTATUS status = GetExceptionCode();

		LOG(LOG_SS_PATHPROC, LOG_PRIORITY_DEBUG, ("GetPathFromOA(): caught an exception. status = 0x%x\n", status));

		return FALSE;
	}


	pusFilename = &ObjectName;


	/*
	 * is the filename referenced in relation to some directory?
	 * if so, append the filename to a specified directory name
	 */

	if (ARGUMENT_PRESENT(ObjectAttributes->RootDirectory))
	{
		if (! NT_SUCCESS( ObReferenceObjectByHandle(ObjectAttributes->RootDirectory, 0, 0,
													KernelMode, &Object, NULL) ))
		{
			FINISH_GetPathFromOA(("GetPathFromOA(): ObReferenceObjectByHandle() failed. Object = %x\n", Object));
		}

		if (Object == NULL)
		{
			FINISH_GetPathFromOA(("GetPathFromOA(): Object = NULL\n"));
		}


		if (! NT_SUCCESS( ObQueryNameString(Object, pONI, bMAX_PATH, &len) ))
		{
			ObDereferenceObject(Object);
			FINISH_GetPathFromOA(("GetPathFromOA(): ObQueryNameString() failed\n"));
		}


		ObDereferenceObject(Object);
		Object = NULL;


		/* extracted directory name */
		pusFilename = &pONI->Name;


		/* is the directory name too long? */

		if (pusFilename->Length >= bMAX_PATH - sizeof(WCHAR))
			FINISH_GetPathFromOA(("GetPathFromOA(): directory name is too long\n"));


		/*
		 * pusFilename points to a buffer of MAX_PATH size, ObQueryNameString() sets MaximumLength to the length
		 * of the directory name, we need to reset this back to MAX_PATH to be able to append a filename
		 * (reusing the same buffer)
		 */
		pusFilename->MaximumLength = bMAX_PATH;


		if (pusFilename->Buffer[ (pusFilename->Length / sizeof(WCHAR)) - 1 ] != L'\\')
		{
			pusFilename->Buffer[ pusFilename->Length / sizeof(WCHAR) ] = L'\\';
			pusFilename->Length += sizeof(WCHAR);
		}

		if (RtlAppendUnicodeStringToString(pusFilename, ObjectAttributes->ObjectName) == STATUS_BUFFER_TOO_SMALL)
		{
			LOG(LOG_SS_PATHPROC, LOG_PRIORITY_VERBOSE, ("GetPathFromOA: 1 %S\n", pusFilename->Buffer));
			LOG(LOG_SS_PATHPROC, LOG_PRIORITY_VERBOSE, ("GetPathFromOA: 2 %S\n", ObjectAttributes->ObjectName->Buffer));
			FINISH_GetPathFromOA(("GetPathFromOA(): RtlAppendUnicodeStringToString() = STATUS_BUFFER_TOO_SMALL\n"));
		}
	}


	if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name, pusFilename, TRUE)))
	{	
		if (ResolveLinks == TRUE)
		{
			ret = ResolveFilename(name.Buffer, OutBuffer, OutBufferSize);
		}
		else
		{
			if (name.Length >= OutBufferSize - 1)
			{
				LOG(LOG_SS_PATHPROC, LOG_PRIORITY_DEBUG, ("GetPathFromOA: Pathname too long %d\n", name.Length));

				OutBuffer[0] = 0;

				ret = FALSE;
			}
			else
			{
				strcpy(OutBuffer, name.Buffer);

				ret = TRUE;
			}
		}

		RtlFreeAnsiString(&name);
	}


//	LOG(LOG_SS_PATHPROC, LOG_PRIORITY_VERBOSE, ("%d GetPathFromOA: %s (%S)\n", (ULONG) PsGetCurrentProcessId(), OutBuffer, pusFilename->Buffer));


	return ret;
}




BOOLEAN
GetPathFromOAW(IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PCHAR OutBuffer, IN USHORT OutBufferSize, IN BOOLEAN ResolveLinks)
{
	NTSTATUS					rc;
	PVOID						Object = NULL;
	ULONG						len;
	CHAR						Buffer[sizeof(OBJECT_NAME_INFORMATION) + bMAX_PATH];
	POBJECT_NAME_INFORMATION	pONI = (POBJECT_NAME_INFORMATION) Buffer;
	BOOLEAN						ret = FALSE;
    UNICODE_STRING				ObjectName;

	PUNICODE_STRING				pusFilename = NULL;
	ANSI_STRING					name;


	if (! ARGUMENT_PRESENT(ObjectAttributes) || OutBuffer == NULL)

		return(FALSE);


	try
	{
		if (KeGetPreviousMode() != KernelMode)

			ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));


		if (ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES))

			FINISH_GetPathFromOA(("GetPathFromOA: Invalid ObjectAttributes length %d\n", ObjectAttributes->Length));


		if (! ARGUMENT_PRESENT(ObjectAttributes->ObjectName) )

			return FALSE;


		if (KeGetPreviousMode() != KernelMode)
		{
			ProbeForRead(ObjectAttributes->ObjectName, sizeof(UNICODE_STRING), sizeof(ULONG));

			ObjectName = ProbeAndReadUnicodeString(ObjectAttributes->ObjectName);
		}
		else
		{
			ObjectName = *ObjectAttributes->ObjectName;
		}


		if (ObjectName.Length == 0)

			return FALSE;


		if (((ObjectName.Length & (sizeof(WCHAR) - 1)) != 0) ||
			(ObjectName.Length > bMAX_PATH - sizeof(WCHAR)) )

			FINISH_GetPathFromOA(("GetPathFromOA: invalid wchar string length = %d\n", ObjectName.Length));


		if (KeGetPreviousMode() != KernelMode)

			ProbeForRead(ObjectName.Buffer, ObjectName.Length, sizeof(WCHAR));
	}

	except(EXCEPTION_EXECUTE_HANDLER)
	{
		NTSTATUS status = GetExceptionCode();

		LOG(LOG_SS_PATHPROC, LOG_PRIORITY_DEBUG, ("GetPathFromOA(): caught an exception. status = 0x%x\n", status));

		return FALSE;
	}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -