📄 policy.c
字号:
/*
* Copyright (c) 2004 Security Architects Corporation. All rights reserved.
*
* Module Name:
*
* policy.c
*
* Abstract:
*
* This module implements various security policy parsing and enforcement routines.
*
* Author:
*
* Eugene Tsyrklevich 16-Feb-2004
*
* Revision History:
*
* None.
*/
// XXX rename all funcs as SpYYY ? (same for other modules?)
#include <NTDDK.h>
#include "policy.h"
#include "pathproc.h"
#include "procname.h"
#include "hookproc.h"
#include "media.h"
#include "learn.h"
#include "misc.h"
#include "i386.h"
#include "process.h"
#include "log.h"
BOOLEAN PolicyParseRule(OUT PSECURITY_POLICY pSecPolicy, IN PCHAR rule, OUT BOOLEAN *Critical);
BOOLEAN PolicyParsePolicyRule(OUT PSECURITY_POLICY pSecPolicy, IN PCHAR Operation, IN PCHAR rule, OUT BOOLEAN *Critical);
BOOLEAN PolicyParseObjectRule(PSECURITY_POLICY pSecPolicy, RULE_TYPE RuleType, PCHAR Operation, PCHAR rule);
BOOLEAN PolicyParseSyscallRule(PSECURITY_POLICY pSecPolicy, PCHAR SyscallName, PCHAR rule);
BOOLEAN PolicyParseProtectionRule(PSECURITY_POLICY pSecPolicy, PCHAR Operation, PCHAR rule);
BOOLEAN PolicyParseMediaRule(PSECURITY_POLICY pSecPolicy, PCHAR Operation, PCHAR rule);
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, InitPolicy)
#pragma alloc_text (PAGE, PolicyPostBootup)
#pragma alloc_text (PAGE, PolicyRemove)
#endif
/*
* example:
*
* SystemRoot - \device\harddisk1\windows
* SystemRootUnresolved - c:\windows
* SystemRootDirectory - \windows
* CDrive - \device\harddisk1
*/
CHAR SystemDrive, SystemRoot[MAX_PATH], SystemRootUnresolved[MAX_PATH], *SystemRootDirectory, CDrive[MAX_PATH];
USHORT SystemRootLength = 0, SystemRootUnresolvedLength = 0, SystemRootDirectoryLength = 0, CDriveLength = 0;
USHORT gPolicyLineNumber;
PWSTR gPolicyFilename, gFilePath;
// to be portable on 32 & 64 bit platforms
ULONG NumberOfBitsInUlong, UlongBitShift;
/* LoadPolicy() can be used by only one thread at a time due to use of global variables */
KMUTEX LoadPolicyMutex;
/* Global Security Policy */
SECURITY_POLICY gSecPolicy;
/*
* InitPolicy()
*
* Description:
* Initialize the policy engine. Load the global policy.
*
* NOTE: Called once during driver initialization (DriverEntry()).
*
* Parameters:
* None.
*
* Returns:
* TRUE if everything is OK, FALSE if failed.
*/
BOOLEAN
InitPolicy()
{
NumberOfBitsInUlong = sizeof(ULONG) * 8;
UlongBitShift = sizeof(ULONG) == 4 ? 5 : 6;
/* gets reinitialized correctly once bootup is complete (see PolicyPostBootup) */
SystemDrive = 'C';
if (ReadSymlinkValue(L"\\SystemRoot", SystemRootUnresolved, MAX_PATH) == FALSE)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("InitPolicy: ReadSymlinkValue failed\n"));
return FALSE;
}
SystemRootUnresolvedLength = (USHORT) strlen(SystemRootUnresolved);
ResolveFilename(SystemRootUnresolved, SystemRoot, MAX_PATH);
/* extract the system directory name by itself (i.e. \windows) */
SystemRootDirectory = strrchr(SystemRoot, '\\');
if (SystemRootDirectory == NULL)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("InitPolicy: SystemRootDirectory is NULL\n"));
return FALSE;
}
SystemRootDirectoryLength = (USHORT) strlen(SystemRootDirectory);
if (ReadSymlinkValue(L"\\??\\C:", CDrive, MAX_PATH) == FALSE)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("InitPolicy: Failed to open C: symbolic link\n"));
return FALSE;
}
CDriveLength = (USHORT) strlen(CDrive);
if (PolicyPostBootup() == FALSE)
{
/*
* if boot process is not complete yet then we cannot get SystemRootUnresolved (i.e. c:\windows)
* because parts of registry are not initialized yet (see PolicyPostBootup)
*
* In that case, try to assemble SystemRootUnresolved manually
*/
SystemRootUnresolved[0] = SystemDrive;
SystemRootUnresolved[1] = ':';
strcpy(SystemRootUnresolved + 2, SystemRootDirectory);
}
LOG(LOG_SS_POLICY, LOG_PRIORITY_VERBOSE, ("InitPolicy: SystemRoot=%s (%s, %s)\n", SystemRoot, SystemRootUnresolved, SystemRootDirectory));
KeInitializeMutex(&LoadPolicyMutex, 0);
RtlZeroMemory(&gSecPolicy, sizeof(gSecPolicy));
KeInitializeSpinLock(&gSecPolicy.SpinLock);
if (LearningMode == TRUE)
return TRUE;
if (FindAndLoadSecurityPolicy(&gSecPolicy, L"computer", NULL) == FALSE)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_WARNING, ("InitPolicy: LoadSecurityPolicy(computer.policy) failed\n"));
gSecPolicy.DefaultPolicyAction = ACTION_PERMIT_DEFAULT;
}
if (gSecPolicy.DefaultPolicyAction != ACTION_PERMIT_DEFAULT)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_WARNING, ("InitPolicy: Global policy default action must be permit\n"));
gSecPolicy.DefaultPolicyAction = ACTION_PERMIT_DEFAULT;
}
return TRUE;
}
/*
* PolicyPostBootup()
*
* Description:
* Finish initializing system variables once the bootup process is complete.
* We are unable to read the SystemRoot registry value before the bootup is complete since
* that part of the registry has not been initialized yet.
*
* Parameters:
* None.
*
* Returns:
* TRUE to indicate success, FALSE if failed.
*/
BOOLEAN
PolicyPostBootup()
{
ASSERT(BootingUp == FALSE);
if (ReadStringRegistryValueA(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion", L"SystemRoot", SystemRootUnresolved, MAX_PATH) == FALSE)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("PolicyPostBootup: Failed to open SystemRoot registry key\n"));
return FALSE;
}
SystemRootUnresolvedLength = (USHORT) strlen(SystemRootUnresolved);
SystemDrive = (CHAR) toupper(SystemRootUnresolved[0]);
return TRUE;
}
/*
* PolicyRemove()
*
* Description:
* Shutdown the policy engine. Delete the global policy
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*/
void
PolicyRemove()
{
PolicyDelete(&gSecPolicy);
}
/*
* PolicyDelete()
*
* Description:
* Delete a security policy. Free all the rules associated with a policy.
*
* Parameters:
* pSecPolicy - pointer to a security policy to delete.
*
* Returns:
* Nothing.
*/
void
PolicyDelete(IN PSECURITY_POLICY pSecPolicy)
{
PPOLICY_RULE r, tmp;
KIRQL irql;
UCHAR i;
if (pSecPolicy == NULL)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("PolicyDelete: pSecPolicy is NULL\n"));
return;
}
if (pSecPolicy->Initialized == FALSE)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_VERBOSE, ("PolicyDelete: pSecPolicy is not initialized\n"));
return;
}
KeAcquireSpinLock(&pSecPolicy->SpinLock, &irql);
for (i = 0; i < RULE_LASTONE; i++)
{
r = pSecPolicy->RuleList[i];
while (r)
{
tmp = r;
r = (PPOLICY_RULE) r->Next;
ExFreePoolWithTag(tmp, _POOL_TAG);
}
}
if (pSecPolicy->Name)
{
ExFreePoolWithTag(pSecPolicy->Name, _POOL_TAG);
pSecPolicy->Name = NULL;
}
pSecPolicy->Initialized = FALSE;
RtlZeroMemory(pSecPolicy->RuleList, sizeof(pSecPolicy->RuleList));
KeReleaseSpinLock(&pSecPolicy->SpinLock, irql);
}
/*
* LoadSecurityPolicy()
*
* Description:
* Parses and loads a security policy.
*
* Parameters:
* pSecPolicy - pointer to a security policy to initialize.
* PolicyFile - string containing the policy filename to parse
* FilePath - string containing full program path of the file we are loading policy for
*
* Returns:
* TRUE if security policy was successfully parsed and loaded, FALSE otherwise.
*/
BOOLEAN
LoadSecurityPolicy(OUT PSECURITY_POLICY pSecPolicy, IN PWSTR PolicyFile, IN PWSTR FilePath)
{
OBJECT_ATTRIBUTES oa;
HANDLE hFile = 0;
UNICODE_STRING usPolicyFile;
ULONG size;
NTSTATUS status;
IO_STATUS_BLOCK isb;
CHAR *p, buffer[POLICY_MAX_RULE_LENGTH];
INT64 offset;
BOOLEAN ret = TRUE, Critical = FALSE;
if (pSecPolicy == NULL || PolicyFile == NULL)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("LoadSecurityPolicy(%x, %x, %x): NULL parameter\n", pSecPolicy, PolicyFile, FilePath));
return FALSE;
}
pSecPolicy->Initialized = FALSE;
pSecPolicy->DefaultPolicyAction = ACTION_NONE;
pSecPolicy->ProtectionFlags = BootingUp ? PROTECTION_ALL_OFF : PROTECTION_ALL_ON;
RtlInitUnicodeString(&usPolicyFile, PolicyFile);
LOG(LOG_SS_POLICY, LOG_PRIORITY_VERBOSE, ("LoadSecurityPolicy: Parsing %S\n", usPolicyFile.Buffer));
InitializeObjectAttributes(&oa, &usPolicyFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
if (!NT_SUCCESS(ZwCreateFile(&hFile, GENERIC_READ, &oa, &isb,
NULL, 0, FILE_SHARE_READ, FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0)))
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_VERBOSE, ("LoadSecurityPolicy: Failed to open file %S\n", usPolicyFile.Buffer));
return FALSE;
}
offset = 0;
buffer[0] = 0;
/* only one thread at a time can use LoadPolicyMutex due to use of global variables (PolicyLineNumber, buffer) */
KeWaitForMutexObject(&LoadPolicyMutex, Executive, KernelMode, FALSE, NULL);
gPolicyLineNumber = 1;
gPolicyFilename = usPolicyFile.Buffer;
gFilePath = FilePath;
while (1)
{
status = ZwReadFile(hFile, NULL, NULL, NULL, &isb, (PVOID) buffer, sizeof(buffer) - 1,
(PLARGE_INTEGER) &offset, NULL);
if (! NT_SUCCESS(status))
{
if (status != STATUS_END_OF_FILE)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("LoadSecurityPolicy: ZwReadFile failed rc=%x\n", status));
ret = FALSE;
PolicyDelete(pSecPolicy);
}
break;
}
if (isb.Information == 0)
break;
buffer[isb.Information] = '\0';
/*
* strchr() will return NULL when the line we read exceeds the size of the buffer or
* the last line was not '\n' terminated
*/
if ((p = strchr(buffer, '\n')) == NULL)
{
/* don't try to parse very long lines */
if (isb.Information == sizeof(buffer) - 1)
{
LOG(LOG_SS_POLICY_PARSER, LOG_PRIORITY_WARNING, ("LoadSecurityPolicy(%s:%d): Rule is too long\n", gPolicyFilename, gPolicyLineNumber));
PolicyDelete(pSecPolicy);
ret = FALSE;
break;
}
/* the last rule was not '\n' terminated */
if (PolicyParseRule(pSecPolicy, buffer, &Critical) == FALSE)
{
if (Critical == TRUE)
{
LOG(LOG_SS_POLICY_PARSER, LOG_PRIORITY_DEBUG, ("LoadSecurityPolicy(%S:%d): Encountered a critical error. Aborting.\n", gPolicyFilename, gPolicyLineNumber));
PolicyDelete(pSecPolicy);
ret = FALSE;
break;
}
}
ret = TRUE;
break;
}
*p = 0;
if (p != buffer && *(p - 1) == '\r')
*(p - 1) = 0;
if (PolicyParseRule(pSecPolicy, buffer, &Critical) == FALSE)
{
if (Critical == TRUE)
{
LOG(LOG_SS_POLICY_PARSER, LOG_PRIORITY_DEBUG, ("LoadSecurityPolicy(%S:%d): Encountered a critical error. Aborting.\n", gPolicyFilename, gPolicyLineNumber));
PolicyDelete(pSecPolicy);
ret = FALSE;
break;
}
}
offset += p - buffer + 1;
if (++gPolicyLineNumber > 10000)
{
LOG(LOG_SS_POLICY_PARSER, LOG_PRIORITY_WARNING, ("LoadSecurityPolicy: Policy '%S' is too long. Maximum number of lines is 10000.\n", gPolicyFilename));
PolicyDelete(pSecPolicy);
ret = FALSE;
break;
}
}
ZwClose(hFile);
if (ret != FALSE)
{
pSecPolicy->Initialized = TRUE;
if (pSecPolicy->DefaultPolicyAction == ACTION_NONE)
pSecPolicy->DefaultPolicyAction = DEFAULT_POLICY_ACTION;
}
LOG(LOG_SS_POLICY, LOG_PRIORITY_VERBOSE, ("LoadSecurityPolicy: Done Parsing %S. Total number of lines %d. (ret=%d)\n", usPolicyFile.Buffer, gPolicyLineNumber, ret));
KeReleaseMutex(&LoadPolicyMutex, FALSE);
return ret;
}
/*
* FindAndLoadSecurityPolicy()
*
* Description:
* Finds and loads a security policy associated with a specified executable filename.
*
* Parameters:
* pSecPolicy - pointer to a security policy to initialize.
* FilePath - string specifying the complete path to an executable
* UserName - optional username, if specified check for a policy in "username" directory first
*
* Returns:
* TRUE if security policy was successfully parsed and loaded, FALSE otherwise.
*/
BOOLEAN
FindAndLoadSecurityPolicy(OUT PSECURITY_POLICY pSecPolicy, IN PWSTR FilePath, IN PWSTR UserName)
{
PWSTR filename;
WCHAR PolicyPath[MAX_PATH];
BOOLEAN ret;
int len;
if (pSecPolicy == NULL || FilePath == NULL)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("FindAndLoadSecurityPolicy: NULL argument %x %x\n", pSecPolicy, FilePath));
return FALSE;
}
if (KeGetCurrentIrql() != 0)
{
LOG(LOG_SS_POLICY, LOG_PRIORITY_DEBUG, ("FindAndLoadSecurityPolicy(): irql=%d\n", KeGetCurrentIrql()));
return FALSE;
}
filename = wcsrchr(FilePath, L'\\');
if (filename == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -