首页
论坛
专栏
课程

[求助]想用minifilter实现u盘的禁用或只读,该怎么着手?

2019-4-5 22:03 2359

[求助]想用minifilter实现u盘的禁用或只读,该怎么着手?

2019-4-5 22:03
2359
网上找的要么是wdm的驱动方式来做, 我想用NT的, 就是一开机就加载的, 搜到了minifilter, 但都是禁止文件访问的, 没有只读的例子, 不知道 怎么判断一个路径是U盘里的。
好不容易在github上找到这个代码,尼玛硬生生看不懂啊https://github.com/surajfale/passthrough-minifilter-driver


[推荐]看雪企服平台,提供安全分析、定制项目开发、APP等级保护、渗透测试等安全服务!

最后于 2019-4-5 23:53 被wumnkx编辑 ,原因:
上一主题 下一主题
最新回复 (56)
wumnkx 2019-4-7 00:50
2
0
现在已经实现了功能,禁用是没问题的, 只读有点问题, 新建空txt文件可以成功, 写入信息保存时会提示拒绝访问然后弹出另存为, 我想在只读时任何覆盖操作都提示一下就完了该这么做呢? 下面是源码


#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>


#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")

#define SETTINGS_AUTORUNINF 0x01
#define SETTINGS_EXECUTABLES SETTINGS_AUTORUNINF << 1
#define SETTINGS_BLOCK SETTINGS_AUTORUNINF << 2
#define SETTINGS_READONLY SETTINGS_AUTORUNINF << 3
#define SETTINGS_NOFILEEXECUTE SETTINGS_AUTORUNINF << 4

#define DENY_CREATE                        1
#define DENY_WRITE                        1 << 1
#define DENY_INFORMATHION        1 << 2



PFLT_FILTER Filter;



#define pasthrough_INSTANCE_CONTEXT_TAG 'cIxC'

typedef struct _pasthrough_INSTANCE_CONTEXT {
       BOOLEAN ucFlags;
} pasthrough_INSTANCE_CONTEXT, *Ppasthrough_INSTANCE_CONTEXT;

#define pasthrough_INSTANCE_CONTEXT_SIZE sizeof(pasthrough_INSTANCE_CONTEXT)

NTSTATUS DriverEntry(__in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath);
NTSTATUS pasthroughUnload(__in FLT_FILTER_UNLOAD_FLAGS Flags);
NTSTATUS pasthroughQueryTeardown(__in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags);
FLT_PREOP_CALLBACK_STATUS pasthroughPreCreate(__inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __deref_out_opt PVOID *CompletionContext);
FLT_PREOP_CALLBACK_STATUS pasthroughPreWrite(__inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __deref_out_opt PVOID *CompletionContext);
FLT_PREOP_CALLBACK_STATUS pasthroughPreSetInformation(__inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __deref_out_opt PVOID *CompletionContext);
NTSTATUS pasthroughInstanceSetup(__in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_SETUP_FLAGS Flags, __in DEVICE_TYPE VolumeDeviceType, __in FLT_FILESYSTEM_TYPE VolumeFilesystemType);
VOID ReadRegistrySettings(__in PUNICODE_STRING RegistryPath);
VOID pasthroughContextCleanup(__in PFLT_CONTEXT Context, __in FLT_CONTEXT_TYPE ContextType);
VOID pasthroughInstanceTeardownComplete(__in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_TEARDOWN_FLAGS Flags);



//  Assign text sections for each routine.

#ifdef ALLOC_PRAGMA
       #pragma alloc_text(INIT, DriverEntry)
       #pragma alloc_text(PAGE, pasthroughUnload)
       #pragma alloc_text(PAGE, pasthroughInstanceSetup)
       #pragma alloc_text(PAGE, pasthroughPreCreate)
       #pragma alloc_text(PAGE, pasthroughPreWrite)
       #pragma alloc_text(PAGE, pasthroughPreSetInformation)
       #pragma alloc_text(PAGE, pasthroughContextCleanup)
       #pragma alloc_text(PAGE, pasthroughInstanceTeardownComplete)
#endif

NTSTATUS DriverEntry(__in PDRIVER_OBJECT pDO, __in PUNICODE_STRING pusRegistryPath)
{
       NTSTATUS iNTStatus;

       const FLT_OPERATION_REGISTRATION Callbacks[] = {
               {IRP_MJ_CREATE, 0, pasthroughPreCreate, NULL},
               {IRP_MJ_SET_INFORMATION, 0, pasthroughPreSetInformation, NULL},
               {IRP_MJ_WRITE, 0, pasthroughPreWrite, NULL},
               {IRP_MJ_OPERATION_END}
       };

       const FLT_CONTEXT_REGISTRATION contextRegistration[] = {
               {FLT_INSTANCE_CONTEXT, 0, pasthroughContextCleanup, pasthrough_INSTANCE_CONTEXT_SIZE, pasthrough_INSTANCE_CONTEXT_TAG},
               {FLT_CONTEXT_END}
       };

       const FLT_REGISTRATION FilterRegistration = {
               sizeof(FLT_REGISTRATION),         //  Size
               FLT_REGISTRATION_VERSION,           //  Version
               0,                                  //  Flags
               contextRegistration,                //  Context Registration.
               Callbacks,                          //  Operation callbacks
               pasthroughUnload,                      //  FilterUnload
               pasthroughInstanceSetup,               //  InstanceSetup
               NULL,                             //  InstanceQueryTeardown
               NULL,                             //  InstanceTeardownStart
               pasthroughInstanceTeardownComplete,      //  InstanceTeardownComplete
               NULL,                               //  GenerateFileName
               NULL,                               //  GenerateDestinationFileName
               NULL                                //  NormalizeNameComponent
       };



       iNTStatus = FltRegisterFilter(pDO, &FilterRegistration, &Filter);

       if (!NT_SUCCESS(iNTStatus))
               return iNTStatus;

       iNTStatus = FltStartFiltering(Filter);

       if (NT_SUCCESS(iNTStatus))
               return STATUS_SUCCESS;

       FltUnregisterFilter(Filter);

       return iNTStatus;
}

