/*++ Module Name: cdsflt.c Abstract: This is the main module of the cds_flt miniFilter driver. Environment: Kernel mode --*/ #include "precomp.h" #pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers") ULONG g_DebugLevel = 0; BS1FLT g_bs1Flt; PFLT_FILTER gFilterHandle; ULONG_PTR OperationStatusCtx = 1; ULONG gTraceFlags = 0; #define _ALLOC_TAG 'kdqw' BOOLEAN g_IsUnloadAllowed = TRUE; /************************************************************************* Prototypes *************************************************************************/ // // Assign text sections for each routine. // #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) #pragma alloc_text(PAGE, Bs1FltUnload) #pragma alloc_text(PAGE, Bs1FltInstanceQueryTeardown) #pragma alloc_text(PAGE, Bs1FltInstanceSetup) #pragma alloc_text(PAGE, Bs1FltInstanceTeardownStart) #pragma alloc_text(PAGE, Bs1FltInstanceTeardownComplete) #endif // // operation registration // CONST FLT_OPERATION_REGISTRATION Callbacks[] = { #if 1 // TODO - List all of the requests to filter. { IRP_MJ_CREATE, 0, Bs1FltPreOperation, Bs1FltPostOperation }, /* { IRP_MJ_CREATE_NAMED_PIPE, 0, cdsfltPreOperation, cdsfltPostOperation },*/ { IRP_MJ_CLOSE, 0, Bs1FltPreOperation, Bs1FltPostOperation }, { IRP_MJ_WRITE, 0, Bs1FltPreOperation, Bs1FltPostOperation }, { IRP_MJ_READ, 0, Bs1FltPreRead, NULL }, /* { IRP_MJ_QUERY_INFORMATION, 0, cdsfltPreOperation, cdsfltPostOperation },*/ { IRP_MJ_SET_INFORMATION, 0, Bs1FltPreOperation, Bs1FltPostOperation }, //{ IRP_MJ_QUERY_EA, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_SET_EA, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_FLUSH_BUFFERS, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_QUERY_VOLUME_INFORMATION, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_SET_VOLUME_INFORMATION, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_DIRECTORY_CONTROL, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_FILE_SYSTEM_CONTROL, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_DEVICE_CONTROL, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_INTERNAL_DEVICE_CONTROL, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_SHUTDOWN, // 0, // cdsfltPreOperationNoPostOperation, // NULL }, //post operations not supported //{ IRP_MJ_LOCK_CONTROL, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, { IRP_MJ_CLEANUP, 0, Bs1FltPreOperation, Bs1FltPostOperation }, //{ IRP_MJ_CREATE_MAILSLOT, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_QUERY_SECURITY, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_SET_SECURITY, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_QUERY_QUOTA, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_SET_QUOTA, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_PNP, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_RELEASE_FOR_SECTION_SYNCHRONIZATION, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_ACQUIRE_FOR_MOD_WRITE, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_RELEASE_FOR_MOD_WRITE, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_ACQUIRE_FOR_CC_FLUSH, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_RELEASE_FOR_CC_FLUSH, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_FAST_IO_CHECK_IF_POSSIBLE, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_NETWORK_QUERY_OPEN, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_MDL_READ, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_MDL_READ_COMPLETE, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_PREPARE_MDL_WRITE, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_MDL_WRITE_COMPLETE, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_VOLUME_MOUNT, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, //{ IRP_MJ_VOLUME_DISMOUNT, // 0, // cdsfltPreOperation, // cdsfltPostOperation }, #endif // TODO { IRP_MJ_OPERATION_END } }; #define VOLUME_CONTEXT_POOLTAG 'b1vo' const FLT_CONTEXT_REGISTRATION ContextRegistration[] = { { FLT_VOLUME_CONTEXT, 0, Bs1FltCleanupVolumeContext, sizeof(VOLUME_CONTEXT), VOLUME_CONTEXT_POOLTAG }, { FLT_CONTEXT_END } }; // // This defines what we want to filter with FltMgr // CONST FLT_REGISTRATION FilterRegistration = { sizeof( FLT_REGISTRATION ), // Size FLT_REGISTRATION_VERSION, // Version 0, // Flags ContextRegistration, // Context Callbacks, // Operation callbacks Bs1FltUnload, // MiniFilterUnload Bs1FltInstanceSetup, // InstanceSetup Bs1FltInstanceQueryTeardown, // InstanceQueryTeardown NULL, // InstanceTeardownStart NULL, // InstanceTeardownComplete NULL, // GenerateFileName NULL, // GenerateDestinationFileName NULL // NormalizeNameComponent }; /* NTSTATUS GetPnPDeviceId( __in PDEVICE_OBJECT DeviceObject, __in DEVICE_REGISTRY_PROPERTY RegistryProperty, // DevicePropertyHardwareID or DevicePropertyInstanceID __out PWCHAR* IdString ) { NTSTATUS status; ULONG resultLength = 0; PVOID buffer = NULL; // 1. ÇÊ¿äÇÑ ¹öÆÛ Å©±â ±¸Çϱâ status = IoGetDeviceProperty( DeviceObject, RegistryProperty, 0, NULL, &resultLength ); if (status != STATUS_BUFFER_TOO_SMALL) { return STATUS_UNSUCCESSFUL; } // 2. ¸Þ¸ð¸® ÇÒ´ç buffer = ExAllocatePoolWithTag(NonPagedPool, resultLength, 'PnPI'); if (!buffer) { return STATUS_INSUFFICIENT_RESOURCES; } // 3. ½ÇÁ¦ µ¥ÀÌÅÍ °¡Á®¿À±â status = IoGetDeviceProperty( DeviceObject, RegistryProperty, resultLength, buffer, &resultLength ); if (NT_SUCCESS(status)) { *IdString = (PWCHAR)buffer; } else { ExFreePoolWithTag(buffer, 'PnPI'); *IdString = NULL; } return status; } NTSTATUS Bs1FltGetUsb( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_SETUP_FLAGS Flags, _In_ DEVICE_TYPE VolumeDeviceType, _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT diskDeviceObject = NULL; PDEVICE_OBJECT physicalDeviceObject = NULL; // PDO PWCHAR pInstanceId = NULL; UNREFERENCED_PARAMETER(Flags); UNREFERENCED_PARAMETER(VolumeDeviceType); UNREFERENCED_PARAMETER(VolumeFilesystemType); PAGED_CODE(); // 1. ³×Æ®¿öÅ© º¼·ý µîÀº ¹°¸® µð½ºÅ©°¡ ¾øÀ¸¹Ç·Î Skip // (³×Æ®¿öÅ© µå¶óÀ̺꿡¼­ DiskDeviceObject¸¦ ±¸ÇÏ¸é ½ÇÆÐÇϰųª NULLÀÌ ³ª¿É´Ï´Ù) if (VolumeDeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) { return STATUS_SUCCESS; } // 2. º¼·ý¿¡¼­ ½ÇÁ¦ µð½ºÅ© µð¹ÙÀ̽º °´Ã¼(Disk Device Object) ȹµæ status = FltGetDiskDeviceObject(FltObjects->Volume, &diskDeviceObject); // µð½ºÅ© ±â¹Ý ÆÄÀÏ ½Ã½ºÅÛÀÌ ¾Æ´Ï¸é(RAM Disk, Network µî) ½ÇÆÐÇÒ ¼ö ÀÖÀ½ if (NT_SUCCESS(status) && diskDeviceObject != NULL) { // 3. µð¹ÙÀ̽º ½ºÅÃÀÇ °¡Àå ¹Ù´Ú¿¡ ÀÖ´Â PDO(Physical Device Object) ȹµæ // PnP Á¤º¸(VID, PID µî)´Â PDO¿¡ ÀúÀåµÇ¾î ÀÖ½À´Ï´Ù. physicalDeviceObject = IoGetDeviceAttachmentBaseRef(diskDeviceObject); if (physicalDeviceObject != NULL) { // 4. Instance ID Á¶È¸ (¿¹: USB\VID_xxxx&PID_xxxx\Serial...) status = GetPnPDeviceId(physicalDeviceObject, DevicePropertyInstanceID, &pInstanceId); if (NT_SUCCESS(status) && pInstanceId != NULL) { KLogEx(DEBUG_TRACE_INFO, "[InstanceSetup] Vol=%p, InstanceID=%S\n", FltObjects->Volume, pInstanceId); // TODO: ¿©±â¼­ pInstanceId¸¦ ÄÁÅØ½ºÆ®¿¡ ÀúÀåÇϰųª Á¤Ã¥ È®Àο¡ »ç¿ë // »ç¿ë ÈÄ ¸Þ¸ð¸® ÇØÁ¦ ExFreePool(pInstanceId); } // [Áß¿ä] IoGetDeviceAttachmentBaseRef´Â ·¹ÆÛ·±½º Ä«¿îÆ®¸¦ Áõ°¡½ÃŰ¹Ç·Î ÇØÁ¦ Çʼö ObDereferenceObject(physicalDeviceObject); } // [Áß¿ä] FltGetDiskDeviceObjectµµ ·¹ÆÛ·±½º¸¦ Áõ°¡½ÃŰ¹Ç·Î ÇØÁ¦ Çʼö ObDereferenceObject(diskDeviceObject); } // InstanceSetupÀº º¸Åë STATUS_SUCCESS¸¦ ¸®ÅÏÇØ¾ß ÇÊÅͰ¡ ºÙ½À´Ï´Ù. // ID¸¦ ¸ø ±¸Çß´Ù°í ÇØ¼­ ÇÊÅÍ ºÎÂøÀ» ½ÇÆÐ½ÃųÁö´Â Á¤Ã¥¿¡ µû¶ó °áÁ¤Çϼ¼¿ä. return STATUS_SUCCESS; } */ /* NTSTATUS Bs1FltInstanceSetup ( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_SETUP_FLAGS Flags, _In_ DEVICE_TYPE VolumeDeviceType, _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType ) //Routine Description: // // This routine is called whenever a new instance is created on a volume. This // gives us a chance to decide if we need to attach to this volume or not. // // If this routine is not defined in the registration structure, automatic // instances are always created. // //Arguments: // // FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing // opaque handles to this filter, instance and its associated volume. // // Flags - Flags describing the reason for this attach request. // //Return Value: // //STATUS_SUCCESS - attach //STATUS_FLT_DO_NOT_ATTACH - do not attach { UCHAR volPropBuffer[sizeof(FLT_VOLUME_PROPERTIES) + 512]; PFLT_VOLUME_PROPERTIES volProp = (PFLT_VOLUME_PROPERTIES)volPropBuffer; PDEVICE_OBJECT devObj = NULL; WCHAR detail[512] = { 0, }; NTSTATUS status = STATUS_SUCCESS; ULONG retLen = 0; //UNICODE_STRING name = { 0, }; PUNICODE_STRING workingName = NULL; USHORT size = 0; PVOLUME_CONTEXT ctx = NULL; //UNICODE_STRING processImagePath = { 0, }; //HANDLE ProcessId = 0; //PVOLUME_CONTEXT volCtx = NULL; UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( Flags ); UNREFERENCED_PARAMETER( VolumeDeviceType ); UNREFERENCED_PARAMETER( VolumeFilesystemType ); PAGED_CODE(); ASSERT(FltObjects->Filter == g_cdsflt.Filter); KLogEx(DEBUG_TRACE_INFO, "Flags(%08x), vtype(%08x), vftype(%08x)\n", Flags, VolumeDeviceType, VolumeFilesystemType); if (VolumeFilesystemType == FLT_FSTYPE_UNKNOWN || VolumeFilesystemType == FLT_FSTYPE_LANMAN || VolumeFilesystemType == FLT_FSTYPE_WEBDAV ) { return STATUS_SUCCESS; } status = FltAllocateContext(FltObjects->Filter, FLT_VOLUME_CONTEXT, sizeof(VOLUME_CONTEXT), NonPagedPool, &ctx); if (!NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_ERROR, "FltAllocateContext Return Fail %x\n", status); return STATUS_SUCCESS; } try { RtlZeroMemory(ctx, sizeof(VOLUME_CONTEXT)); status = FltGetVolumeProperties(FltObjects->Volume, volProp, sizeof(volPropBuffer), &retLen); if (!NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_ERROR, "FltGetVolumeProperties Return Fail %x\n", status); leave; } status = FltGetDiskDeviceObject(FltObjects->Volume, &devObj); if (NT_SUCCESS(status)) { status = RtlVolumeDeviceToDosName(devObj, &ctx->name); ctx->device_type = devObj->DeviceType; if (devObj) ObDereferenceObject(devObj); KLogEx(DEBUG_TRACE_INFO, "DosName(%S)\n", ctx->name.Buffer); } if (!NT_SUCCESS(status)) { if (!MmIsAddressValid(ctx)) { KLogEx(DEBUG_TRACE_ERROR, "MmIsAddressValid Return Fail"); leave; } if (volProp->RealDeviceName.Length > 0) workingName = &volProp->RealDeviceName; else if (volProp->FileSystemDeviceName.Length > 0) workingName = &volProp->FileSystemDeviceName; else { status = STATUS_FLT_DO_NOT_ATTACH; KLogEx(DEBUG_TRACE_ERROR, "STATUS_FLT_DO_NOT_ATTACH -\n"); leave; } size = workingName->Length + sizeof(WCHAR); status = UStrNew(&ctx->name, size); if (!NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_ERROR, "IStrNew Return Fail %x, size(%d)\n", status, size); leave; } RtlCopyUnicodeString(&ctx->name, workingName); RtlAppendUnicodeToString(&ctx->name, L":"); } { IO_STATUS_BLOCK Iosb = { 0, }; ULONG64 buf[8] = { 0, }; PFILE_FS_VOLUME_INFORMATION volumeInfo = NULL; NTSTATUS querystatus = STATUS_SUCCESS; volumeInfo = (PFILE_FS_VOLUME_INFORMATION)buf; querystatus = FltQueryVolumeInformation(FltObjects->Instance, &Iosb, volumeInfo, sizeof(ULONG64) * 8, FileFsVolumeInformation); if (querystatus == STATUS_SUCCESS) { if (volumeInfo->VolumeLabelLength > 0 && volumeInfo->VolumeLabelLength < 100) { memcpy(ctx->wLabel, volumeInfo->VolumeLabel, volumeInfo->VolumeLabelLength); KLogEx(DEBUG_TRACE_INFO, "FltQueryVolumeInformation Return wLabel[%S]\n", ctx->wLabel); } } } GetVolumeProperties(FltObjects, ctx); if (ctx && ctx->name.Buffer) { // KLogEx (±¸Çöü¿¡ µû¶ó ´Ù¸£Áö¸¸, DbgPrint ȣȯÀ̶ó¸é %wZ »ç¿ë °¡´É) // ¸¸¾à KLogEx°¡ %wZ¸¦ Áö¿øÇÏÁö ¾Ê´Â´Ù¸é ¾Æ·¡ RtlStringCbPrintfW ¹æ½ÄÀ» ¸ÕÀú ½á¾ß ÇÔ //KLogEx(DEBUG_TRACE_INFO, // "Name(%wZ), BusType(%d), DeviceType(%d), VendorId(%.8hs), ProductId(%.16hs)\n", // &ctx->name, // .Buffer°¡ ¾Æ´Ï¶ó ±¸Á¶Ã¼ ÁÖ¼Ò¸¦ ³Ñ±è (%wZ) // ctx->bustype, // ctx->device_type, // ctx->vendorid ? ctx->vendorid : (PUCHAR)"NULL", // ctx->productid ? ctx->productid : (PUCHAR)"NULL" //); // RtlStringCbPrintfW (Ç¥ÁØ Ä¿³Î ÇÔ¼ö) RtlStringCbPrintfW( detail, sizeof(detail), L"Name(%wZ), BusType(%d), DeviceType(%d), VendorId(%.16hs), ProductId(%.16hs), Revision(%.20hs), Serial(%.20hs)", &ctx->name, // [ÇÙ½É] %s ´ë½Å %wZ »ç¿ë, Buffer ´ë½Å ±¸Á¶Ã¼ Æ÷ÀÎÅÍ Àü´Þ ctx->bustype, ctx->device_type, // ANSI ¹®ÀÚ¿­ÀÌ °íÁ¤±æÀÌ(¿¹: SCSI ½ºÆå)¶ó¸é ±æÀ̸¦ ¸í½Ã(%.8hs)ÇØÁÖ´Â °ÍÀÌ ¾ÈÀüÇÔ ctx->vendorid ? ctx->vendorid : (PUCHAR)"NULL", ctx->productid ? ctx->productid : (PUCHAR)"NULL", ctx->productrevisionlevel ? ctx->productrevisionlevel : (PUCHAR)"NULL", ctx->vendorspecific ? ctx->vendorspecific : (PUCHAR)"NULL" ); SetConnectLog(FltObjects, ctx->device_type, 0, 0, L"system", detail); } status = FltSetVolumeContext(FltObjects->Volume, FLT_SET_CONTEXT_KEEP_IF_EXISTS, ctx, NULL); KLogEx(DEBUG_TRACE_INFO, "state(%x)\n", status); if (status == STATUS_FLT_CONTEXT_ALREADY_DEFINED) status = STATUS_SUCCESS; } finally { if (ctx) FltReleaseContext(ctx); } return STATUS_SUCCESS; } */ NTSTATUS Bs1FltInstanceSetup( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_SETUP_FLAGS Flags, _In_ DEVICE_TYPE VolumeDeviceType, _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType ) { //UCHAR volPropBuffer[sizeof(FLT_VOLUME_PROPERTIES) + 512]; //PFLT_VOLUME_PROPERTIES volProp = (PFLT_VOLUME_PROPERTIES)volPropBuffer; //PUNICODE_STRING workingName = NULL; //USHORT newNameSize = 0; //ULONG retLen = 0; //PFLT_GENERIC_WORKITEM workItem = NULL; PDEVICE_OBJECT devObj = NULL; WCHAR detail[1024] = { 0, }; NTSTATUS status = STATUS_SUCCESS; PVOLUME_CONTEXT ctx = NULL; PFULL_DISK_INFO diskInfo = NULL; ; UCHAR labelBuf[sizeof(FILE_FS_VOLUME_INFORMATION) + 256] = { 0 }; PFILE_FS_VOLUME_INFORMATION volInfo = (PFILE_FS_VOLUME_INFORMATION)labelBuf; IO_STATUS_BLOCK Iosb = { 0, }; UNREFERENCED_PARAMETER(Flags); UNREFERENCED_PARAMETER(VolumeDeviceType); UNREFERENCED_PARAMETER(VolumeFilesystemType); PAGED_CODE(); // 1. ´ë»ó ÆÄÀÏ ½Ã½ºÅÛ ÇÊÅ͸µ if (VolumeFilesystemType == FLT_FSTYPE_UNKNOWN || VolumeFilesystemType == FLT_FSTYPE_LANMAN || VolumeFilesystemType == FLT_FSTYPE_WEBDAV) { return STATUS_SUCCESS; } if(VolumeDeviceType != FILE_DEVICE_DISK_FILE_SYSTEM) return STATUS_SUCCESS; status = FltAllocateContext(FltObjects->Filter, FLT_VOLUME_CONTEXT, sizeof(VOLUME_CONTEXT), NonPagedPool, &ctx); if (!NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_ERROR, "FltAllocateContext Failed %x\n", status); return status; } RtlZeroMemory(ctx, sizeof(VOLUME_CONTEXT)); __try { diskInfo = (PFULL_DISK_INFO)ExAllocatePoolWithTag(NonPagedPool, sizeof(FULL_DISK_INFO), _ALLOC_TAG); if (diskInfo) { RtlZeroMemory(diskInfo, sizeof(FULL_DISK_INFO)); // --------------------------------------------------------------------- // µð½ºÅ© Á¤º¸ »ó¼¼ ¼öÁý // --------------------------------------------------------------------- status = FltGetDiskDeviceObject(FltObjects->Volume, &devObj); if (NT_SUCCESS(status) && devObj != NULL) { ctx->device_type = devObj->DeviceType; // Çϵå¿þ¾î »ó¼¼ Á¤º¸ ¼öÁý (BusType, Vendor, Product, Serial...) // ÀÌ ÇÔ¼ö´Â ³»ºÎÀûÀ¸·Î PDO¿Í TopDevice¸¦ ±¸ºÐÇÏ¿© Á¤º¸¸¦ ±Ü¾î¿É´Ï´Ù. CollectAllDiskInfo(devObj, diskInfo); ctx->bustype = diskInfo->BusType; RtlStringCbCopyA((PCHAR)ctx->vendorid, sizeof(ctx->vendorid), diskInfo->VendorId); RtlStringCbCopyA((PCHAR)ctx->productid, sizeof(ctx->productid), diskInfo->ProductId); RtlStringCbCopyA((PCHAR)ctx->productrevisionlevel, sizeof(ctx->productrevisionlevel), diskInfo->Productrevisionlevel); // ¿¹½Ã RtlStringCbCopyA((PCHAR)ctx->vendorspecific, sizeof(ctx->vendorspecific), diskInfo->SerialNumber); status = RtlVolumeDeviceToDosName(devObj, &ctx->name); // µð¹ÙÀ̽º °´Ã¼ ÇØÁ¦ ObDereferenceObject(devObj); KLogEx(DEBUG_TRACE_INFO, "DEBUG_TRACE_INFO, devObj(%p), ctx->vendorid(%s), ctx->productid(%s)\n", devObj, (PCHAR)ctx->vendorid, (PCHAR)ctx->productid); if (devObj && devObj->DriverObject) { UNICODE_STRING driverName = devObj->DriverObject->DriverName; KLogEx(DEBUG_TRACE_INFO, "Volume Driver Name: %wZ\n", &driverName); // ƯÁ¤ µå¶óÀ̹ö À̸§ÀÌ Æ÷ÇԵǾî ÀÖ´ÂÁö È®ÀÎ if (wcsstr(driverName.Buffer, L"Secret") || wcsstr(driverName.Buffer, L"CNTDrive")) { KLogEx(DEBUG_TRACE_INFO, "Secretberry Virtual Drive Detected!\n"); // °¡»ó µå¶óÀ̺êÀÓÀÌ È®ÀεǸé, VendorID/ProductID¸¦ °­Á¦·Î ¼³Á¤ RtlStringCbCopyA((PCHAR)ctx->vendorid, sizeof(ctx->vendorid), "SecretBerry"); RtlStringCbCopyA((PCHAR)ctx->productid, sizeof(ctx->productid), "VirtualDisk"); EscapeJsonStringW(driverName.Buffer, diskInfo->Description, sizeof(diskInfo->Description)); } } } } else { KLogEx(DEBUG_TRACE_ERROR, "alloc fail\n"); } // --------------------------------------------------------------------- // 4. À̸§ ȹµæ ½ÇÆÐ ½Ã Fallback (Volume Properties ÀÌ¿ë) // --------------------------------------------------------------------- // ctx->name.buffer°¡ nullÀ̸é À§¿¡¼­ dos À̸§À» ¸ø ¾òÀº °ÍÀÓ //if (ctx->name.Buffer == NULL) //{ // // volume properties °¡Á®¿À±â // status = FltGetVolumeProperties(FltObjects->Volume, volProp, sizeof(volPropBuffer), &retLen); // // if (NT_SUCCESS(status)) // { // if (volProp->RealDeviceName.Length > 0) // workingName = &volProp->RealDeviceName; // else if (volProp->FileSystemDeviceName.Length > 0) // workingName = &volProp->FileSystemDeviceName; // } // if (workingName != NULL) // { // // À̸§ ÇÒ´ç ¹× º¹»ç (ustrnew°¡ ¸Þ¸ð¸® ÇÒ´ç ÇÔ¼ö¶ó°í °¡Á¤) // // ¿¹: \device\harddiskvolume1 // newNameSize = workingName->Length + sizeof(WCHAR); // null °ø°£ Æ÷ÇÔ // // ÁÖÀÇ: ustrnew ³»ºÎ ±¸ÇöÀ» ¸ð¸£¹Ç·Î Ç¥ÁØ ·ÎÁ÷À¸·Î ¼³¸í // // ctx->name.buffer = exallocatepool...(newnamesize); // // ¿©±â¼­´Â »ç¿ëÀÚÀÇ ustrnew È£Ãâ À¯Áö // status = UStrNew(&ctx->name, newNameSize); // if (NT_SUCCESS(status)) // { // RtlCopyUnicodeString(&ctx->name, workingName); // } // } // else // { // KLogEx(DEBUG_TRACE_ERROR, "failed to get volume name. do not attach.\n"); // //return status_flt_do_not_attach; // } //} // --------------------------------------------------------------------- // º¼·ý ·¹ÀÌºí °¡Á®¿À±â (Label) // --------------------------------------------------------------------- { status = FltQueryVolumeInformation(FltObjects->Instance, &Iosb, volInfo, sizeof(labelBuf), FileFsVolumeInformation); if (NT_SUCCESS(status)) { ULONG copyLen = (volInfo->VolumeLabelLength < sizeof(ctx->wLabel) - sizeof(WCHAR)) ? volInfo->VolumeLabelLength : sizeof(ctx->wLabel) - sizeof(WCHAR); RtlCopyMemory(ctx->wLabel, volInfo->VolumeLabel, copyLen); ctx->wLabel[copyLen / sizeof(WCHAR)] = L'\0'; // Null Terminate KLogEx(DEBUG_TRACE_INFO, "Volume Driver Name: %S\n", ctx->wLabel); } } if (ctx->name.Buffer) { FILE_FS_SIZE_INFORMATION sizeInfo; // ULONG lengthReturned; LONGLONG totalSizeBytes = 0; LONGLONG freeSizeBytes = 0; LONGLONG totaldecimalPart = 0; LONGLONG freedecimalPart = 0; status = FltQueryVolumeInformation( FltObjects->Instance, // ÇÊÅÍ ÀνºÅϽº &Iosb, // IO_STATUS_BLOCK (±âÁ¸¿¡ ¼±¾ðµÈ º¯¼ö »ç¿ë) &sizeInfo, // °á°ú¸¦ ¹ÞÀ» ±¸Á¶Ã¼ sizeof(sizeInfo), // ±¸Á¶Ã¼ Å©±â FileFsSizeInformation // ¡Ú Å©±â Á¤º¸¸¦ ´Þ¶ó°í ¿äû ); if (NT_SUCCESS(status)) { // 1. Àüü µð½ºÅ© Å©±â °è»ê (Allocation Units * SectorsPerUnit * BytesPerSector) totalSizeBytes = sizeInfo.TotalAllocationUnits.QuadPart * sizeInfo.SectorsPerAllocationUnit * sizeInfo.BytesPerSector; // 2. »ç¿ë °¡´ÉÇÑ ¿©À¯ °ø°£ °è»ê freeSizeBytes = sizeInfo.AvailableAllocationUnits.QuadPart * sizeInfo.SectorsPerAllocationUnit * sizeInfo.BytesPerSector; KLogEx(DEBUG_TRACE_INFO, "Total Size: %lld Bytes, Free: %lld Bytes\n", totalSizeBytes, freeSizeBytes); } else { KLogEx(DEBUG_TRACE_ERROR, "FltQueryVolumeInformation Failed: %x\n", status); } // { // VOLUME_DETAILS volDetails; // // 1. ÅëÇÕ ÇÔ¼ö È£Ãâ // status = GetAllVolumeDetails(FltObjects->Instance, &volDetails); // if (NT_SUCCESS(status)) // { // // 2. ·Î±× Ãâ·Â // KLogEx(DEBUG_TRACE_INFO, "=== Volume Details ===\n"); // KLogEx(DEBUG_TRACE_INFO, " Name: %ws (FS: %ws), VolumSerial : %u\n", volDetails.VolumeLabel, volDetails.FileSystemName, volDetails.VolumeSerialNumber); // //KLogEx(DEBUG_TRACE_INFO, " Guid : %ws\n", volDetails.VolumeGuid); // KLogEx(DEBUG_TRACE_INFO, " Size: %lld / %lld Bytes\n", volDetails.FreeBytes, volDetails.TotalBytes); // KLogEx(DEBUG_TRACE_INFO, " Serial: 0x%08X\n", volDetails.VolumeSerialNumber); // KLogEx(DEBUG_TRACE_INFO, " Sector: Phy(%u), Log(%u)\n", volDetails.PhysicalBytesPerSector, volDetails.LogicalBytesPerSector); // KLogEx(DEBUG_TRACE_INFO, " DeviceType(%u), DeviceCharacteristics(%u), FileSystemAttributes(%u)\n", // volDetails.DeviceType, volDetails.DeviceCharacteristics, volDetails.FileSystemAttributes); // // // ReadOnly ¿©ºÎ È®ÀÎ ¿¹½Ã // if (volDetails.FileSystemAttributes & FILE_READ_ONLY_VOLUME) // { // DbgPrint(" -> Warning: Read-Only Volume!\n"); // } // } // else // { //KLogEx(DEBUG_TRACE_INFO, "GetAllVolumeDetails Failed: %x\n", status); // } // } totalSizeBytes = totalSizeBytes / ONEGB; totaldecimalPart = ((totalSizeBytes % ONEGB) * 100) / ONEGB; freeSizeBytes = freeSizeBytes / ONEGB; freedecimalPart = ((freeSizeBytes % ONEGB) * 100) / ONEGB; status = RtlStringCbPrintfW( detail, sizeof(detail), L"{" L"\"name\": \"%wZ\", " // %s -> %wZ (¾ÈÀü¼º Çâ»ó) L"\"freeGB\": \"%lld.%02lld\", " L"\"totalGB\": \"%lld.%02lld\", " L"\"vid\": \"%.16hs\", " L"\"pid\": \"%.16hs\", " L"\"rev\": \"%.20hs\", " L"\"serial\": \"%.20hs\", " L"\"instanceId\": \"%s\", " L"\"enumerator\": \"%s\", " L"\"friendlyName\": \"%s\", " L"\"hardwareId\": \"%s\", " L"\"description\": \"%s\"" //L"\"parentId\": \"%s\"" L"}", &ctx->name, freeSizeBytes, freedecimalPart, totalSizeBytes, totaldecimalPart, ctx->vendorid, ctx->productid, ctx->productrevisionlevel, ctx->vendorspecific, diskInfo->InstanceId, diskInfo->EnumeratorName, diskInfo->FriendlyName, diskInfo->HardwareId, diskInfo->Description // diskInfo->ParentId ); if (!NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_ERROR, "RtlStringCbPrintfW failed: %x\n", status); } else { KLogEx(DEBUG_TRACE_INFO, "%S\n", detail); } if (NT_SUCCESS(status)) { SetConnectLog(FltObjects, VolumeDeviceType, VolumeFilesystemType, 0, ctx->name.Buffer, L"System", detail); } } else { } status = FltSetVolumeContext(FltObjects->Volume, FLT_SET_CONTEXT_KEEP_IF_EXISTS, ctx, NULL); //workItem = FltAllocateGenericWorkItem(); //if (workItem) { // // Volume °´Ã¼ ÂüÁ¶ Ä«¿îÆ® Áõ°¡ (ÀÛ¾÷ÀÚ ½º·¹µå¿¡¼­ »ç¿ëÇϱâ À§ÇØ) // FltObjectReference(FltObjects->Volume); // FltQueueGenericWorkItem( // workItem, // FltObjects->Instance, // SafeQueryIdRoutine, // À§¿¡¼­ ¸¸µç ÇÔ¼ö // DelayedWorkQueue, // FltObjects->Volume // ); //} if (status == STATUS_FLT_CONTEXT_ALREADY_DEFINED) status = STATUS_SUCCESS; } __finally { if(diskInfo) { ExFreePoolWithTag(diskInfo, _ALLOC_TAG); } if (ctx) { FltReleaseContext(ctx); } } return STATUS_SUCCESS; } VOID Bs1FltCleanupVolumeContext( __in PFLT_CONTEXT Context, __in FLT_CONTEXT_TYPE ContextType ) { PVOLUME_CONTEXT ctx = (PVOLUME_CONTEXT)Context; PAGED_CODE(); UNREFERENCED_PARAMETER(ContextType); if (ContextType != FLT_VOLUME_CONTEXT) return; if (!MmIsAddressValid(ctx)) return; if (!MmIsAddressValid(ctx->name.Buffer)) return; if (ctx->name.Buffer != NULL) { KLogEx(DEBUG_TRACE_INFO, "ctx->name(%S)\n", ctx->name.Buffer); ExFreePool(ctx->name.Buffer); ctx->name.Buffer = NULL; } } NTSTATUS Bs1FltInstanceQueryTeardown ( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags ) /*++ Routine Description: This is called when an instance is being manually deleted by a call to FltDetachVolume or FilterDetach thereby giving us a chance to fail that detach request. If this routine is not defined in the registration structure, explicit detach requests via FltDetachVolume or FilterDetach will always be failed. Arguments: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance and its associated volume. Flags - Indicating where this detach request came from. Return Value: Returns the status of this operation. --*/ { UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); KLogEx(DEBUG_TRACE_INFO, "cdsflt!cdsfltInstanceQueryTeardown: Entered\n"); return STATUS_SUCCESS; } VOID Bs1FltInstanceTeardownStart ( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags ) /*++ Routine Description: This routine is called at the start of instance teardown. Arguments: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance and its associated volume. Flags - Reason why this instance is being deleted. Return Value: None. --*/ { UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); KLogEx(DEBUG_TRACE_INFO, "cdsflt!cdsfltInstanceTeardownStart: Entered\n"); } VOID Bs1FltInstanceTeardownComplete ( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags ) /*++ Routine Description: This routine is called at the end of instance teardown. Arguments: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance and its associated volume. Flags - Reason why this instance is being deleted. Return Value: None. --*/ { UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); KLogEx(DEBUG_TRACE_INFO, "Bs1FltInstanceTeardownComplete: Entered\n" ); } /************************************************************************* MiniFilter initialization and unload routines. *************************************************************************/ NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ Routine Description: This is the initialization routine for this miniFilter driver. This registers with FltMgr and initializes all global data structures. Arguments: DriverObject - Pointer to driver object created by the system to represent this driver. RegistryPath - Unicode string identifying where the parameters for this driver are located in the registry. Return Value: Routine can return non success error codes. --*/ { NTSTATUS status; PSECURITY_DESCRIPTOR sd; UNICODE_STRING uni; OBJECT_ATTRIBUTES oa; UNREFERENCED_PARAMETER(RegistryPath); g_DebugLevel = DEBUG_TRACE_INFO; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%s:%s : Entered RegPath(%S)(%d)", DRIVERNAMEA, __FUNCTION__, RegistryPath->Buffer, RegistryPath->Length); RtlZeroMemory(&g_bs1Flt, sizeof(g_bs1Flt)); if (!NT_SUCCESS(USetConfiguration(RegistryPath))) { g_DebugLevel = 0; } //g_DebugLevel = DEBUG_TRACE_ALL; // // Register with FltMgr to tell it our callback routines // KLogEx(DEBUG_TRACE_INFO, "DebugLevel(%x)\n", g_DebugLevel); status = FltRegisterFilter(DriverObject, &FilterRegistration, &g_bs1Flt.Filter); FLT_ASSERT(NT_SUCCESS(status)); if (!NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_ERROR, "FltRegisterFilter status(%08x)\n", status); return status; } // // Start filtering i/o // USetProcessNameOffset(); g_bs1Flt.OsVersion = UGetKernelVersion(); g_bs1Flt.DriverObject = DriverObject; g_bs1Flt.LogType = LOG_ALL; RtlInitUnicodeString(&uni, BS1FLT_PORTNAME); status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS); if (!NT_SUCCESS(status)) goto $cleanup; InitializeObjectAttributes(&oa, &uni, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, sd); status = FltCreateCommunicationPort(g_bs1Flt.Filter, &g_bs1Flt.ServerPort, &oa, NULL, Bs1FltPortConnect, Bs1FltPortDisconnect, Bs1FltMssageProc, 10); FltFreeSecurityDescriptor(sd); if (!NT_SUCCESS(status)) goto $cleanup; g_bs1Flt.IsAttached = FALSE; g_bs1Flt.ClientPort = NULL; g_bs1Flt.IsShareWatched = FALSE; g_bs1Flt.IsFolderProtect = FALSE; g_bs1Flt.IsAttached = FALSE; g_bs1Flt.IsDeviceProtect = FALSE; Bs1FltPortInit(); Initlist(); InitProcessNotify(); PgInitialize(); Initlog(); Initpolicy(); status = FltStartFiltering(g_bs1Flt.Filter); if (!NT_SUCCESS(status)) { FltCloseCommunicationPort(g_bs1Flt.ServerPort); goto $cleanup; } PgAddPid(0, PG_PID_ALLOW); PgAddPid(4, PG_PID_ALLOW); PgAddPid(8, PG_PID_ALLOW); KLogEx(DEBUG_TRACE_INFO, "Success\n"); return STATUS_SUCCESS; $cleanup: KLogEx(DEBUG_TRACE_ERROR, "status(%08x)\n", status); FltUnregisterFilter(g_bs1Flt.Filter); return status; } NTSTATUS Bs1FltUnload ( _In_ FLT_FILTER_UNLOAD_FLAGS Flags ) /*++ Routine Description: This is the unload routine for this miniFilter driver. This is called when the minifilter is about to be unloaded. We can fail this unload request if this is not a mandatory unload indicated by the Flags parameter. Arguments: Flags - Indicating if this is a mandatory unload. Return Value: Returns STATUS_SUCCESS. --*/ { UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); KLogEx(DEBUG_TRACE_INFO, " Entered\n"); if (Flags & FLTFL_FILTER_UNLOAD_MANDATORY) { // Á¤¸® ÀÛ¾÷ ¼öÇà ÈÄ ¼º°ø ¸®ÅÏ goto $Success; } if (g_IsUnloadAllowed == FALSE) { KLogEx(DEBUG_TRACE_INFO, "Unload blocked by Self-Defense policy.\n"); // ÀÌ »óÅ Äڵ带 ¸®ÅÏÇϸé fltmc unload°¡ ½ÇÆÐÇÔ return STATUS_FLT_DO_NOT_DETACH; } $Success: if (g_bs1Flt.ServerPort != NULL) { FltCloseCommunicationPort(g_bs1Flt.ServerPort); g_bs1Flt.ServerPort = NULL; } //Bs1FltPortUnload(); g_bs1Flt.IsShareWatched = FALSE; g_bs1Flt.IsFolderProtect = FALSE; g_bs1Flt.IsAttached = FALSE; g_bs1Flt.IsDeviceProtect = FALSE; // if(g_RegistryPath.Buffer) // PBStrFree(&g_RegistryPath); CleanupProcessNotify(); CleanupFilelist(); CleanupPathlist(); CleanupProcesslist(); CleanupProcessProtectList(); PgReset(); CleanupUsbDiskExceptionList(); StopRegFlt(); UnInstallProcessProtect(); #ifdef USB_PORT_HOOK USBIrpHookCleanup(); BlueToothIrpHookCleanup(); MtpIrpHookCleanup(); CleanupUsbPortExceptionList(); #endif if (g_bs1Flt.Filter != NULL) { FltUnregisterFilter(g_bs1Flt.Filter); g_bs1Flt.Filter = NULL; } Cleanuplog(); return STATUS_SUCCESS; }