#include "precomp.h" /************************************************************************* Prototypes *************************************************************************/ // // Assign text sections for each routine. // #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, Bs1FltPortConnect) #pragma alloc_text(PAGE, Bs1FltPortDisconnect) #pragma alloc_text(PAGE, Bs1FltMssageProc) #endif typedef struct _CLIENT_CONTEXT { LIST_ENTRY ListEntry; // ¸®½ºÆ® ¿¬°á¿ë PFLT_PORT ClientPort; // Ŭ¶óÀÌ¾ðÆ® Æ÷Æ® ÇÚµé PEPROCESS UserProcess; // ¿¬°áÇÑ À¯Àú ÇÁ·Î¼¼½º HANDLE ProcessId; // PID (·Î±ë/½Äº°¿ë) } CLIENT_CONTEXT, * PCLIENT_CONTEXT; // Àü¿ª º¯¼ö ¼±¾ð (DriverEntry µî¿¡¼­ ÃʱâÈ­ Çʼö) LIST_ENTRY g_ClientListHead; KSPIN_LOCK g_ClientListLock; LONG g_refCnt = 0; #define Reference() InterlockedIncrement(&g_refCnt) #define Dereference() InterlockedDecrement(&g_refCnt); void Bs1FltPortInit() { InitializeListHead(&g_ClientListHead); KeInitializeSpinLock(&g_ClientListLock); } void Bs1FltPortUnload() { KIRQL oldIrql; PCLIENT_CONTEXT clientCtx = NULL; PFLT_PORT portToClose = NULL; while (TRUE) { KeAcquireSpinLock(&g_ClientListLock, &oldIrql); if (IsListEmpty(&g_ClientListHead)) { KeReleaseSpinLock(&g_ClientListLock, oldIrql); break; } PLIST_ENTRY pEntry = g_ClientListHead.Flink; clientCtx = CONTAINING_RECORD(pEntry, CLIENT_CONTEXT, ListEntry); portToClose = (PFLT_PORT)InterlockedExchangePointer((PVOID*)&clientCtx->ClientPort, NULL); KeReleaseSpinLock(&g_ClientListLock, oldIrql); if (portToClose != NULL) { KLogEx(DEBUG_TRACE_INFO, "Force closing port: 0x%p\n", portToClose); FltCloseClientPort(g_bs1Flt.Filter, &portToClose); } else { KeAcquireSpinLock(&g_ClientListLock, &oldIrql); if (!IsListEmpty(&g_ClientListHead) && g_ClientListHead.Flink == pEntry) { RemoveEntryList(pEntry); ExFreePoolWithTag(clientCtx, '1SB'); } KeReleaseSpinLock(&g_ClientListLock, oldIrql); } } return; } NTSTATUS Bs1FltPortConnect( __in PFLT_PORT ClientPort, __in_opt PVOID ServerPortCookie, __in_bcount_opt(SizeOfContext) PVOID ConnectionContext, __in ULONG SizeOfContext, __deref_out_opt PVOID* ConnectionCookie ) { PCLIENT_CONTEXT clientCtx = NULL; KIRQL oldIrql; PAGED_CODE(); UNREFERENCED_PARAMETER(ServerPortCookie); UNREFERENCED_PARAMETER(ConnectionContext); UNREFERENCED_PARAMETER(SizeOfContext); UNREFERENCED_PARAMETER(ConnectionCookie); ASSERT(g_bs1Flt.ClientPort == NULL); ASSERT(g_bs1Flt.UserProcess == NULL); // // Set the user process and port. // clientCtx = (PCLIENT_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, sizeof(CLIENT_CONTEXT), '1SB'); if (clientCtx == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(clientCtx, sizeof(CLIENT_CONTEXT)); clientCtx->ClientPort = ClientPort; clientCtx->UserProcess = PsGetCurrentProcess(); clientCtx->ProcessId = PsGetCurrentProcessId(); KeAcquireSpinLock(&g_ClientListLock, &oldIrql); InsertTailList(&g_ClientListHead, &clientCtx->ListEntry); KeReleaseSpinLock(&g_ClientListLock, oldIrql); *ConnectionCookie = (PVOID)clientCtx; if( g_refCnt == 0 ) { // ÃʱâÈ­ ÀÛ¾÷ g_bs1Flt.UserProcess = PsGetCurrentProcess(); g_bs1Flt.ClientPort = ClientPort; } KLogEx(DEBUG_TRACE_INFO, "connected, port=0x%p\n", ClientPort); Reference(); return STATUS_SUCCESS; } VOID Bs1FltPortDisconnect( __in_opt PVOID ConnectionCookie ) { PCLIENT_CONTEXT clientCtx = (PCLIENT_CONTEXT)ConnectionCookie; KIRQL oldIrql; PFLT_PORT portToClose = NULL; //UNREFERENCED_PARAMETER(ConnectionCookie); PAGED_CODE(); if (clientCtx == NULL) { return; } KeAcquireSpinLock(&g_ClientListLock, &oldIrql); if (!IsListEmpty(&clientCtx->ListEntry)) { RemoveEntryList(&clientCtx->ListEntry); //InitializeListHead(&clientCtx->ListEntry); // Á¦°Å ÈÄ ÃʱâÈ­ (Áߺ¹ Á¦°Å ¹æÁö) clientCtx->ListEntry.Flink = NULL; clientCtx->ListEntry.Blink = NULL; } BOOLEAN bIsLastClient = IsListEmpty(&g_ClientListHead); KeReleaseSpinLock(&g_ClientListLock, oldIrql); portToClose = (PFLT_PORT)InterlockedExchangePointer((PVOID*)&clientCtx->ClientPort, NULL); KLogEx(DEBUG_TRACE_INFO, "disconnected, port=0x%p\n", portToClose); if (portToClose) { FltCloseClientPort(g_bs1Flt.Filter, &portToClose); clientCtx->ClientPort = NULL; } ExFreePoolWithTag(clientCtx, '1SB'); Dereference(); if (bIsLastClient) { g_bs1Flt.UserProcess = NULL; g_bs1Flt.ClientPort = NULL; g_bs1Flt.IsAttached = FALSE; g_bs1Flt.IsShareWatched = FALSE; g_bs1Flt.IsDeviceProtect = FALSE; // ResetFileObjectList(); // ResetFileList(); // CleanupPathlist(); // CleanupProcesslist(); // PgReset(); } if (g_refCnt == 0) { /* NTSTATUS ntstatus = 0; UNICODE_STRING drivername = {0,}; RtlInitUnicodeString(&drivername, DRIVERNAME); // PBShareLockUnload(0); // // KLogEx("Unload RegPath-----"); // KLogEx(DEBUG_TRACE_INFO, "Unload RegPath = %S\n", drivername.Buffer); ntstatus = FltUnloadFilter(&drivername); KLogEx(DEBUG_TRACE_INFO, "Unload ntstatus(%x)\n", ntstatus); */ } else { } } NTSTATUS Bs1FltMssageProc( __in PVOID ConnectionCookie, __in_bcount_opt(InputBufferSize) PVOID InputBuffer, __in ULONG InputBufferSize, __out_bcount_part_opt(OutputBufferSize, *ReturnOutputBufferLength) PVOID OutputBuffer, __in ULONG OutputBufferSize, __out PULONG ReturnOutputBufferLength ) { NTSTATUS ntStatus = STATUS_SUCCESS; PBS1FLT_MESSAGE msg = NULL; PAGED_CODE(); UNREFERENCED_PARAMETER(InputBufferSize); UNREFERENCED_PARAMETER(ConnectionCookie); UNREFERENCED_PARAMETER(ReturnOutputBufferLength); UNREFERENCED_PARAMETER(OutputBufferSize); try { msg = (PBS1FLT_MESSAGE)InputBuffer; if (!InputBuffer) leave; switch (msg->id_) { case SET_DEBUG_LEVEL: { g_DebugLevel = msg->pid_; KLogEx(DEBUG_TRACE_INFO, "SET_DEBUG_LEVEL(%x)\n", g_DebugLevel); } break; case START: { g_bs1Flt.IsAttached = TRUE; KLogEx(DEBUG_TRACE_INFO, "START\n"); } break; case STOP: { g_bs1Flt.IsAttached = FALSE; KLogEx(DEBUG_TRACE_INFO, "STOP\n"); } break; case CLEAR: { CleanupPathlist(); CleanupProcesslist(); CleanupFilelist(); CleanupProcessProtectList(); PgReset(); Initpolicy(); //CleanupUnloadlist(); PgAddPid(0, PG_PID_ALLOW); PgAddPid(4, PG_PID_ALLOW); PgAddPid(8, PG_PID_ALLOW); KLogEx(DEBUG_TRACE_INFO, "CLEAR\n"); } break; case SET_LOG_TYPE: { /*if (msg->type_ == 0 || msg->type_ == LOG_ALL) g_bs1Flt.LogType = msg->type_; else*/ g_bs1Flt.LogType = msg->type_; KLogEx(DEBUG_TRACE_INFO, "SET_LOG_TYPE(%d)\n", g_bs1Flt.LogType); } break; case SET_PROCESSNAME: { if (msg->w.process_path_.size == 0) break; SetProcessPath(msg->w.process_path_.type, msg->w.process_path_.path, msg->w.process_path_.size); KLogEx(DEBUG_TRACE_INFO, "SET_PROCESSNAME(%d)(%S)(%d)\n", \ msg->w.process_path_.type, \ msg->w.process_path_.path, \ msg->w.process_path_.size \ ); } break; case DEL_PROCESSNAME: { DelProcessPath(msg->w.process_path_.type, msg->w.process_path_.path, msg->w.process_path_.size); KLogEx(DEBUG_TRACE_INFO, "DEL_PROCESSNAME(%d)(%S)(%d)\n", \ msg->w.process_path_.type, \ msg->w.process_path_.path, \ msg->w.process_path_.size \ ); } break; case SET_PATH: { if (msg->w.file_path_.size == 0) break; SetProtectPath(msg->w.file_path_.type, msg->w.file_path_.path, msg->w.file_path_.size); KLogEx(DEBUG_TRACE_INFO, "SET_PATH(%d)(%S)(%d)\n", msg->w.file_path_.type, msg->w.file_path_.path, msg->w.file_path_.size); } break; case DEL_PATH: { DelPathlist(msg->w.file_path_.type, msg->w.file_path_.path, msg->w.file_path_.size); } break; case SET_FILENAME: { if (msg->w.file_path_.size == 0) break; SetFileName(msg->w.file_path_.type, msg->w.file_path_.path, msg->w.file_path_.size); KLogEx(DEBUG_TRACE_INFO, "SET_FILENAME(%d)(%S)(%d)\n", msg->w.file_path_.type, msg->w.file_path_.path, msg->w.file_path_.size); } break; case START_FOLDER_PROTECT: { if (msg->state_) g_bs1Flt.IsFolderProtect = TRUE; else g_bs1Flt.IsFolderProtect = FALSE; KLogEx(DEBUG_TRACE_INFO, "START_FOLDER_PROTECT(%d)\n", msg->state_); } break; case START_DEVICE_PROTECT: { if (msg->state_) g_bs1Flt.IsDeviceProtect = TRUE; else g_bs1Flt.IsDeviceProtect = FALSE; KLogEx(DEBUG_TRACE_INFO, "START_DEVICE_PROTECT(%d)\n", msg->state_); } break; case START_IS_SHARE_FOLDER_WATCHE: { if (msg->state_) g_bs1Flt.IsShareWatched = TRUE; else g_bs1Flt.IsShareWatched = FALSE; KLogEx(DEBUG_TRACE_INFO, "START_IS_SHARE_FOLDER_WATCHE(%d)\n", msg->state_); } break; case GET_PROCESS_NOTIFY_STATUS: { *(DWORD*)OutputBuffer = (DWORD)GetProcessNotifyStatus(); *ReturnOutputBufferLength = sizeof(DWORD); KLogEx(DEBUG_TRACE_INFO, "GET_PROCESS_NOTIFY_STATUS(%d)\n", *(DWORD*)OutputBuffer); } break; case SET_POLICY: { KLogEx(DEBUG_TRACE_INFO, "SET_POLICY, devicetype(%d), state(%d), log(%d)\n", msg->device_policy_.device_type, msg->device_policy_.state, msg->device_policy_.islog); SetPolicy(msg->device_policy_.device_type, msg->device_policy_.state, msg->device_policy_.islog); break; } case GET_LOG: { ULONG req = 0; ntStatus = GetLog(OutputBuffer, OutputBufferSize, &req); if (ntStatus == STATUS_SUCCESS) *ReturnOutputBufferLength = OutputBufferSize; else *ReturnOutputBufferLength = req; break; } case SET_HOOK: { #ifdef USB_PORT_HOOK if(msg->type_ == BDC_USB) // USB Port Hook { if (msg->state_) USBIrpHookInit(); else USBIrpHookCleanup(); } else if (msg->type_ == BDC_BLUETOOTH) { if (msg->state_) BlueToothIrpHookInit(); else BlueToothIrpHookCleanup(); } else if (msg->type_ == BDC_MTP) { if (msg->state_) MtpIrpHookInit(); else MtpIrpHookCleanup(); } else { switch (msg->type_) { case BDC_1394: case BDC_SERIAL: case BDC_PARALLEL: case BDC_IRDA: case BDC_MODEM: if (msg->state_) EtcIrpHookInit(); else EtcIrpHookCleanup(); break; default: break; } } #endif KLogEx(DEBUG_TRACE_INFO, "SET_HOOK(%d)(%d)\n", msg->type_, msg->state_); break; } case SET_REG_PROTECT: { if (msg->state_) StartRegFlt(g_bs1Flt.DriverObject); else g_bs1Flt.IsRegProtect = FALSE; KLogEx(DEBUG_TRACE_INFO, "SET_REG_PROTECT(%d)\n", msg->state_); break; } case SET_REG_KEY: { SetRegKeylist(msg->w.regkey_.regkey); KLogEx(DEBUG_TRACE_INFO, "SET_REG_KEY(%S)\n", msg->w.regkey_.regkey); break; } case DEL_REG_KEY: { DelRegKeylist(msg->w.regkey_.regkey); KLogEx(DEBUG_TRACE_INFO, "DEL_REG_KEY(%S)\n", msg->w.regkey_.regkey); break; } case SET_PROCESS_PROTECT: { if (msg->state_) InstallProcessProtect(); else g_bs1Flt.IsProcessProtect = FALSE; KLogEx(DEBUG_TRACE_INFO, "SET_PROCESS_PROTECT(%d)\n", g_bs1Flt.IsProcessProtect); break; } case SET_PROCESS_PROTECT_PID: { PgAddPid(msg->pid_, PG_PID_PROTECT); KLogEx(DEBUG_TRACE_INFO, "SET_PROCESS_PROTECT_PID(%d)\n", msg->pid_); break; } case DEL_PROCESS_PROTECT_PID: { if (msg->pid_ == 0) { PgResetState(PG_PID_PROTECT); } else { PgRemovePidState(msg->pid_, PG_PID_PROTECT); } KLogEx(DEBUG_TRACE_INFO, "DEL_PROCESS_PROTECT_PID(%d)\n", msg->pid_); break; } case SET_PROCESS_PROTECT_PROCESSNAME: { SetProcessProtectList(msg->w.process_path_.type, msg->w.process_path_.path, msg->w.process_path_.size); KLogEx(DEBUG_TRACE_INFO, "SET_PROCESS_PROTECT_PROCESSNAME(%S)(%d)\n", msg->w.process_path_.path, msg->w.process_path_.size); break; } case DEL_PROCESS_PROTECT_PROCESSNAME: { if (msg->w.process_path_.size == 0) { CleanupProcessProtectList(); } else { DelProcessProtectList(msg->w.process_path_.type, msg->w.process_path_.path, msg->w.process_path_.size); } KLogEx(DEBUG_TRACE_INFO, "DEL_PROCESS_PROTECT_PROCESSNAME(%S)(%d)\n", msg->w.process_path_.path, msg->w.process_path_.size); break; } case SET_USB_DISK_EXCEPT: { if (msg->state_ == STATE_SET) { SetUsbDiskException( msg->w.usb_except_.vendorid, msg->w.usb_except_.productid, msg->w.usb_except_.productrevisionlevel, msg->w.usb_except_.vendorspecific ); KLogEx(DEBUG_TRACE_INFO, "SET_USB_DISK_EXCEPT, (STATE_SET), vid(%s), pid(%s)(%s)\n", msg->w.usb_except_.vendorid, msg->w.usb_except_.productid, msg->w.usb_except_.vendorspecific ); } else if (msg->state_ == STATE_DEL) { KLogEx(DEBUG_TRACE_INFO, "SET_USB_DISK_EXCEPT, (STATE_DEL), vid(%s), pid(%s)(%s)\n", msg->w.usb_except_.vendorid, msg->w.usb_except_.productid, msg->w.usb_except_.vendorspecific ); DelUsbDiskExceptionList( msg->w.usb_except_.vendorid, msg->w.usb_except_.productid, msg->w.usb_except_.productrevisionlevel, msg->w.usb_except_.vendorspecific ); } else { CleanupUsbDiskExceptionList(); KLogEx(DEBUG_TRACE_INFO, "SET_USB_DISK_EXCEPT, (STATE_CLEAR)\n"); } break; } case SET_USB_PORT_EXCEPT: { #ifdef USB_PORT_HOOK if (msg->state_ == STATE_SET) { SetUsbPortException( msg->w.usb_port_except_.devicetype, msg->w.usb_port_except_.vendorid, msg->w.usb_port_except_.productid, msg->w.usb_port_except_.bcddevice, msg->w.usb_port_except_.serial ); KLogEx(DEBUG_TRACE_INFO, "SET_USB_PORT_EXCEPT, (STATE_SET), vid(%x), pid(%x), serial(%S)\n", msg->w.usb_port_except_.vendorid, msg->w.usb_port_except_.productid, msg->w.usb_port_except_.serial ); } else if (msg->state_ == STATE_DEL) { DelUsbPortExceptionList( msg->w.usb_port_except_.devicetype, msg->w.usb_port_except_.vendorid, msg->w.usb_port_except_.productid, msg->w.usb_port_except_.bcddevice, msg->w.usb_port_except_.serial ); KLogEx(DEBUG_TRACE_INFO, "SET_USB_PORT_EXCEPT, (STATE_DEL), vid(%x), pid(%x), serial(%S)\n", msg->w.usb_port_except_.vendorid, msg->w.usb_port_except_.productid, msg->w.usb_port_except_.serial ); } else { CleanupUsbPortExceptionList(); KLogEx(DEBUG_TRACE_INFO, "SET_USB_PORT_EXCEPT, (STATE_CLEAR)(%d)\n" , msg->state_); } #endif break; } default: break; } } except(EXCEPTION_EXECUTE_HANDLER) { ULONG ulEceptcode = GetExceptionCode(); KLogEx(DEBUG_TRACE_INFO, "eception = %08x\n", ulEceptcode); return ulEceptcode; } return ntStatus; }