NTSTATUS pasthroughUnload(__in FLT_FILTER_UNLOAD_FLAGS iFFUF)
{
       UNREFERENCED_PARAMETER(iFFUF);
        
        PAGED_CODE();


       FltUnregisterFilter(Filter);

       return STATUS_SUCCESS;
}

int VolumeToDosName(__in PFLT_VOLUME pFV)
{
       PDEVICE_OBJECT pDO = NULL;
       UNICODE_STRING usDosName;
       NTSTATUS iNTStatus;
       int iReturn = 0;

       iNTStatus = FltGetDiskDeviceObject(pFV, &pDO);
       if (NT_SUCCESS(iNTStatus))
       {
               iNTStatus = IoVolumeDeviceToDosName(pDO, &usDosName);
               if (NT_SUCCESS(iNTStatus))
               {
                       iReturn = RtlUpcaseUnicodeChar(usDosName.Buffer[0]);
                       ExFreePool(usDosName.Buffer);
               }
       }

       return iReturn;
}

NTSTATUS pasthroughInstanceSetup(__in PCFLT_RELATED_OBJECTS pFRO, __in FLT_INSTANCE_SETUP_FLAGS iFISF, __in DEVICE_TYPE iDT, __in FLT_FILESYSTEM_TYPE iFFT)
{
       UCHAR ucBuffer[sizeof(FLT_VOLUME_PROPERTIES)+512];
       PFLT_VOLUME_PROPERTIES pFVP = (PFLT_VOLUME_PROPERTIES)ucBuffer;
       ULONG ulLengthReceived;
       NTSTATUS iNTStatus;
       NTSTATUS iNTStatusReturn;
       Ppasthrough_INSTANCE_CONTEXT pAIC = NULL;
       int iDrive;

       UNREFERENCED_PARAMETER(iFISF);
       UNREFERENCED_PARAMETER(iFFT);

       ulLengthReceived = 0;

       //ReadRegistrySettings(NULL);

       PAGED_CODE();

       iDrive = VolumeToDosName(pFRO->Volume);

       iNTStatus = FltAllocateContext(pFRO->Filter, FLT_INSTANCE_CONTEXT, pasthrough_INSTANCE_CONTEXT_SIZE, NonPagedPool, &pAIC);

       if (!NT_SUCCESS(iNTStatus))
       {
               if (pAIC != NULL)
                       FltReleaseContext(pAIC);
               return STATUS_FLT_DO_NOT_ATTACH;
       }

       
       DbgPrint("pasthrough: pasthroughInstanceSetup iDT: %d", iDT);
                       
       switch(iDT)
         {
                case FILE_DEVICE_DISK_FILE_SYSTEM: 
                       
                       if (NT_SUCCESS(FltGetVolumeProperties(pFRO->Volume, pFVP, sizeof(ucBuffer), &ulLengthReceived)))
                       {
                               DbgPrint("pasthrough: pasthroughInstanceSetup FILE_DEVICE_DISK_FILE_SYSTEM: RealDeviceName: %wZ DeviceCharacteristics: %08x", &pFVP->RealDeviceName, pFVP->DeviceCharacteristics);
                               if (pFVP->DeviceCharacteristics & FILE_REMOVABLE_MEDIA)
                               {
                                       pAIC->ucFlags = TRUE;
                                       iNTStatusReturn = STATUS_SUCCESS;
                                       
                               }
                       }
                       break;

                  default:
                          iNTStatusReturn = STATUS_FLT_DO_NOT_ATTACH;
         }
       
                       
       
       DbgPrint("pasthrough: pasthroughInstanceSetup iNTStatusReturn: %d", iNTStatusReturn);

       iNTStatus = FltSetInstanceContext(pFRO->Instance, FLT_SET_CONTEXT_KEEP_IF_EXISTS, pAIC, NULL);

       if (!NT_SUCCESS(iNTStatus))
       {
               if (pAIC != NULL)
                       FltReleaseContext(pAIC);
               return STATUS_FLT_DO_NOT_ATTACH;
       }

       if (pAIC != NULL)
               FltReleaseContext(pAIC);

       if (NT_SUCCESS(iNTStatusReturn))
       {
               if (ulLengthReceived <= 0)
                       FltGetVolumeProperties(pFRO->Volume, pFVP, sizeof(ucBuffer), &ulLengthReceived);
               DbgPrint("pasthrough: Instance setup iDT: %d RealDeviceName: %wZ DeviceCharacteristics: %08x Dosname: %c", iDT, &pFVP->RealDeviceName, pFVP->DeviceCharacteristics, iDrive);
       }

       return iNTStatusReturn;
}


