From 2acec63b2ed75bf4b71ad257db573c4b8f9639e7 Mon Sep 17 00:00:00 2001 From: tumagonx Date: Tue, 8 Aug 2017 10:54:53 +0700 Subject: initial commit --- file.c | 665 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 665 insertions(+) create mode 100644 file.c (limited to 'file.c') diff --git a/file.c b/file.c new file mode 100644 index 0000000..b82ed5c --- /dev/null +++ b/file.c @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2004 Security Architects Corporation. All rights reserved. + * + * Module Name: + * + * file.c + * + * Abstract: + * + * This module implements various file hooking routines. + * + * Author: + * + * Eugene Tsyrklevich 19-Feb-2004 + * + * Revision History: + * + * None. + */ + + +#include +#include "file.h" +#include "policy.h" +#include "pathproc.h" +#include "hookproc.h" +#include "accessmask.h" +#include "learn.h" + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text (INIT, InitFileHooks) +#endif + + +fpZwCreateFile OriginalNtCreateFile = NULL; +fpZwOpenFile OriginalNtOpenFile = NULL; +fpZwDeleteFile OriginalNtDeleteFile = NULL; +fpZwQueryAttributesFile OriginalNtQueryAttributesFile = NULL; +fpZwQueryFullAttributesFile OriginalNtQueryFullAttributesFile = NULL; +fpZwQueryDirectoryFile OriginalNtQueryDirectoryFile = NULL; +fpZwSetInformationFile OriginalNtSetInformationFile = NULL; + +fpZwCreateMailslotFile OriginalNtCreateMailslotFile = NULL; +fpZwCreateNamedPipeFile OriginalNtCreateNamedPipeFile = NULL; + + + +// XXX make sure that this still works with POSIX subsystem (inside windows 2000 describes how to start posix subsystem) + +// XXX make sure streams don't screw anything up... do a search on a directory, observe NtCreateFile output.. + + +/* + * HookedNtCreateFile() + * + * Description: + * This function mediates the NtCreateFile() system service and checks the + * provided file name against the global and current process security policies. + * + * NOTE: ZwCreateFile() creates or opens a file. [NAR] + * + * Parameters: + * Those of NtCreateFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtCreateFile(). + */ + +NTSTATUS +NTAPI +HookedNtCreateFile +( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength +) +{ + PCHAR FunctionName = "HookedNtCreateFile"; + CHAR BufferLongName[MAX_PATH], BufferShortName[MAX_PATH]; + PCHAR FILENAME = BufferLongName;//BufferShortName; + PCHAR DIRECTORYNAME = BufferLongName;//BufferShortName; + BOOLEAN CreateDirectoryRequest = FALSE; + + + HOOK_ROUTINE_ENTER(); + + + /* special handling for directories, look at flags to figure out whether we are dealing w/a directory */ + if ((CreateOptions & FILE_DIRECTORY_FILE) && (CreateDisposition & FILE_CREATE)) + CreateDirectoryRequest = TRUE; + + + if (LearningMode == FALSE) + { + GetPathFromOA(ObjectAttributes, BufferLongName, MAX_PATH, RESOLVE_LINKS); + +// ConvertLongFileNameToShort(BufferLongName, BufferShortName, MAX_PATH); +//KdPrint(("%s\n%s\n", BufferLongName, BufferShortName)); + + if (CreateDirectoryRequest == TRUE) + { + POLICY_CHECK_OPTYPE(DIRECTORY, OP_DIR_CREATE); + } + else + { + POLICY_CHECK_OPTYPE(FILE, Get_FILE_OperationType(DesiredAccess)); + } + } + +//XXX if resolved name's first character is not '\' then allow? to allow names such as IDE#CdRomNECVMWar_VMware.. + + +/* +XXX +investigate + +The FileId can be used to open the file, when the FILE_OPEN_BY_FILE_ID +CreateOption is specified in a call to ZwCreateFile. + +whether this can be used to bypass name checking mechanism +*/ + if (CreateOptions & FILE_OPEN_BY_FILE_ID) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_WARNING, ("%d HookedNtCreateFile: FILE_OPEN_BY_FILE_ID set\n", (ULONG) PsGetCurrentProcessId())); + + HOOK_ROUTINE_EXIT( STATUS_ACCESS_DENIED ); + } + + + ASSERT(OriginalNtCreateFile); + + rc = OriginalNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, + AllocationSize, FileAttributes, ShareAccess, CreateDisposition, + CreateOptions, EaBuffer, EaLength); + + + if (CreateDirectoryRequest == TRUE) + { + HOOK_ROUTINE_FINISH_OPTYPE(DIRECTORY, OP_DIR_CREATE); + } + else + { + HOOK_ROUTINE_FINISH(FILE); + } +} + + + +/* + * HookedNtOpenFile() + * + * Description: + * This function mediates the NtOpenFile() system service and checks the + * provided file name against the global and current process security policies. + * + * NOTE: ZwOpenFile() opens a file. [NAR] + * + * Parameters: + * Those of NtOpenFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtOpenFile(). + */ + +NTSTATUS +NTAPI +HookedNtOpenFile +( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG OpenOptions +) +{ + PCHAR FunctionName = "HookedNtOpenFile"; +// HOOK_ROUTINE_START(FILE); + + CHAR BufferLongName[MAX_PATH], BufferShortName[MAX_PATH]; + PCHAR FILENAME = BufferLongName;//BufferShortName; + + + HOOK_ROUTINE_ENTER(); + + + if (LearningMode == FALSE) + { + GetPathFromOA(ObjectAttributes, BufferLongName, MAX_PATH, RESOLVE_LINKS); + +// ConvertLongFileNameToShort(BufferLongName, BufferShortName, MAX_PATH); +//KdPrint(("%s\n%s\n", BufferLongName, BufferShortName)); + + POLICY_CHECK_OPTYPE(FILE, Get_FILE_OperationType(DesiredAccess)); + } + + + ASSERT(OriginalNtOpenFile); + + rc = OriginalNtOpenFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, + ShareAccess, OpenOptions); + + + HOOK_ROUTINE_FINISH(FILE); +} + + + +/* + * HookedNtDeleteFile() + * + * Description: + * This function mediates the NtDeleteFile() system service and checks the + * provided file name against the global and current process security policies. + * + * NOTE: ZwDeleteFile deletes a file. [NAR] + * + * Parameters: + * Those of NtDeleteFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtDeleteFile(). + */ + +NTSTATUS +NTAPI +HookedNtDeleteFile +( + IN POBJECT_ATTRIBUTES ObjectAttributes +) +{ + PCHAR FunctionName = "HookedNtDeleteFile"; + + + HOOK_ROUTINE_START_OPTYPE(FILE, OP_DELETE); + + + ASSERT(OriginalNtDeleteFile); + + rc = OriginalNtDeleteFile(ObjectAttributes); + + + HOOK_ROUTINE_FINISH_OPTYPE(FILE, OP_DELETE); +} + + + +/* + * HookedNtQueryAttributesFile() + * + * Description: + * This function mediates the NtQueryAttributesFile() system service and checks the + * provided file name against the global and current process security policies. + * + * NOTE: ZwQueryAttributesFile retrieves basic information about a file object. [NAR] + * + * Parameters: + * Those of NtQueryAttributesFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtQueryAttributesFile(). + */ + +NTSTATUS +NTAPI +HookedNtQueryAttributesFile +( + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_BASIC_INFORMATION FileInformation +) +{ + PCHAR FunctionName = "HookedNtQueryAttributesFile"; + + + HOOK_ROUTINE_START_OPTYPE(FILE, OP_READ); + + + ASSERT(OriginalNtQueryAttributesFile); + + rc = OriginalNtQueryAttributesFile(ObjectAttributes, FileInformation); + + + HOOK_ROUTINE_FINISH_OPTYPE(FILE, OP_READ); +} + + + +/* + * HookedNtQueryFullAttributesFile() + * + * Description: + * This function mediates the NtQueryFullAttributesFile() system service and checks the + * provided file name against the global and current process security policies. + * + * NOTE: ZwQueryFullAttributesFile retrieves extended information about a file object. [NAR] + * + * Parameters: + * Those of NtQueryFullAttributesFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtQueryFullAttributesFile(). + */ + +NTSTATUS +NTAPI +HookedNtQueryFullAttributesFile +( + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation +) +{ + PCHAR FunctionName = "HookedNtQueryFullAttributesFile"; + + + HOOK_ROUTINE_START_OPTYPE(FILE, OP_READ); + + + ASSERT(OriginalNtQueryFullAttributesFile); + + rc = OriginalNtQueryFullAttributesFile(ObjectAttributes, FileInformation); + + + HOOK_ROUTINE_FINISH_OPTYPE(FILE, OP_READ); +} + + + +/* + * HookedNtQueryDirectoryFile() + * + * Description: + * This function mediates the NtQueryDirectoryFile() system service and checks the + * provided file name against the global and current process security policies. + * + * NOTE: ZwQueryDirectoryFile retrieves information about the contents of a directory. [NAR] + * + * Parameters: + * Those of NtQueryDirectoryFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtQueryDirectoryFile(). + */ + +NTSTATUS +NTAPI +HookedNtQueryDirectoryFile +( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG FileInformationLength, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN BOOLEAN ReturnSingleEntry, + IN PUNICODE_STRING FileName OPTIONAL, + IN BOOLEAN RestartScan +) +{ + PCHAR FunctionName = "HookedNtQueryDirectoryFile"; + UNICODE_STRING usInputFileName; + CHAR FILENAME[MAX_PATH]; + ANSI_STRING asFileName; + + + HOOK_ROUTINE_ENTER(); + + + if (ARGUMENT_PRESENT(FileName)) + { + if (!VerifyUnicodeString(FileName, &usInputFileName)) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("HookedNtQueryDirectoryFile: VerifyUnicodeString failed\n")); + HOOK_ROUTINE_EXIT( STATUS_ACCESS_DENIED ); + } + + + _snprintf(FILENAME, MAX_PATH, "%S", usInputFileName.Buffer); + FILENAME[ MAX_PATH - 1 ] = 0; + + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("HookedNtQueryDirectoryFile: %s\n", FILENAME)); + } + + + if (LearningMode == FALSE) + { + //XXX +// POLICY_CHECK_OPTYPE(FILE, OP_READ); + } + + + ASSERT(OriginalNtQueryDirectoryFile); + + rc = OriginalNtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, + FileInformation, FileInformationLength, FileInformationClass, + ReturnSingleEntry, FileName, RestartScan); + + +// HOOK_ROUTINE_FINISH_OBJECTNAME_OPTYPE(FILE, FILENAME, OP_READ); + HOOK_ROUTINE_EXIT(rc); +} + + + +/* + * HookedNtSetInformationFile() + * + * Description: + * This function mediates the NtSetInformationFile() system service and checks the + * provided file name against the global and current process security policies. + * + * NOTE: ZwSetInformationFile sets information affecting a file object. [NAR] + * + * Parameters: + * Those of NtSetInformationFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtSetInformationFile(). + */ + +NTSTATUS +NTAPI +HookedNtSetInformationFile +( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FileInformation, + IN ULONG FileInformationLength, + IN FILE_INFORMATION_CLASS FileInformationClass +) +{ + PCHAR FunctionName = "HookedNtSetInformationFile"; + CHAR FILENAME[MAX_PATH]; + WCHAR FILENAMEW[MAX_PATH]; + PWSTR FileName = NULL; + UCHAR Operation = OP_READ; + + + HOOK_ROUTINE_ENTER(); + + + /* FileDispositionInformation is used to delete files */ + if (FileInformationClass == FileDispositionInformation) + Operation = OP_DELETE; + + + if ((FileName = GetNameFromHandle(FileHandle, FILENAMEW, sizeof(FILENAMEW))) != NULL) + { + sprintf(FILENAME, "%S", FileName); + + LOG(LOG_SS_FILE, LOG_PRIORITY_VERBOSE, ("%d %s: %s\n", (ULONG) PsGetCurrentProcessId(), FunctionName, FILENAME)); + + if (LearningMode == FALSE) + { + POLICY_CHECK_OPTYPE_NAME(FILE, Operation); + } + } + + + ASSERT(OriginalNtSetInformationFile); + + rc = OriginalNtSetInformationFile(FileHandle, IoStatusBlock, FileInformation, FileInformationLength, FileInformationClass); + + + HOOK_ROUTINE_FINISH_OBJECTNAME_OPTYPE(FILE, FileName, Operation); +} + + + +/* + * HookedNtCreateNamedPipeFile() + * + * Description: + * This function mediates the NtCreateNamedPipeFile() system service and checks the + * provided named pipe name against the global and current process security policies. + * + * NOTE: ZwCreateNamedPipeFile creates a named pipe. [NAR] + * + * Parameters: + * Those of NtCreateNamedPipeFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtCreateNamedPipeFile(). + */ + +NTSTATUS +NTAPI +HookedNtCreateNamedPipeFile +( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN ULONG TypeMessage, + IN ULONG ReadmodeMessage, + IN ULONG Nonblocking, + IN ULONG MaxInstances, + IN ULONG InBufferSize, + IN ULONG OutBufferSize, + IN PLARGE_INTEGER DefaultTimeout OPTIONAL +) +{ + PCHAR FunctionName = "HookedNtCreateNamedPipeFile"; + + + HOOK_ROUTINE_START(NAMEDPIPE); + + + ASSERT(OriginalNtCreateNamedPipeFile); + + rc = OriginalNtCreateNamedPipeFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, + ShareAccess, CreateDisposition, CreateOptions, TypeMessage, + ReadmodeMessage, Nonblocking, MaxInstances, InBufferSize, + OutBufferSize, DefaultTimeout); + + + HOOK_ROUTINE_FINISH(NAMEDPIPE); +} + + + +/* + * HookedNtCreateMailslotFile() + * + * Description: + * This function mediates the NtCreateMailslotFile() system service and checks the + * provided mailslot name against the global and current process security policies. + * + * NOTE: ZwCreateMailslotFile creates a mailslot. [NAR] + * + * Parameters: + * Those of NtCreateMailslotFile(). + * + * Returns: + * STATUS_ACCESS_DENIED if the call does not pass the security policy check. + * Otherwise, NTSTATUS returned by NtCreateMailslotFile(). + */ + +NTSTATUS +NTAPI +HookedNtCreateMailslotFile +( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CreateOptions, + IN ULONG InBufferSize, + IN ULONG MaxMessageSize, + IN PLARGE_INTEGER ReadTimeout OPTIONAL +) +{ + PCHAR FunctionName = "HookedNtCreateMailslotFile"; + + + HOOK_ROUTINE_START(MAILSLOT); + + + ASSERT(OriginalNtCreateMailslotFile); + + rc = OriginalNtCreateMailslotFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, + CreateOptions, InBufferSize, MaxMessageSize, ReadTimeout); + + + HOOK_ROUTINE_FINISH(MAILSLOT); +} + + + +/* + * InitFileHooks() + * + * Description: + * Initializes all the mediated file operation pointers. The "OriginalFunction" pointers + * are initialized by InstallSyscallsHooks() that must be called prior to this function. + * + * NOTE: Called once during driver initialization (DriverEntry()). + * + * Parameters: + * None. + * + * Returns: + * TRUE to indicate success, FALSE if failed. + */ + +BOOLEAN +InitFileHooks() +{ + if ( (OriginalNtCreateFile = (fpZwCreateFile) ZwCalls[ZW_CREATE_FILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtCreateFile is NULL\n")); + return FALSE; + } + + if ( (OriginalNtOpenFile = (fpZwOpenFile) ZwCalls[ZW_OPEN_FILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtOpenFile is NULL\n")); + return FALSE; + } + + if ( (OriginalNtDeleteFile = (fpZwDeleteFile) ZwCalls[ZW_DELETE_FILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtDeleteFile is NULL\n")); + return FALSE; + } + + if ( (OriginalNtQueryAttributesFile = (fpZwQueryAttributesFile) ZwCalls[ZW_QUERY_ATTRIBUTES_FILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtQueryAttributesFile is NULL\n")); + return FALSE; + } + + if ( (OriginalNtQueryFullAttributesFile = (fpZwQueryFullAttributesFile) ZwCalls[ZW_QUERY_FULLATTR_FILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtQueryFullAttributesFile is NULL\n")); + return FALSE; + } +/* + if ( (OriginalNtQueryDirectoryFile = (fpZwQueryDirectoryFile) ZwCalls[ZW_QUERY_DIRECTORYFILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtQueryDirectoryFile is NULL\n")); + return FALSE; + } +*/ + if ( (OriginalNtSetInformationFile = (fpZwSetInformationFile) ZwCalls[ZW_SET_INFO_FILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtSetInformationFile is NULL\n")); + return FALSE; + } + + if ( (OriginalNtCreateNamedPipeFile = (fpZwCreateNamedPipeFile) ZwCalls[ZW_CREATE_NAMEDPIPEFILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtCreateNamedPipeFile is NULL\n")); + return FALSE; + } + + if ( (OriginalNtCreateMailslotFile = (fpZwCreateMailslotFile) ZwCalls[ZW_CREATE_MAILSLOTFILE_INDEX].OriginalFunction) == NULL) + { + LOG(LOG_SS_FILE, LOG_PRIORITY_DEBUG, ("InitFileHooks: OriginalNtCreateMailslotFile is NULL\n")); + return FALSE; + } + + return TRUE; +} -- cgit v1.3