From 2acec63b2ed75bf4b71ad257db573c4b8f9639e7 Mon Sep 17 00:00:00 2001 From: tumagonx Date: Tue, 8 Aug 2017 10:54:53 +0700 Subject: initial commit --- driver.c | 1237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1237 insertions(+) create mode 100644 driver.c (limited to 'driver.c') diff --git a/driver.c b/driver.c new file mode 100644 index 0000000..09f66ad --- /dev/null +++ b/driver.c @@ -0,0 +1,1237 @@ +/* + * Copyright (c) 2004 Security Architects Corporation. All rights reserved. + * + * Module Name: + * + * driver.c + * + * Abstract: + * + * This module implements all the device driver "plumbing" (DriverEntry, etc). + * + * Author: + * + * Eugene Tsyrklevich 9-Feb-2004 + * + * Revision History: + * + * None. + */ + + +#include +#include + +#include "driver.h" +//#include "eugene.h" +#include "file.h" +#include "registry.h" +#include "sysinfo.h" +#include "policy.h" +#include "process.h" +#include "learn.h" +#include "event.h" +#include "semaphore.h" +#include "dirobj.h" +#include "symlink.h" +#include "mutant.h" +#include "port.h" +#include "timer.h" +#include "token.h" +#include "job.h" +#include "driverobj.h" +#include "network.h" +#include "section.h" +#include "atom.h" +#include "time.h" +#include "vdm.h" +#include "procname.h" +#include "userland.h" +#include "media.h" +#include "boprot.h" +#include "debug.h" +#include "i386.h" +#include "misc.h" +#include "log.h" + + +LONG SysenterEip = 0; + + +__declspec(naked) +VOID +SysenterHandler() +{ + _asm and ecx, 0x000000FF + _asm sub esp, ecx + _asm jmp [SysenterEip] +} + + +VOID +blah() +{ + LONG c, s; + +#define SYSENTER_CS_MSR 0x174 +#define SYSENTER_ESP_MSR 0x175 +#define SYSENTER_EIP_MSR 0x176 + + _asm + { + mov ecx, SYSENTER_CS_MSR + rdmsr + + mov c, eax + + + mov ecx, SYSENTER_ESP_MSR + rdmsr + + mov s, eax + + + mov ecx, SYSENTER_EIP_MSR + rdmsr + + mov SysenterEip, eax + + mov eax, SysenterHandler + + wrmsr + } + + KdPrint(("old eip=%x:%x (%x), new eip=%x\n", c, SysenterEip, s, SysenterHandler)); +} + + + +/* + * DriverEntry() + * + * Description: + * Driver entry point. + * + * Parameters: + * pDriverObject - pointer to an initialized driver object that represents our driver + * pRegistryPath - name of the service key in the registry + * + * Returns: + * STATUS_SUCCESS to indicate success or an error code to indicate an error. + */ + +/* macro shortcut for bailing out of DriverEntry in case of an error */ + +#define ABORT_DriverEntry(msg) \ + { \ + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_CRITICAL, (msg)); \ + if (irql != PASSIVE_LEVEL) KeLowerIrql(irql); \ + DriverUnload(pDriverObject); \ + return status; \ + } +/* +PVOID Find_Kernel32_Base(); +NTSTATUS +NTAPI +ZwCreateSymbolicLinkObject( + OUT PHANDLE SymbolicLinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING TargetName + ); + HANDLE h; +*/ +NTSTATUS +DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) +{ + UNICODE_STRING usDeviceName, usSymLinkName; + PDEVICE_OBJECT pDeviceObject; + PDEVICE_EXTENSION pDeviceExtension; + NTSTATUS status; + KIRQL irql = KeGetCurrentIrql(); + int i; + +/* + { + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING dest, target; + NTSTATUS status; + + RtlInitUnicodeString(&dest, L"\\??\\MyRegistryMachine"); + RtlInitUnicodeString(&target, L"\\Registry\\Machine"); + + InitializeObjectAttributes(&ObjectAttributes, &dest, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + + status = ZwCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, &target); + if (! NT_SUCCESS(status)) + { + KdPrint(("failed, status %x\n", status)); + } + else + { + KdPrint(("link ok\n")); + } + +// return STATUS_UNSUCCESSFUL; + } +*/ + //XXX add pRegistryPath to deny registry access rule?! + + __try + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverEntry: Entered (%x %S)\n", pDriverObject, pRegistryPath->Buffer)); + + +// blah(); +// KdPrint(("after blah\n")); + + + /* + * Verify we are running on x86 & everything is in order + */ + + if (!InitI386()) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_CRITICAL, ("InitI386 failed. Aborting.\n")); + return STATUS_UNSUCCESSFUL; + } + + + /* + * Initialize all the driver object related data and create a device representing our device + */ + + // set to NULL to disable unload by admins +// pDriverObject->DriverUnload = NULL; + pDriverObject->DriverUnload = DriverUnload; + +//XXX need to intercept DriverObject->FastIoDispatch = &VTrcFSFastIoDispatchTable; + + for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) + //XXX don't intercept IRP_MJ_POWER & IRP_MJ_PNP + pDriverObject->MajorFunction[i] = DriverDeviceControl; + + pDriverObject->MajorFunction[ IRP_MJ_CREATE ] = DriverCreate; + pDriverObject->MajorFunction[ IRP_MJ_CLEANUP ] = DriverCleanup; + pDriverObject->MajorFunction[ IRP_MJ_CLOSE ] = DriverClose; + pDriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = DriverDeviceControl; +/* + pDriverObject->MajorFunction[ IRP_MJ_READ ] = DriverRead; + pDriverObject->MajorFunction[ IRP_MJ_WRITE ] = DriverWrite; + */ + RtlInitUnicodeString(&usDeviceName, DEVICE_NAME); + + status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), + &usDeviceName, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, FALSE,//FALSE (Exclusive - Reserved for system use. Drivers set this parameter to FALSE.) +// 0, TRUE, + &pDeviceObject); + + if (!NT_SUCCESS(status)) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverEntry: IoCreateDevice failed with status %x\n", status)); + + return status; + } + + + pDeviceObject->Flags |= DO_BUFFERED_IO; + + pDeviceExtension = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension; + pDeviceExtension->pDeviceObject = pDeviceObject; + + + RtlInitUnicodeString(&pDeviceExtension->usSymLink, DEVICE_SYMLINK_NAME); + + status = IoCreateSymbolicLink(&pDeviceExtension->usSymLink, &usDeviceName); + if (!NT_SUCCESS(status)) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverEntry: IoCreateSymbolicLink failed with status %x\n", status)); + + IoDeleteDevice(pDeviceObject); + + return status; + } + + + /* + * Now, mediate all the necessary calls + */ + +#if HOOK_NETWORK + status = InstallNetworkHooks(pDriverObject); + if (! NT_SUCCESS(status)) + ABORT_DriverEntry("InstallNetworkHooks() failed"); +#endif + + + /* all consequitive calls that fail will cause the following error to be returned */ + + status = STATUS_DRIVER_INTERNAL_ERROR; + + if (!InitSyscallsHooks()) + ABORT_DriverEntry("InitSyscallsHooks() failed\n"); + + + /* + * raise irql to DPC level to avoid any spurious system calls taking place before we + * manage to initialize appropriate hooked function pointers + */ + + irql = KeRaiseIrqlToDpcLevel(); + + + if (!InstallSyscallsHooks()) + ABORT_DriverEntry("InstallSyscallsHooks() failed\n"); + + +#if HOOK_FILE + if (!InitFileHooks()) + ABORT_DriverEntry("InitFileHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitFileHooks\n")); +#endif + +#if HOOK_REGISTRY + if (!InitRegistryHooks()) + ABORT_DriverEntry("InitRegistryHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitRegistryHooks\n")); +#endif + +#if HOOK_SECTION + if (!InitSectionHooks()) + ABORT_DriverEntry("InitSectionHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitSectionHooks\n")); +#endif + +#if HOOK_SYSINFO + if (!InitSysInfoHooks()) + ABORT_DriverEntry("InitSysInfoHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitSysInfoHooks\n")); +#endif + +#if HOOK_EVENT + if (!InitEventHooks()) + ABORT_DriverEntry("InitEventHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitEventHooks\n")); +#endif + +#if HOOK_SEMAPHORE + if (!InitSemaphoreHooks()) + ABORT_DriverEntry("InitSemaphoreHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitSemaphoreHooks\n")); +#endif + +#if HOOK_JOB + if (!InitJobHooks()) + ABORT_DriverEntry("InitJobHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitJobHooks\n")); +#endif + +#if HOOK_MUTANT + if (!InitMutantHooks()) + ABORT_DriverEntry("InitMutantHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitMutantHooks\n")); +#endif + +#if HOOK_DIROBJ + if (!InitDirobjHooks()) + ABORT_DriverEntry("InitDirobjHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitDirobjHooks\n")); +#endif + +#if HOOK_PORT + if (!InitPortHooks()) + ABORT_DriverEntry("InitPortHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitPortHooks\n")); +#endif + +#if HOOK_SYMLINK + if (!InitSymlinkHooks()) + ABORT_DriverEntry("InitSymlinkHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitSymlinkHooks\n")); +#endif + +#if HOOK_TIMER + if (!InitTimerHooks()) + ABORT_DriverEntry("InitTimerHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitTimerHooks\n")); +#endif + +#if HOOK_TOKEN + if (!InitTokenHooks()) + ABORT_DriverEntry("InitTokenHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitTokenHooks\n")); +#endif + +#if HOOK_TIME + if (!InitTimeHooks()) + ABORT_DriverEntry("InitTimeHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitTimeHooks\n")); +#endif + +#if HOOK_DRIVEROBJ + if (!InitDriverObjectHooks()) + ABORT_DriverEntry("InitDriverObjectHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitDriverObjectHooks\n")); +#endif + +#if HOOK_ATOM + if (!InitAtomHooks()) + ABORT_DriverEntry("InitAtomHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitAtomHooks\n")); +#endif + +#if HOOK_VDM + if (!InitVdmHooks()) + ABORT_DriverEntry("InitVdmHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitVdmHooks\n")); +#endif + + +#if HOOK_DEBUG + if (!InitDebugHooks()) + ABORT_DriverEntry("InitDebugHooks() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitDebugHooks\n")); +#endif + + + KeLowerIrql(irql); + + + /* + * The order of the following calls is important: + * + * InitProcessEntries() initializes OzoneInstallPath + * InitPolicy() initiailizes policy related variables + * InitProcessNameEntries() then uses policy vars & OzoneInstallPath to load policies + */ + +#if HOOK_PROCESS + if (!InitProcessEntries()) + ABORT_DriverEntry("InitProcessEntries() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitProcessEntries\n")); +#endif + + + if (!InitProcessNameEntries()) + ABORT_DriverEntry("InitProcessNameEntries() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitProcessNameEntries\n")); + + + if (!InitPolicy()) + ABORT_DriverEntry("InitPolicy() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitPolicy\n")); + + + EnumerateExistingProcesses(); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past EnumerateExistingProcesses\n")); + + + + if (LearningMode == TRUE) + { + if (!InitLearningMode()) + ABORT_DriverEntry("InitLearningMode() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitLearningMode\n")); + } + + +#if HOOK_MEDIA + if (!InitRemovableMediaHooks(pDriverObject, pDeviceObject)) + ABORT_DriverEntry("InitRemovableMedia() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitRemovableMediaHooks\n")); +#endif + + +#if HOOK_BOPROT + if (!InitBufferOverflowProtection()) + ABORT_DriverEntry("InitBufferOverflowProtection() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitBufferOverflowProtection\n")); +#endif + + + if (!InitLog()) + ABORT_DriverEntry("InitLog() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitLog\n")); + + + if (!InitUserland()) + ABORT_DriverEntry("InitUserland() failed\n"); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverEntry: Past InitUserland\n")); + + } // __try + + __except(EXCEPTION_EXECUTE_HANDLER) + { + NTSTATUS status = GetExceptionCode(); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_CRITICAL, ("DriverEntry: caught an exception. status = 0x%x\n", status)); + + return STATUS_DRIVER_INTERNAL_ERROR; + } + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverEntry: Done\n")); + + + return STATUS_SUCCESS; +} + + + +/* + * DriverUnload() + * + * Description: + * Clean up and unload the driver. + * + * NOTE: Since this driver mediates system calls and other devices, it is not safe to + * unload the driver since there might remain outstanding references to our driver code and data + * segments once the driver is unloaded. + * + * NOTE2: In release builds, unload functionality should be disabled for security reasons. + * + * Parameters: + * pDriverObject - pointer to a driver object that represents this driver. + * + * Returns: + * Nothing. + */ + +VOID +DriverUnload(IN PDRIVER_OBJECT pDriverObject) +{ + PDEVICE_OBJECT pDeviceObject, pNextDeviceObject; + PDEVICE_EXTENSION pDeviceExtension; + LARGE_INTEGER delay; + + +#if DBG + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverUnload: irql = %d %d\n", KeGetCurrentIrql(), HookedTDIRunning)); +#endif + + + if (SysenterEip) + _asm + { + mov ecx, SYSENTER_EIP_MSR + mov eax, SysenterEip + xor edx, edx + wrmsr + } + +#if HOOK_BOPROT + ShutdownBufferOverflowProtection(); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverUnload: Past ShutdownBufferOverflowProtection\n")); +#endif + + + RemoveRemovableMediaHooks(); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverUnload: Past RemoveRemovableMediaHooks\n")); + + RemoveNetworkHooks(pDriverObject); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverUnload: Past RemoveNetworkHooks\n")); + + RemoveSyscallsHooks(); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverUnload: Past RemoveSyscallsHooks\n")); + + RemoveProcessNameEntries(); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverUnload: Past RemoveProcessNameEntries\n")); + + + if (LearningMode) + ShutdownLearningMode(); + else + PolicyRemove(); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverUnload: Past LearningMode\n")); + + + ShutdownLog(); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverUnload: Past ShutdownLog\n")); + + + ShutdownUserland(); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverUnload: Past UserlandShutdown\n")); + + + pDeviceObject = pNextDeviceObject = pDriverObject->DeviceObject; + + while (pNextDeviceObject != NULL) + { + pNextDeviceObject = pDeviceObject->NextDevice; + pDeviceExtension = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension; + + if (pDeviceExtension) + { + NTSTATUS status; + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverUnload: IoDeleteSymbolicLink(%S)\n", pDeviceExtension->usSymLink.Buffer)); + + status = IoDeleteSymbolicLink(&pDeviceExtension->usSymLink); + if (! NT_SUCCESS(status)) + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverUnload: IoDeleteSymbolicLink failed: %x\n", status)); + } + else + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverUnload: pDeviceExtension = NULL\n")); + + IoDeleteDevice(pDeviceObject); + pDeviceObject = pNextDeviceObject; + } + + + /* wait for 1 second for all timers/callbacks to complete */ + delay.QuadPart = SECONDS(1); + + KeDelayExecutionThread(KernelMode, FALSE, &delay); + + +#if DBG + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverUnload: HookedRoutineRunning = %d\n", HookedRoutineRunning)); +#endif + + + return; +} + + + +/* + * DriverDeviceControl() + * + * Description: + * Dispatch routine. Process network (TDI) and our driver requests. + * + * Parameters: + * pDeviceObject - pointer to a device object that a request is being sent to. + * pIrp - IRP (I/O Request Packet) request. + * + * Returns: + * Nothing. + */ + +#define COMPLETE_REQUEST(irp, status) \ + pIrp->IoStatus.Status = (status); \ + IoCompleteRequest((irp), IO_NO_INCREMENT); \ + return((status)); + +NTSTATUS +DriverDeviceControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) +{ + PIO_STACK_LOCATION pIrpStack; + ULONG ControlCode; + NTSTATUS status; + ULONG InSize, OutSize; + KIRQL irql; + + + if (pDeviceObject == NULL || pIrp == NULL) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: NULL value %x %x\n", pDeviceObject, pIrp)); + + COMPLETE_REQUEST(pIrp, STATUS_UNSUCCESSFUL); + } + + +#if HOOK_NETWORK + if (TDIDispatch(pDeviceObject, pIrp, &status) == TRUE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverDeviceControl(%x, %x): TDIDispatch\n", pDeviceObject, pIrp)); + return status; + } +#endif + + + pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + + pIrp->IoStatus.Information = 0; + + + ControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; + InSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; + OutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + switch (ControlCode) + { + /* + * When userland agent service starts up, it registers with the driver using IOCTL_REGISTER_AGENT_SERVICE. + * Expects back 1 ULONG - version of the driver + */ + + // XXX save agent pid and version? + case IOCTL_REGISTER_AGENT_SERVICE: + { + ULONG DriverVersion = DRIVER_VERSION; + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_REGISTER_AGENT_SERVICE ControlCode=%x InBufferSize=%x OutBufferSize=%x\n", ControlCode, InSize, OutSize)); + + + if (OutSize < sizeof(ULONG)) + { + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + + + RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, &DriverVersion, sizeof(ULONG)); + + ActiveUserAgent = TRUE; + + + pIrp->IoStatus.Information = sizeof(ULONG); + + status = STATUS_SUCCESS; + + + break; + } + + + /* + * Userland agent service retrieves log alerts using IOCTL_GET_ALERT + */ + + case IOCTL_GET_ALERT: + { + PSECURITY_ALERT TmpAlert; + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_GET_ALERT ControlCode=%x InBufferSize=%x OutBufferSize=%x\n", ControlCode, InSize, OutSize)); + + +// if (UserAgentRegistered == FALSE) +// XXX; + + KeAcquireSpinLock(&gLogSpinLock, &irql); + { + if (LogList == NULL) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_GET_ALERT No More Alerts\n")); + + status = STATUS_NO_MORE_ENTRIES; + + KeReleaseSpinLock(&gLogSpinLock, irql); + + break; + } + + /* don't count the size of the Next pointer */ + LogList->Size -= sizeof(struct _SECURITY_ALERT *); + + if (OutSize < LogList->Size) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_GET_ALERT %d < %d\n", OutSize, LogList->Size)); + status = STATUS_INVALID_BUFFER_SIZE; + KeReleaseSpinLock(&gLogSpinLock, irql); + break; + } + + /* copy the SECURITY_ALERT structure without including the Next pointer */ + RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, (PCHAR)LogList + sizeof(struct _SECURITY_ALERT *), LogList->Size); + + pIrp->IoStatus.Information = LogList->Size; + + + --NumberOfAlerts; + + TmpAlert = LogList; + LogList = LogList->Next; + + ExFreePoolWithTag(TmpAlert, _POOL_TAG); + } + KeReleaseSpinLock(&gLogSpinLock, irql); + + + status = STATUS_SUCCESS; + + break; + } + + + /* + * Userland agent service retrieves userland requests using IOCTL_GET_USERLAND_REQUEST + */ + + case IOCTL_GET_USERLAND_REQUEST: + { + PUSERLAND_REQUEST_HEADER TmpRequest; + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_GET_USERLAND_REQUEST ControlCode=%x InBufferSize=%x OutBufferSize=%x\n", ControlCode, InSize, OutSize)); + + + KeAcquireSpinLock(&gUserlandRequestListSpinLock, &irql); + { + USHORT UserlandRequestSize; + + + if (UserlandRequestList == NULL) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_GET_USERLAND_REQUEST No More Process Requests\n")); + + status = STATUS_NO_MORE_ENTRIES; + + KeReleaseSpinLock(&gUserlandRequestListSpinLock, irql); + + break; + } + + + /* don't count the size of the Next pointer */ + UserlandRequestSize = UserlandRequestList->RequestSize - sizeof(struct _USERLAND_REQUEST *); + + if (OutSize < UserlandRequestSize) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_GET_USERLAND_REQUEST %d < %d\n", OutSize, UserlandRequestSize)); + + KeReleaseSpinLock(&gUserlandRequestListSpinLock, irql); + + status = STATUS_INVALID_BUFFER_SIZE; + + break; + } + + /* copy the PROCESS_REQUEST structure without including the Next pointer */ + RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, (PCHAR)UserlandRequestList + sizeof(struct _USERLAND_REQUEST *), UserlandRequestSize); + + pIrp->IoStatus.Information = UserlandRequestSize; + + + TmpRequest = UserlandRequestList; + UserlandRequestList = UserlandRequestList->Next; + + ExFreePoolWithTag(TmpRequest, _POOL_TAG); + } + KeReleaseSpinLock(&gUserlandRequestListSpinLock, irql); + + + status = STATUS_SUCCESS; + + break; + } + + + /* + * Userland agent service returns userland replies using IOCTL_SEND_USERLAND_SID_RESOLVE_REPLY + */ + +#define MAXIMUM_USERLAND_REPLY_SIZE 512 + + case IOCTL_SEND_USERLAND_SID_RESOLVE_REPLY: + { + PSID_RESOLVE_REPLY pSidResolveReply; + PIMAGE_PID_ENTRY ProcessEntry; + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_SEND_USERLAND_SID_RESOLVE_REPLY ControlCode=%x InBufferSize=%x OutBufferSize=%x\n", ControlCode, InSize, OutSize)); + + + if (InSize > MAXIMUM_USERLAND_REPLY_SIZE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_SEND_USERLAND_SID_RESOLVE_REPLY %d > %d\n", InSize, MAXIMUM_USERLAND_REPLY_SIZE)); + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + + pSidResolveReply = ExAllocatePoolWithTag(PagedPool, InSize, _POOL_TAG); + if (pSidResolveReply == NULL) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_SEND_USERLAND_SID_RESOLVE_REPLY out of memory\n")); + status = STATUS_UNSUCCESSFUL; + break; + } + + + RtlCopyMemory(pSidResolveReply, pIrp->AssociatedIrp.SystemBuffer, InSize); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: Received sid resolve reply. insize=%d seq=%d, %S\n", InSize, pSidResolveReply->ReplyHeader.SeqId, pSidResolveReply->UserName)); + + ProcessEntry = FindImagePidEntry(pSidResolveReply->ReplyHeader.ProcessId, 0); + + if (ProcessEntry) + { + if (ProcessEntry->WaitingForUserRequestId == 0) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: Process (pid=%d) is not expecting a user request!\n", pSidResolveReply->ReplyHeader.ProcessId)); + ExFreePoolWithTag(pSidResolveReply, _POOL_TAG); + ProcessEntry->UserlandReply = NULL; + break; + } + + if (ProcessEntry->WaitingForUserRequestId != pSidResolveReply->ReplyHeader.SeqId) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: Process (pid=%d) is expecting to receive sequence id %d. Got %d\n", pSidResolveReply->ReplyHeader.ProcessId, ProcessEntry->WaitingForUserRequestId, pSidResolveReply->ReplyHeader.SeqId)); + ExFreePoolWithTag(pSidResolveReply, _POOL_TAG); + ProcessEntry->UserlandReply = NULL; + break; + } + + + /* deliver the reply */ + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: Waking up process %d\n", pSidResolveReply->ReplyHeader.ProcessId)); + + ProcessEntry->UserlandReply = (PUSERLAND_REPLY_HEADER) pSidResolveReply; + + KeSetEvent(&ProcessEntry->UserlandRequestDoneEvent, IO_NO_INCREMENT, FALSE); + } + else + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: cannot find process with pid=%d\n", pSidResolveReply->ReplyHeader.ProcessId)); + + + status = STATUS_SUCCESS; + + break; + } + + + /* + * Userland agent service returns "ask user" replies using IOCTL_SEND_USERLAND_ASK_USER_REPLY + */ + + case IOCTL_SEND_USERLAND_ASK_USER_REPLY: + { + PASK_USER_REPLY pAskUserReply; + PIMAGE_PID_ENTRY ProcessEntry; + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_SEND_USERLAND_ASK_USER_REPLY ControlCode=%x InBufferSize=%x OutBufferSize=%x\n", ControlCode, InSize, OutSize)); + + + if (InSize != sizeof(ASK_USER_REPLY)) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_SEND_USERLAND_ASK_USER_REPLY %d != %d\n", InSize, sizeof(ASK_USER_REPLY))); + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + + pAskUserReply = ExAllocatePoolWithTag(PagedPool, sizeof(ASK_USER_REPLY), _POOL_TAG); + if (pAskUserReply == NULL) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_SEND_USERLAND_ASK_USER_REPLY out of memory\n")); + status = STATUS_UNSUCCESSFUL; + break; + } + + + RtlCopyMemory(pAskUserReply, pIrp->AssociatedIrp.SystemBuffer, InSize); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: Received ask user reply. insize=%d, action=%d\n", InSize, pAskUserReply->Action)); + + ProcessEntry = FindImagePidEntry(pAskUserReply->ReplyHeader.ProcessId, 0); + + if (ProcessEntry) + { + if (ProcessEntry->WaitingForUserRequestId == 0) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: Process (pid=%d) is not expecting a user request!\n", pAskUserReply->ReplyHeader.ProcessId)); + ExFreePoolWithTag(pAskUserReply, _POOL_TAG); + ProcessEntry->UserlandReply = NULL; + break; + } + + if (ProcessEntry->WaitingForUserRequestId != pAskUserReply->ReplyHeader.SeqId) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: Process (pid=%d) is expecting to receive sequence id %d. Got %d\n", pAskUserReply->ReplyHeader.ProcessId, ProcessEntry->WaitingForUserRequestId, pAskUserReply->ReplyHeader.SeqId)); + ExFreePoolWithTag(pAskUserReply, _POOL_TAG); + ProcessEntry->UserlandReply = NULL; + break; + } + + + /* deliver the reply */ + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: Waking up process %d\n", pAskUserReply->ReplyHeader.ProcessId)); + + ProcessEntry->UserlandReply = (PUSERLAND_REPLY_HEADER) pAskUserReply; + + KeSetEvent(&ProcessEntry->UserlandRequestDoneEvent, IO_NO_INCREMENT, FALSE); + } + else + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("cannot find process with pid=%d\n", pAskUserReply->ReplyHeader.ProcessId)); + + + status = STATUS_SUCCESS; + + break; + } + + + /* + * train.exe puts the driver in learning/training mode using IOCTL_START_CREATE_POLICY + */ + + case IOCTL_START_CREATE_POLICY: + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverDeviceControl: IOCTL_START_CREATE_POLICY ControlCode=%x InBufferSize=%x OutBufferSize=%x\n", ControlCode, InSize, OutSize)); + + + if ((InSize > MAX_PROCESS_NAME * sizeof(WCHAR)) || (InSize % 2)) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_START_CREATE_POLICY Invalid Insize: %d\n", InSize)); + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + + status = STATUS_SUCCESS; + + if (LearningMode == TRUE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_START_CREATE_POLICY Already in Learning Mode\n")); + break; + } + + RtlCopyMemory(ProcessToMonitor, pIrp->AssociatedIrp.SystemBuffer, InSize); + ProcessToMonitor[(InSize / sizeof(WCHAR)) - 1] = 0; + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_START_CREATE_POLICY Learning about '%S'\n", ProcessToMonitor)); + + LearningMode = TRUE; + + InitLearningMode(); + + break; + } + + + /* + * train.exe stops training/learning mode using IOCTL_STOP_CREATE_POLICY + */ + + case IOCTL_STOP_CREATE_POLICY: + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverDeviceControl: IOCTL_STOP_CREATE_POLICY ControlCode=%x InBufferSize=%x OutBufferSize=%x\n", ControlCode, InSize, OutSize)); + + + if ((InSize > MAX_PROCESS_NAME * sizeof(WCHAR)) || (InSize % 2)) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_STOP_CREATE_POLICY Invalid Insize: %d\n", InSize)); + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + + status = STATUS_SUCCESS; + + if (LearningMode == FALSE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_STOP_CREATE_POLICY Not in Learning Mode\n")); + break; + } + +// RtlCopyMemory(ProcessToMonitor, pIrp->AssociatedIrp.SystemBuffer, InSize); +// ProcessToMonitor[(InSize / sizeof(WCHAR)) - 1] = 0; + +// LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_STOP_CREATE_POLICY '%S'\n", ProcessToMonitor)); + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverDeviceControl: IOCTL_STOP_CREATE_POLICY\n")); + + ShutdownLearningMode(); + + LearningMode = FALSE; + + break; + } + + + default: + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("%d DriverDeviceControl default %x %x %x %x\n", (ULONG) PsGetCurrentProcessId(), pIrpStack->MajorFunction, ControlCode, InSize, OutSize)); + status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + + COMPLETE_REQUEST(pIrp, status); +} + + + +NTSTATUS +DriverCreate(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) +{ + NTSTATUS status; + + +#if HOOK_NETWORK + if (TDIDispatch(pDeviceObject, pIrp, &status) == TRUE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverCreate(%x, %x): TDIDispatch\n", pDeviceObject, pIrp)); + return status; + } +#endif + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverCreate(%x, %x)\n", pDeviceObject, pIrp)); + + + //XXX need to consider any possible lock out issues where a valid userland agent is disallowed access + //can verify userland binary name as well +#if 0 + if (ActiveUserAgent == TRUE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("Userland agent already exists!\n")); + + pIrp->IoStatus.Status = STATUS_ACCESS_DENIED; + pIrp->IoStatus.Information = 0; + IoCompleteRequest(pIrp, IO_NO_INCREMENT); + + return STATUS_ACCESS_DENIED; + } + + ActiveUserAgent = TRUE; +#endif + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest(pIrp, IO_NO_INCREMENT); + + + return STATUS_SUCCESS; +} + + + +NTSTATUS +DriverClose(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) +{ + NTSTATUS status; + + +#if HOOK_NETWORK + if (TDIDispatch(pDeviceObject, pIrp, &status) == TRUE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverClose(%x, %x): TDIDispatch\n", pDeviceObject, pIrp)); + return status; + } +#endif + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverClose(%x, %x)\n", pDeviceObject, pIrp)); + +#if 0 + if (ActiveUserAgent == FALSE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("Userland agent does not exist!\n")); + } + + ActiveUserAgent = FALSE; +#endif + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest(pIrp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + + + +NTSTATUS +DriverCleanup(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) +{ + NTSTATUS status; + + +#if HOOK_NETWORK + if (TDIDispatch(pDeviceObject, pIrp, &status) == TRUE) + { + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_VERBOSE, ("DriverCleanup(%x, %x): TDIDispatch\n", pDeviceObject, pIrp)); + return status; + } +#endif + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverCleanup(%x, %x)\n", pDeviceObject, pIrp)); + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest(pIrp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + + + +#if 0 +NTSTATUS +DriverRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) +{ + PDEVICE_EXTENSION pDeviceExtension; + PIO_STACK_LOCATION pIrpStack; + ULONG size = 0; + + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("DriverRead()\n")); + + pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + + pDeviceExtension = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension; +/* + size = min(pDeviceExtension->BufferSize, pIrpStack->Parameters.Read.Length); + + RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, pDeviceExtension->Buffer, size); + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("Wrote %d bytes: %s\n", size, pDeviceExtension->Buffer)); + + pDeviceExtension->BufferSize = 0; +*/ + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = size; + IoCompleteRequest(pIrp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + + + +NTSTATUS +DriverWrite(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) +{ + PDEVICE_EXTENSION pDeviceExtension; + PIO_STACK_LOCATION pIrpStack; + ULONG size = 0; + + + LOG(LOG_SS_DRIVER_INTERNAL,LOG_PRIORITY_DEBUG, ("DriverWrite()\n")); + + pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + + pDeviceExtension = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension; +/* + size = min(128, pIrpStack->Parameters.Write.Length); + RtlCopyMemory(pDeviceExtension->Buffer, pIrp->AssociatedIrp.SystemBuffer, size); + + pDeviceExtension->BufferSize = size; + + LOG(LOG_SS_DRIVER_INTERNAL, LOG_PRIORITY_DEBUG, ("Read %d bytes: %s\n", size, pDeviceExtension->Buffer)); +*/ + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = size; + IoCompleteRequest(pIrp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} +#endif -- cgit v1.3