PKEY_VALUE_PARTIAL_INFORMATION QueryRegistryValue(const wchar_t* regPath, const wchar_t* regKey)
{
       HANDLE KeyHandle = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    UNICODE_STRING KeyPath;
    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING SourceKeyName;
    PKEY_VALUE_PARTIAL_INFORMATION AcKeyInfo = NULL;
    KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
    ULONG Length = 0;

       RtlInitUnicodeString(&KeyPath, regPath);
       RtlInitUnicodeString(&SourceKeyName, regKey);
       DbgPrint("pasthrough: KeyPath = %wZ, SourceKeyName = %wZ\n", &KeyPath, &SourceKeyName);
    //初始化OBJECT_ATTRIBUTES结构体
    InitializeObjectAttributes(
        &ObjectAttributes,
        &KeyPath,
        OBJ_CASE_INSENSITIVE,
        NULL,
        NULL);

    //打开注册表键
    Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
    if (!NT_SUCCESS(Status))
    {
        DbgPrint("pasthrough: Open the Key Handle Faild!! -- %#X\n", Status);
        return AcKeyInfo;
    }

    //第一次读取注册表键值探测数据大小
    Status = ZwQueryValueKey(
        KeyHandle,
        &SourceKeyName,
        KeyValuePartialInformation,
        &KeyInfo,
        sizeof(KEY_VALUE_PARTIAL_INFORMATION),
        &Length);   
    if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL)
    {
        DbgPrint("pasthrough: 读取SystemRoot键值失败!! - %#X\n", Status);
        ZwClose(KeyHandle);
        return AcKeyInfo;
    }

    //根据上面探测的注册表键值大小动态分配内存
    AcKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, Length, "tag2");
    if (NULL == AcKeyInfo)
    {
        DbgPrint("pasthrough: 在分配保存Key键值的内存空间时失败!!");
        ZwClose(KeyHandle);
        Status = STATUS_INSUFFICIENT_RESOURCES;
        return AcKeyInfo;
    }

    //再次读取注册表键值
    Status = ZwQueryValueKey(
    KeyHandle,
    &SourceKeyName,
    KeyValuePartialInformation,
    AcKeyInfo,
    Length,
    &Length);
    if (!NT_SUCCESS(Status))
    {
        DbgPrint("pasthrough: 读取SystemRoot键值失败!! - %#X\n", Status);
        ZwClose(KeyHandle);
        ExFreePool(AcKeyInfo);
        return AcKeyInfo;
    }
       ZwClose(KeyHandle);
       return AcKeyInfo;
}


VOID UnicodeToChar(PUNICODE_STRING dst, char *src)
{
       ANSI_STRING string;
       RtlUnicodeStringToAnsiString(&string,dst, TRUE);
       strcpy(src,string.Buffer);
       RtlFreeAnsiString(&string);
}

int QueryUSBRegInfo(PCFLT_RELATED_OBJECTS pFRO)
{
       int option = 0;
       char VolumeName[2] = {0};
       UNICODE_STRING u;
       char RegVolimeValue[100] = {0};
       PKEY_VALUE_PARTIAL_INFORMATION AcOptionInfo = NULL;
       PULONG pulValue = NULL;
       PKEY_VALUE_PARTIAL_INFORMATION AcKeyInfo = QueryRegistryValue(L"\\Registry\\Machine\\Software\\USBInfo", L"Volume");
       if (NULL == AcKeyInfo) {
               DbgPrint("pasthrough QueryUSBRegInfo AcKeyInfo == NULL");
               return option;
       }
       if (AcKeyInfo->Type != REG_SZ) {
               DbgPrint("pasthrough QueryUSBRegInfo AcKeyInfo->Type != REG_SZ");
               ExFreePool(AcKeyInfo);
               return option;
       }
       
       VolumeName[0] = (char)VolumeToDosName(pFRO->Volume);
       DbgPrint("pasthrough QueryUSBRegInfo VolimeName = %s\n", VolumeName);
       RtlInitUnicodeString(&u, AcKeyInfo->Data);
       DbgPrint("pasthrough QueryUSBRegInfo u = %wZ\n", &u);
       ExFreePool(AcKeyInfo);
       UnicodeToChar(&u, RegVolimeValue);
       DbgPrint("pasthrough QueryUSBRegInfo RegVolimeValue = %s\n", RegVolimeValue);
       if (strstr(RegVolimeValue, VolumeName) == NULL) {
               return option;
       }
       AcOptionInfo = QueryRegistryValue(L"\\Registry\\Machine\\Software\\USBInfo", L"Option");
       if (NULL == AcOptionInfo) {
               DbgPrint("pasthrough QueryUSBRegInfo NULL == AcOptionInfo\n");
               return option;
       }
       if (AcOptionInfo->Type != REG_DWORD || AcOptionInfo->DataLength != sizeof(ULONG)) {
               DbgPrint("pasthrough QueryUSBRegInfo AcOptionInfo type or length error\n");
               ExFreePool(AcOptionInfo);
               return option;
       }
       pulValue = (PULONG) AcOptionInfo->Data;
       option = (int)*pulValue;
       DbgPrint("pasthrough QueryUSBRegInfo option  %d\n", option);
       ExFreePool(AcOptionInfo);
       return option;
}

