Ejemplo n.º 1
0
        public static bool AuthorizeFileAccess(FilterAPI.MessageSendData messageSend, ref FilterAPI.MessageReplyData messageReply)
        {
            bool ret = true;

            try
            {
                messageReply.MessageId    = messageSend.MessageId;
                messageReply.MessageType  = messageSend.MessageType;
                messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;

                messageReply.MessageId   = messageSend.MessageId;
                messageReply.MessageType = messageSend.MessageType;

                //
                //here you can control all the registered IO requests,block the access or modify the I/O data base on the file IO information from MessageSend struture
                //
                //

                //if you don't want to change anything to this IO request, just let it pass through as below setting:
                //messageReply.FilterStatus = 0;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                //if you want to block the access this IO request before it goes down to the file system, you can return the status as below,
                //it is only for pre IO requests, it means the user IO reuqests will be completed here instead of going down to the file system.
                //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;

                //if you want to modify the IO data and complete the pre IO with your own data, you can return status as below:
                // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                // messageReply.DataBufferLength = the return data buffer length.
                // messageReply.DataBuffer = the data you want to return.
                // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                FilterAPI.MessageType       messageType = (FilterAPI.MessageType)messageSend.MessageType;
                WinData.FileInfomationClass infoClass   = (WinData.FileInfomationClass)messageSend.InfoClass;

                uint   dataLength = messageSend.DataBufferLength;
                byte[] data       = messageSend.DataBuffer;

                //here is some IO information for your reference:
                if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FO_REMOTE_ORIGIN) > 0)
                {
                    //this is file access request comes from remote network server
                }

                //you can check the file create option with this data:
                //"DesiredAccess: messageSend.DesiredAccess
                //"Disposition:" + ((WinData.Disposition)messageSend.Disposition).ToString();
                //"ShareAccess:" + ((WinData.ShareAccess)messageSend.SharedAccess).ToString();
                //"CreateOptions:"messageSend.CreateOptions


                //Here is the demo to copy file content before it was deleted.-----------------------------------------------
                bool isFileDeleting = false;
                if (messageSend.Status == (uint)NtStatus.Status.Success)
                {
                    if (messageType == FilterAPI.MessageType.POST_CREATE)
                    {
                        if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FILE_DELETE_ON_CLOSE) > 0)
                        {
                            isFileDeleting = true;
                        }
                    }
                    else if (messageType == FilterAPI.MessageType.PRE_SET_INFORMATION)
                    {
                        if (infoClass == WinData.FileInfomationClass.FileDispositionInformation)
                        {
                            isFileDeleting = true;
                        }
                    }

                    if (isFileDeleting)
                    {
                        //IntPtr fileHandle = IntPtr.Zero;
                        //bool retVal = FilterAPI.GetFileHandleInFilter(messageSend.FileName,(uint)FileAccess.Read, ref fileHandle);
                        //if (retVal)
                        //{
                        //    SafeFileHandle sHandle = new SafeFileHandle(fileHandle, true);
                        //    FileStream fileStream = new FileStream(sHandle, FileAccess.Read);

                        //    //copy your data here...

                        //    fileStream.Close();
                        //}
                    }
                }
                //End -----------------------------------------------



                switch (messageType)
                {
                case FilterAPI.MessageType.PRE_CREATE:
                {
                    //here you reparse the file open to another new file name

                    //string newReparseFileName = "\\??\\c:\\myNewFile.txt";
                    //byte[] returnData = Encoding.Unicode.GetBytes(newReparseFileName);
                    //Array.Copy(returnData, messageReply.DataBuffer, returnData.Length);
                    //messageReply.DataBufferLength = (uint)returnData.Length;
                    //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                    //messageReply.ReturnStatus = (uint)NtStatus.Status.Reparse;

                    break;
                }


                case FilterAPI.MessageType.PRE_CACHE_READ:
                case FilterAPI.MessageType.POST_CACHE_READ:
                case FilterAPI.MessageType.PRE_NOCACHE_READ:
                case FilterAPI.MessageType.POST_NOCACHE_READ:
                case FilterAPI.MessageType.PRE_PAGING_IO_READ:
                case FilterAPI.MessageType.POST_PAGING_IO_READ:
                case FilterAPI.MessageType.PRE_CACHE_WRITE:
                case FilterAPI.MessageType.POST_CACHE_WRITE:
                case FilterAPI.MessageType.PRE_NOCACHE_WRITE:
                case FilterAPI.MessageType.POST_NOCACHE_WRITE:
                case FilterAPI.MessageType.PRE_PAGING_IO_WRITE:
                case FilterAPI.MessageType.POST_PAGING_IO_WRITE:
                {
                    //byte[] returnData = //new data you want to modify the read/write data;
                    //Array.Copy(returnData, messageReply.DataBuffer, returnData.Length);
                    //messageReply.DataBufferLength = (uint)returnData.Length;

                    ////for pre IO,use this one
                    //// messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;

                    // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                    // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;


                    break;
                }

                case FilterAPI.MessageType.PRE_SET_INFORMATION:
                case FilterAPI.MessageType.POST_SET_INFORMATION:
                case FilterAPI.MessageType.PRE_QUERY_INFORMATION:
                case FilterAPI.MessageType.POST_QUERY_INFORMATION:
                {
                    switch (infoClass)
                    {
                    case WinData.FileInfomationClass.FileRenameInformation:
                    {
                        if (FilterAPI.MessageType.PRE_SET_INFORMATION == messageType)
                        {
                            string blockFileName = @"c:\filterTest\blockRename.txt";
                            //test block rename to blockFileName, it needs to register PRE_SET_INFORMATION;
                            if (string.Compare(messageSend.FileName, blockFileName, true) == 0)
                            {
                                EventManager.WriteMessage(179, "IOAccessControl", EventLevel.Warning, "Block rename for file:" + messageSend.FileName);
                                ret = false;
                                break;
                            }
                        }

                        //you can block file rename as below
                        //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                        break;
                    }

                    case WinData.FileInfomationClass.FileDispositionInformation:
                    {
                        //you can block file delete as below
                        //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                        break;
                    }

                    case WinData.FileInfomationClass.FileEndOfFileInformation:
                    {
                        //change file size
                        break;
                    }

                    case WinData.FileInfomationClass.FileBasicInformation:
                    {
                        //file basic information
                        break;
                    }

                    case WinData.FileInfomationClass.FileStandardInformation:
                    {
                        //file standard information
                        break;
                    }

                    case WinData.FileInfomationClass.FileNetworkOpenInformation:
                    {
                        //file network information
                        break;
                    }

                    case WinData.FileInfomationClass.FileInternalInformation:
                    {
                        //file internal inofrmation
                        break;
                    }

                    default:
                    {
                        break;
                    }
                    }

                    break;
                }
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(174, "IOAccessControl", EventLevel.Error, "IOAccessControl failed." + ex.Message);
            }

            return(ret);
        }
        public static bool AuthorizeRegistryAccess(FilterAPI.MessageSendData messageSend, ref FilterAPI.MessageReplyData messageReply)
        {
            bool ret = true;

            try
            {
                messageReply.MessageId    = messageSend.MessageId;
                messageReply.MessageType  = messageSend.MessageType;
                messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;


                //
                //here you can control registry request,block the access or modify the registry data.
                //
                //

                //if you don't want to change anything to this registry request, just let it pass through as below setting:
                //messageReply.FilterStatus = 0;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                //if you want to block the access this registry request, you can return the status as below,
                //it is only for pre callback requests.
                //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;

                //if you want to modify the registry data and complete the pre IO with your own data, you can return status as below:
                // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                // messageReply.DataBufferLength = the return data buffer length.
                // messageReply.DataBuffer = the data you want to return.
                // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                FilterAPI.RegCallbackClass regCallbackClass = (FilterAPI.RegCallbackClass)messageSend.Offset;

                uint   dataLength = messageSend.DataBufferLength;
                byte[] data       = messageSend.DataBuffer;

                switch (regCallbackClass)
                {
                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    IntPtr keyValueInfoPtr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);


                    if (messageSend.FileName.IndexOf("EaseFilter") <= 0)
                    {
                        //this is not our unit test key
                        break;
                    }

                    //below code is for unit test to demo how to complete pre-callback registry call with our own data.
                    EventManager.WriteMessage(400, "AuthorizeRegistryAccess", EventLevel.Error, "Reg_Pre_Query_Value_Key keyValuseInformationClass:" + keyValuseInformationClass.ToString());

                    switch (keyValuseInformationClass)
                    {
                    case KEY_VALUE_INFORMATION_CLASS.KeyValueBasicInformation:
                    {
                        //public struct KEY_VALUE_BASIC_INFORMATION
                        // {
                        //     public uint TitleIndex;
                        //     public uint Type;
                        //     public uint NameLength;
                        //     public byte[] Name;
                        // }

                        uint   titleIndex      = 0;
                        uint   type            = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        byte[] valueName       = Encoding.Unicode.GetBytes("value1");
                        uint   valueNameLength = (uint)valueName.Length;

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);
                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(valueNameLength);
                        bw.Write(valueName);

                        messageReply.DataBufferLength = (uint)ms.Position;
                        messageReply.FilterStatus     = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;


                        break;
                    }

                    case KEY_VALUE_INFORMATION_CLASS.KeyValueFullInformation:
                    {
                        //KeyValueFullInformation class structure
                        //public uint TitleIndex;
                        //public uint Type;
                        //public uint DataOffset;
                        //public uint DataLength;
                        //public uint NameLength;
                        //public byte[] Name;

                        uint   titleIndex      = 0;
                        uint   type            = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        uint   testData        = 12345;
                        uint   testDataLength  = sizeof(uint);
                        byte[] valueName       = Encoding.Unicode.GetBytes("value1");
                        uint   valueNameLength = (uint)valueName.Length;
                        uint   dataOffset      = 5 * sizeof(uint) + valueNameLength;

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);
                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(dataOffset);
                        bw.Write(testDataLength);
                        bw.Write(valueNameLength);
                        bw.Write(valueName);
                        bw.Write(testData);

                        messageReply.DataBufferLength = (uint)ms.Position;
                        messageReply.FilterStatus     = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;


                        break;
                    }

                    case KEY_VALUE_INFORMATION_CLASS.KeyValuePartialInformation:
                    {
                        // public struct KEY_VALUE_PARTIAL_INFORMATION
                        //{
                        //    public uint TitleIndex;
                        //    public uint Type;
                        //    public uint DataLength;
                        //    public byte[] Data;
                        //}

                        uint titleIndex     = 0;
                        uint type           = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        uint testData       = 12345;
                        uint testDataLength = sizeof(uint);

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);

                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(testDataLength);
                        bw.Write(testData);

                        messageReply.DataBufferLength = (uint)ms.Position;

                        messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;

                        break;
                    }


                    default: break;
                    }
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Create_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Pre_Open_KeyEx:
                {
                    //this is our unit test key
                    if (messageSend.FileName.IndexOf("EaseFilter") > 0)
                    {
                        //NOT allow to create new registry key.

                        messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                    }

                    break;
                }

                default: break;
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(400, "AuthorizeRegistryAccess", EventLevel.Error, "AuthorizeRegistryAccess exception:" + ex.Message);
            }

            return(ret);
        }