FLT_PREOP_CALLBACK_STATUS pasthroughPreCreate(__inout PFLT_CALLBACK_DATA pFCD, __in PCFLT_RELATED_OBJECTS pFRO, __deref_out_opt PVOID *ppvCompletionContext)
{
       Ppasthrough_INSTANCE_CONTEXT pAIC = NULL;
       int option;
       int CreateDisposition;
       int IsNewCreate = 0;

       UNREFERENCED_PARAMETER(pFRO);
       UNREFERENCED_PARAMETER(ppvCompletionContext);

       PAGED_CODE();

       option = QueryUSBRegInfo(pFRO);
       CreateDisposition = (pFCD->Iopb->Parameters.Create.Options >> 24) & 0x000000ff;
       IsNewCreate = (CreateDisposition == FILE_CREATE || CreateDisposition == FILE_OPEN_IF || CreateDisposition == FILE_OVERWRITE_IF);

       if ((option & DENY_CREATE) != DENY_CREATE)
               return FLT_PREOP_SUCCESS_NO_CALLBACK;
       else if ((option & DENY_WRITE) == DENY_WRITE) {
               pFCD->IoStatus.Status = IsNewCreate ? STATUS_ACCESS_DENIED : STATUS_MEDIA_WRITE_PROTECTED;
                 pFCD->IoStatus.Information = 0;
                 return FLT_PREOP_COMPLETE;
       }
       else
       {
               DbgPrint("pasthrough pre Create: access denied");
                  
               pFCD->IoStatus.Status = STATUS_ACCESS_DENIED;
               pFCD->IoStatus.Information = 0;

               return FLT_PREOP_COMPLETE;
       }
}

FLT_PREOP_CALLBACK_STATUS pasthroughPreWrite(__inout PFLT_CALLBACK_DATA pFCD, __in PCFLT_RELATED_OBJECTS pFRO, __deref_out_opt PVOID *ppvCompletionContext)
{
       Ppasthrough_INSTANCE_CONTEXT pAIC = NULL;
       int option;

       UNREFERENCED_PARAMETER(pFRO);
       UNREFERENCED_PARAMETER(ppvCompletionContext);

       PAGED_CODE();

       option = QueryUSBRegInfo(pFRO);

       if ((option & DENY_WRITE) != DENY_WRITE)
               return FLT_PREOP_SUCCESS_NO_CALLBACK;
       else
       {
               DbgPrint("pasthrough pre Write: access denied");
                  
               pFCD->IoStatus.Status = STATUS_ACCESS_DENIED;
               pFCD->IoStatus.Information = 0;

               return FLT_PREOP_COMPLETE;
       }
}

FLT_PREOP_CALLBACK_STATUS pasthroughPreSetInformation(__inout PFLT_CALLBACK_DATA pFCD, __in PCFLT_RELATED_OBJECTS pFRO, __deref_out_opt PVOID *ppvCompletionContext)
{
       int option;

       UNREFERENCED_PARAMETER(ppvCompletionContext);

       PAGED_CODE();
    
       option = QueryUSBRegInfo(pFRO);

       if ((option & DENY_INFORMATHION) != DENY_INFORMATHION)
               return FLT_PREOP_SUCCESS_NO_CALLBACK;
       else
       {
               DbgPrint("pasthrough pre SetInformation: access denied");
                  
               pFCD->IoStatus.Status = STATUS_ACCESS_DENIED;
               pFCD->IoStatus.Information = 0;

               return FLT_PREOP_COMPLETE;
       }
}


VOID pasthroughContextCleanup(__in PFLT_CONTEXT pFC, __in FLT_CONTEXT_TYPE pFCT)
{
       Ppasthrough_INSTANCE_CONTEXT pAIC;

       PAGED_CODE();

       if (FLT_INSTANCE_CONTEXT == pFCT)
       {
               pAIC = (Ppasthrough_INSTANCE_CONTEXT) pFC;
               // no memory to release
       }
}

VOID pasthroughInstanceTeardownComplete(__in PCFLT_RELATED_OBJECTS pFRO, __in FLT_INSTANCE_TEARDOWN_FLAGS iFITF)
{
       Ppasthrough_INSTANCE_CONTEXT pAIC;
       NTSTATUS iNTStatus;

       UNREFERENCED_PARAMETER(iFITF);

       PAGED_CODE();

       iNTStatus = FltGetInstanceContext(pFRO->Instance, (PFLT_CONTEXT *)&pAIC);
       if (NT_SUCCESS(iNTStatus))
               FltReleaseContext(pAIC);
}
wumnkx 2019-4-8 00:06
3
0
好了, 只读也搞定了, 通过看日志, 发现在precreate里面CreateDisposition不等于FILE_OPEN就是写入, 于是在这里拦截, 效果很好。
IsWrite = (CreateDisposition != FILE_OPEN)

if ((option & DENY_WRITE) == DENY_WRITE && IsWrite) {
               DbgPrint("pasthrough pre Create: access denied IsWrite = %d, IsExcute = %d\n", IsWrite, IsExcute);
               pFCD->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;
                 pFCD->IoStatus.Information = 0;
                 return FLT_PREOP_COMPLETE;
       }

我还想禁止执行exe, 但没找到好的办法, 如果有人想到了希望不吝指教, 谢谢!!
Thead 2019-4-8 08:46
4
0
IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION
wumnkx 2019-4-8 11:08
5
0
Thead IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION
感谢大佬, 试了下在这里做可以禁止执行exe!!!
option = QueryUSBRegInfo(pFRO);
       IsExcute = (pFCD->Iopb->Parameters.AcquireForSectionSynchronization.PageProtection == PAGE_EXECUTE);


       if ((option & DENY_EXCUTE) != DENY_EXCUTE || !IsExcute)
               return FLT_PREOP_SUCCESS_NO_CALLBACK;
       else
       {
               DbgPrint("pasthrough pre CreateProcess: access denied");
                  
               pFCD->IoStatus.Status = STATUS_ACCESS_DENIED;
               pFCD->IoStatus.Information = 0;

               return FLT_PREOP_COMPLETE;
       }
wumnkx 2019-4-8 11:10
6
0
Thead IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION
实际测试中发现, 移动硬盘识别出来是硬盘, 还有些手机比如我的小米手机识别的是便携设备,有些识别的是你U盘, 我想对这些设备都做处理,  设备怎么在驱动里面区分呢?
Thead 2019-4-8 13:56
7
0
wumnkx 实际测试中发现, 移动硬盘识别出来是硬盘, 还有些手机比如我的小米手机识别的是便携设备,有些识别的是你U盘, 我想对这些设备都做处理, 设备怎么在驱动里面区分呢?
IOCTL_STORAGE_QUERY_PROPERTY
wumnkx 2019-4-8 16:47
8
0
Thead IOCTL_STORAGE_QUERY_PROPERTY
谢谢大佬!
wumnkx 2019-4-8 23:41
9
0
wumnkx 实际测试中发现, 移动硬盘识别出来是硬盘, 还有些手机比如我的小米手机识别的是便携设备,有些识别的是你U盘, 我想对这些设备都做处理, 设备怎么在驱动里面区分呢?
自己试验了一下, 便携设备在资源管理器里面显示的不是盘符,而是一个设备名称, 在设备管理器里面有个专门的便携设备项, 设备插上电脑时不会触发minifilter的InstanceSetup; 后来查了一下资料, 发现这个设备用的是叫WPD的驱动, 这玩意有人熟悉吗?
KanXuerr 2019-4-9 09:42
10
0
我也在做类似的功能,请教楼主大大是怎么判断盘符是否是U盘呢?还有QueryRegistryValue(L"\\Registry\\Machine\\Software\\USBInfo", L"Volume");这个注册表路径我用Win7和Win10看了下,好像都不存在呢?
wumnkx 2019-4-9 09:53
11
0
KanXuerr 我也在做类似的功能,请教楼主大大是怎么判断盘符是否是U盘呢?还有QueryRegistryValue(L"\\Registry\\Machine\\Software\\USBInfo&quo ...
这个注册表是我自己写的, 我这样写是为了方便测试, 因为公司电脑USB口封掉了。
判断是U盘可以在instancesetup里面通过卷取到设备对象, 然后取设备的这个属性IOCTL_STORAGE_QUERY_PROPERTY。
现在卡在便携设备这里了, 昨天发现这东西没有加载到文件系统, 使用的用WPD驱动, 有熟悉的人愿意讲讲吗?
NTSTATUS InstanceSetup(__in PCFLT_RELATED_OBJECTS pFRO, __in FLT_INSTANCE_SETUP_FLAGS iFISF, __in DEVICE_TYPE iDT, __in FLT_FILESYSTEM_TYPE iFFT)
{
       PDEVICE_OBJECT DeviceObject;
       NTSTATUS status;
       BYTE busType;

       UNREFERENCED_PARAMETER(iFISF);
       UNREFERENCED_PARAMETER(iFFT);

       //ReadRegistrySettings(NULL);

       PAGED_CODE();

       status = FltGetDiskDeviceObject(pFRO->Volume, &DeviceObject);
       if (!NT_SUCCESS(status))
       {
               return STATUS_UNSUCCESSFUL;
       }

       GetDeviceBusType(DeviceObject, &busType);
       if (busType == 7) {
               // 是U盘或者移动硬盘
       }



NTSTATUS
GetDeviceBusType(
__in PDEVICE_OBJECT Device,
__in __out BYTE* pBusType
)
{
       PIRP Irp;
       KEVENT Event;
       NTSTATUS status;
       IO_STATUS_BLOCK Iosb;
       STORAGE_PROPERTY_QUERY PropQuery;
       PSTORAGE_DEVICE_DESCRIPTOR pDesc;
       PVOID QueryBuffer = NULL;
       ULONG QuerySize = 0x2000;
       char * pDeviceInfo;

       __try
       {
               QueryBuffer = ExAllocatePoolWithTag(NonPagedPool, QuerySize, UIM_USB_POOL_TAG);
               if (!QueryBuffer)
               {
                       status = STATUS_INSUFFICIENT_RESOURCES;
                       __leave;
               }

               memset(&PropQuery, 0, sizeof(PropQuery));
               memset(QueryBuffer, 0, QuerySize);
               PropQuery.PropertyId = StorageDeviceProperty;
               PropQuery.QueryType = PropertyStandardQuery;

               KeInitializeEvent(&Event, NotificationEvent, FALSE);
               //
               //A driver that calls IoBuildDeviceIoControlRequest must not call IoFreeIrp, 
               //because the I/O manager frees these synchronous IRPs after IoCompleteRequest has been called.
               //
               Irp = IoBuildDeviceIoControlRequest(
                       IOCTL_STORAGE_QUERY_PROPERTY,
                       Device,
                       &PropQuery,
                       sizeof(PropQuery),
                       QueryBuffer,
                       QuerySize,
                       FALSE,
                       &Event,
                       &Iosb
                       );

               if (!Irp)
               {
                       status = STATUS_UNSUCCESSFUL;
                       __leave;
               }

               status = IoCallDriver(Device, Irp);

               if (STATUS_PENDING == status)
               {
                       KeWaitForSingleObject(
                               &Event,
                               Executive,
                               KernelMode,
                               FALSE,
                               (PLARGE_INTEGER)NULL
                               );

                       status = Iosb.Status;
               }

               if (!NT_SUCCESS(status))
               {
                       __leave;
               }

               if (!Iosb.Information)
               {
                       status = STATUS_UNSUCCESSFUL;
                       __leave;
               }

               pDesc = (PSTORAGE_DEVICE_DESCRIPTOR)QueryBuffer;

               if (pBusType)
                       *pBusType = (BYTE)pDesc->BusType;
               // 将pid, vid, seq打印出来
               pDeviceInfo = (char*)pDesc;
               DbgPrint("GetDeviceBusType pid: %s, vid: %s, version: %s, seq: %s\n", &pDeviceInfo[pDesc->ProductIdOffset], &pDeviceInfo[pDesc->VendorIdOffset], &pDeviceInfo[pDesc->ProductRevisionOffset], &pDeviceInfo[pDesc->SerialNumberOffset]);
       }
       __finally
       {
               if (QueryBuffer)
                       if (QueryBuffer != NULL)
                       {
                               ExFreePoolWithTag(QueryBuffer, UIM_USB_POOL_TAG);
                               QueryBuffer = NULL;
                       }
       }

       return status;
}
sylingyy 2019-4-9 10:28
12
0
你需要的是usbstore  filter,而不是minifilter。
wumnkx 2019-4-9 10:46
13
0
sylingyy 你需要的是usbstore filter,而不是minifilter。
便携设备使用的是WPD驱动, 就好比USB鼠标键盘, 不走文件系统, 限制usbstore对他无效, usbstore还是属于文件系统的 
sylingyy 2019-4-9 15:30
14
0
wumnkx 便携设备使用的是WPD驱动, 就好比USB鼠标键盘, 不走文件系统, 限制usbstore对他无效, usbstore还是属于文件系统的
他说是U盘,这样讲那自己写的文件系统,怎么过滤也是一样无效。
sylingyy 2019-4-9 15:32
15
0
wumnkx 便携设备使用的是WPD驱动, 就好比USB鼠标键盘, 不走文件系统, 限制usbstore对他无效, usbstore还是属于文件系统的
或许你需要USB CLASS filter,但是下层设备的判断需要自己做。
wumnkx 2019-4-10 10:01
16
0
WPD过滤驱动有方向了, 参照这个上面来做http://www.osronline.com/article.cfm%5earticle=446.htm
wx_幼儿园的王 2019-4-18 09:16
17
0
楼主。你的UIM_USB_POOL_TAG参数是什么啊
wumnkx 2019-4-18 09:34
18
0
wx_幼儿园的王 楼主。你的UIM_USB_POOL_TAG参数是什么啊
#define UIM_USB_POOL_TAG 'umiD'
pccq 2019-4-18 10:12
19
0
wumnkx WPD过滤驱动有方向了, 参照这个上面来做http://www.osronline.com/article.cfm%5earticle=446.htm
之前研究wpd过滤的时候,研究过这个帖子,没有成功,最后用的umdf filter
wumnkx 2019-4-18 14:17
20
0
pccq 之前研究wpd过滤的时候,研究过这个帖子,没有成功,最后用的umdf filter
我用这个帖子做的kmdf upperfilers只能处理DeviceControlCode, 不能细化到操控wpd的内部存储器的文件读写。你用umdf filter可以做到吗?
曹操abc 2019-4-18 18:11
21
0
有用
pccq 2019-4-18 19:09
22
0
wumnkx 我用这个帖子做的kmdf upperfilers只能处理DeviceControlCode, 不能细化到操控wpd的内部存储器的文件读写。你用umdf filter可以做到吗?
umdf filter可以获取到打开、读写、删除、关闭操作,还有文件名(可以转换成文件路径)和ProcessID
wx_幼儿园的王 2019-4-18 19:45
23
0
楼主,我写的是sfilter框架的过滤驱动,现在也遇到了禁用便携设备的问题,有什么经验可以跟我交流下吗,我现在还找不到方法
wumnkx 2019-4-18 20:50
24
0
pccq umdf filter可以获取到打开、读写、删除、关闭操作,还有文件名(可以转换成文件路径)和ProcessID
umdf是用的COM形式的接口做的吗? 大哥能否指点一下, 比如参照哪个例子
wumnkx 2019-4-18 20:52
25
0
wx_幼儿园的王 楼主,我写的是sfilter框架的过滤驱动,现在也遇到了禁用便携设备的问题,有什么经验可以跟我交流下吗,我现在还找不到方法
本来是打算在驱动层搞, 网上资料太少, 现在打算用组策略搞读写的权限限制, 然后文件审计的还没找到方法。。。
wumnkx 2019-4-18 21:11
26
0
wx_幼儿园的王 楼主,我写的是sfilter框架的过滤驱动,现在也遇到了禁用便携设备的问题,有什么经验可以跟我交流下吗,我现在还找不到方法
我现在在研究1个竞品,他的禁用是直接禁止设备, 就和设备管理器里面禁用设备操作一样, 用devcon 加个命令行就可以做, 这个做法不太好我不采取。我现在在研究他的文件审计, 本以为他是注dll到explorer里面来做, 今天调了一天explorer发现不是, 直接调试竞品的主进程导致卡死, 郁闷。其实我也想到了办法:便携设备菜单是在wpdshext.dll里面做的, 如果HOOK这个dll里面菜单处理函数应该就可以; 还有就是HOOK吊explorer的文件操作函数也是可以; 目前我想先搞清楚竞品是怎么做的。
wx_幼儿园的王 2019-4-19 09:15
27
0
wumnkx 我现在在研究1个竞品,他的禁用是直接禁止设备, 就和设备管理器里面禁用设备操作一样, 用devcon 加个命令行就可以做, 这个做法不太好我不采取。我现在在研究他的文件审计, 本以为他是注dll到ex ...
我第一次学,我的老师让我在两周做完,应该不会是这么复杂的东西吧
MRRighter 2019-4-19 09:32
28
0
我正好也是在做这个 我使用class filter来做的 我建议你用classfilter 做lowerfilter 因为某著名安全厂商企业版的设备禁用驱动和网上某国内著名透明加解密厂商的这个需求我逆向之后发现都是这么实现的,我最开始也是想用minifilter做 但是发现做不好
pccq 2019-4-19 09:54
29
0
wumnkx umdf是用的COM形式的接口做的吗? 大哥能否指点一下, 比如参照哪个例子
是的,umdf本质是一个com组件。实际上,wpd设备 分2种,一种是u盘,另一种是mtp(多媒体传输协议)设备,用umdf filter做,可以解析出mtp的操作
pccq 2019-4-19 09:55
30
0
wumnkx 我现在在研究1个竞品,他的禁用是直接禁止设备, 就和设备管理器里面禁用设备操作一样, 用devcon 加个命令行就可以做, 这个做法不太好我不采取。我现在在研究他的文件审计, 本以为他是注dll到ex ...
explorer打开wpd设备,用的是wpd api,hook file operations function是没有用的
pccq 2019-4-19 10:06
31
0
C:\Windows\System32\drivers\UMDF目录下面有2个文件:WpdFs.dll和WpdMtpDr.dll,前者用于U盘,后者用于mtp设备,umdf filter要过滤后者。

wx_幼儿园的王 2019-4-19 10:30
32
0
楼主找到了怎么判断智能手机等便携设备的方法了吗
wumnkx 2019-4-19 14:50
33
0
MRRighter 我正好也是在做这个 我使用class filter来做的 我建议你用classfilter 做lowerfilter 因为某著名安全厂商企业版的设备禁用驱动和网上某国内著名透明加解密厂商的这个需求我逆 ...
是用的哪个class呢?  U盘和WPD都能搞吗?
wumnkx 2019-4-19 15:01
34
0
pccq C:\Windows\System32\drivers\UMDF目录下面有2个文件:WpdFs.dll和WpdMtpDr.dll,前者用于U盘,后者用于mtp设备,umdf filter要过滤后者。
大哥, 你是参考wdk的这个例子吗?WinDDK\src\usb\osrusbfx2\umdf\filter。
最后于 2019-4-19 15:01 被wumnkx编辑 ,原因:
wumnkx 2019-4-19 15:03
35
0
wx_幼儿园的王 楼主找到了怎么判断智能手机等便携设备的方法了吗
便携设备要单独处理, 看上面讨论的
wx_幼儿园的王 2019-4-19 15:16
36
0
wumnkx 便携设备要单独处理, 看上面讨论的
使用wpd驱动写?能禁用便携设备吗,你做到了吗
pccq 2019-4-19 16:21
37
0
wumnkx pccq C:\Windows\System32\drivers\UMDF目录下面有2个文件:WpdFs.dll和WpdMtpDr.dll,前者用于U盘,后者 ...
好几年了,参考了好多资料,已经记不清了,这个应该也参考过
wumnkx 2019-4-19 16:30
38
0
wx_幼儿园的王 使用wpd驱动写?能禁用便携设备吗,你做到了吗
没实现, 前面的pccq大佬说他用umdf filter实现了。
你如果单纯想禁用就直接禁设备就好了, 想高级点就写个NT驱动禁用wudfhost.exe启动就好。  要精确控制文件读写就得用umdf filter来搞了
wx_幼儿园的王 2019-4-19 16:45
39
0
wumnkx 没实现, 前面的pccq大佬说他用umdf filter实现了。 你如果单纯想禁用就直接禁设备就好了, 想高级点就写个NT驱动禁用wudfhost.exe启动就好。 要精确控制文件读写就得用umd ...
直接禁用设备会不会导致接口插入键盘鼠标什么的不能用
wumnkx 2019-4-19 22:44
40
0
wx_幼儿园的王 直接禁用设备会不会导致接口插入键盘鼠标什么的不能用
我也不知道啊 , pccq大佬也不说具体怎么搞, 看看就好
wumnkx 2019-4-19 22:51
41
0
wumnkx 没实现, 前面的pccq大佬说他用umdf filter实现了。 你如果单纯想禁用就直接禁设备就好了, 想高级点就写个NT驱动禁用wudfhost.exe启动就好。 要精确控制文件读写就得用umd ...
你跟你老师说, wpd要重新开个课题,写个新的驱动搞了, 资料少, 不一定搞的定, 微软的文档真是一帮神仙写的, 用谷歌翻译一下玛德都是什么佛系语句, 简直受不了, 写了等于不写。这个东西工作量是U盘的好几倍, 你看着办吧
wx_幼儿园的王 2019-4-20 09:59
42
0
wumnkx 你跟你老师说, wpd要重新开个课题,写个新的驱动搞了, 资料少, 不一定搞的定, 微软的文档真是一帮神仙写的, 用谷歌翻译一下玛德都是什么佛系语句, 简直受不了, 写了等于不写。这个东西工作量是U盘 ...
你那个竞品的链接可以发一份给我看看嘛
wx_幼儿园的王 2019-4-20 10:16
43
0
wumnkx 你跟你老师说, wpd要重新开个课题,写个新的驱动搞了, 资料少, 不一定搞的定, 微软的文档真是一帮神仙写的, 用谷歌翻译一下玛德都是什么佛系语句, 简直受不了, 写了等于不写。这个东西工作量是U盘 ...
我自己觉得既然他连接生成了文件,文件过滤系统应该能抓到吧
wumnkx 2019-4-20 10:28
44
0
wx_幼儿园的王 我自己觉得既然他连接生成了文件,文件过滤系统应该能抓到吧
竞品是企业级的产品, 不是1个链接就能用的, 要申请激活码。我不透漏了。
你看看wdk目录下的tool, 找一下有没有devcon, 然后在命令行下 devcon /? 看下有哪些参数, 然后稍微转下自己灵活的小脑瓜就知道怎么用了
wx_幼儿园的王 2019-4-20 11:31
45
0
wumnkx 竞品是企业级的产品, 不是1个链接就能用的, 要申请激活码。我不透漏了。 你看看wdk目录下的tool, 找一下有没有devcon, 然后在命令行下 devcon /? 看下有哪些参数, 然后稍微转 ...
好了,我师父要我不管用什么方法把便携设备不包括摄像头之类的存储设备禁用和只读,还是要学习WPD
wumnkx 2019-4-21 23:12
46
0
wumnkx 没实现, 前面的pccq大佬说他用umdf filter实现了。 你如果单纯想禁用就直接禁设备就好了, 想高级点就写个NT驱动禁用wudfhost.exe启动就好。 要精确控制文件读写就得用umd ...
最后于 2019-4-21 23:13 被wumnkx编辑 ,原因:
wumnkx 2019-4-21 23:14
47
0
wumnkx 我也不知道啊 , pccq大佬也不说具体怎么搞, 看看就好
最后于 2019-4-21 23:15 被wumnkx编辑 ,原因:
wumnkx 2019-4-21 23:16
48
0
pccq C:\Windows\System32\drivers\UMDF目录下面有2个文件:WpdFs.dll和WpdMtpDr.dll,前者用于U盘,后者用于mtp设备,umdf filter要过滤后者。
大锅, 你说的umdf我自己也撸了一个, 这玩意只能针对特定设备啊, 不能控制所有便携设备, 最后我还是用kmdf来搞了, 只能搞禁用, 只读都不能搞, 文件名什么的都取不到。综合衡量了一下, 我决定搞个NT驱动, 保护组策略的注册表的方式来搞只读和禁用, 文件审计现在还在摸索中, 虽然我想到了好几个方案,但是领导要我先逆竞品的方案, 尼玛这个竞品竟然是多进程的, 资源管理器被它挂了20个多dll, 真他妈不好逆啊, 算了, 我就不含糊了, 竞品是ipguard,它能审计到便携设备的文件增加, 但不能审计来源, 我最开始怀疑他是用SHChangeNotifyRegister来实现的, 用IDA看了下, 没有;用windbg挂断点, 不命中;哎, 只能再让领导多给我点时间了
库尔 2019-4-22 01:30
49
0
这个ipguard听人说透明是自己解析文件格式,自己做了个界面让他读取.比透明加密稳啊.
wx_幼儿园的王 2019-4-22 09:20
50
0
wumnkx 大锅, 你说的umdf我自己也撸了一个, 这玩意只能针对特定设备啊, 不能控制所有便携设备, 最后我还是用kmdf来搞了, 只能搞禁用, 只读都不能搞, 文件名什么的都取不到。综合衡量了一下, 我决定 ...
问问楼主,UMDF  winDDk有例子吗,是哪些例子,我也想做个简单的看看效果
游客
登录 | 注册 方可回帖
返回