Пример #1
0
 public unsafe static extern NTSTATUS NtEnumerateValueKey(
     RegistryKeyHandle KeyHandle,
     uint Index,
     KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
     void *KeyValueInformation,
     uint Length,
     out uint ResultLength);
        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);
        }
        private static string KeyValueInformation(KEY_VALUE_INFORMATION_CLASS keyValueInfoClass, byte[] keyValueInformation)
        {
            string keyValueInfoStr = string.Empty;

            try
            {
                MemoryStream ms = new MemoryStream(keyValueInformation);
                BinaryReader br = new BinaryReader(ms);

                switch (keyValueInfoClass)
                {
                case KEY_VALUE_INFORMATION_CLASS.KeyValueBasicInformation:
                {
                    int titleIndex = br.ReadInt32();
                    int type       = br.ReadInt32();
                    int nameLength = br.ReadInt32();
                    keyValueInfoStr = "(" + keyValueInfoClass.ToString() + ") Name:" + Encoding.Unicode.GetString(keyValueInformation, (int)ms.Position, nameLength);

                    break;
                }

                case KEY_VALUE_INFORMATION_CLASS.KeyValueFullInformation:
                {
                    int titleIndex = br.ReadInt32();
                    int type       = br.ReadInt32();
                    int dataOffset = br.ReadInt32();
                    int dataLength = br.ReadInt32();
                    int nameLength = br.ReadInt32();
                    keyValueInfoStr  = "(" + keyValueInfoClass.ToString() + ") Name:" + Encoding.Unicode.GetString(keyValueInformation, (int)ms.Position, nameLength);
                    keyValueInfoStr += " Type:" + ((VALUE_DATA_TYPE)type).ToString();

                    byte[] dataBuffer = new byte[dataLength];
                    Array.Copy(keyValueInformation, dataOffset, dataBuffer, 0, dataBuffer.Length);

                    keyValueInfoStr += " Data:" + ValueTypeData((VALUE_DATA_TYPE)type, dataBuffer.Length, dataBuffer);

                    break;
                }

                case KEY_VALUE_INFORMATION_CLASS.KeyValuePartialInformation:
                {
                    int titleIndex = br.ReadInt32();
                    int type       = br.ReadInt32();
                    int dataLength = br.ReadInt32();
                    keyValueInfoStr += "(" + keyValueInfoClass.ToString() + ") Type:" + ((VALUE_DATA_TYPE)type).ToString();

                    byte[] dataBuffer = new byte[dataLength];
                    Array.Copy(keyValueInformation, ms.Position, dataBuffer, 0, dataBuffer.Length);
                    keyValueInfoStr += " Data:" + ValueTypeData((VALUE_DATA_TYPE)type, dataBuffer.Length, dataBuffer);

                    break;
                }


                default: break;
                }
            }
            catch (Exception ex)
            {
                keyValueInfoStr = "get data failed:" + ex.Message;
            }


            return(keyValueInfoStr);
        }
        public static string FormatDescription(FilterAPI.MessageSendData messageSend)
        {
            string descrption = string.Empty;

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

            try
            {
                if (messageSend.Status != (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS)
                {
                    return("");
                }

                switch (regCallbackClass)
                {
                case FilterAPI.RegCallbackClass.Reg_Pre_Delete_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Delete_Key:
                {
                    descrption = "registry key is being deleted.";
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Set_Value_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Set_Value_Key:
                {
                    VALUE_DATA_TYPE valueType = (VALUE_DATA_TYPE)messageSend.InfoClass;
                    descrption  = "Type:" + valueType.ToString();
                    descrption += " Data:" + ValueTypeData(valueType, (int)messageSend.DataBufferLength, messageSend.DataBuffer);
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Delete_Value_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Delete_Value_Key:
                {
                    descrption = "registry key's value is being deleted.";
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_SetInformation_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_SetInformation_Key:
                {
                    KEY_SET_INFORMATION_CLASS keySetInformationClass = (KEY_SET_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keySetInformationClass.ToString();
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Rename_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Rename_Key:
                {
                    string newName = Encoding.Unicode.GetString(messageSend.DataBuffer);
                    descrption = "registry key's name is being changed to " + newName;
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Enumerate_Key:
                {
                    KEY_INFORMATION_CLASS keyInformationClass = (KEY_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keyInformationClass.ToString();

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Enumerate_Key:
                {
                    KEY_INFORMATION_CLASS keyInformationClass = (KEY_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption += KeyInformation(keyInformationClass, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Enumerate_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keyValuseInformationClass.ToString();

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Enumerate_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption += KeyValueInformation(keyValuseInformationClass, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Key:
                {
                    KEY_INFORMATION_CLASS keyInformationClass = (KEY_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keyInformationClass.ToString();

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Query_Key:
                {
                    KEY_INFORMATION_CLASS keyInformationClass = (KEY_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption += KeyInformation(keyInformationClass, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keyValuseInformationClass.ToString();

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Query_Value_Key:
                {
                    //for unit test
                    if (messageSend.FileName.IndexOf("EaseFilter") > 0)
                    {
                        //this is our test key.
                        RegistryUnitTest.postQueryValueKeyPassed = true;
                    }

                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption += KeyValueInformation(keyValuseInformationClass, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Multiple_Value_Key:
                {
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Query_Multiple_Value_Key:
                {
                    uint entryCount = messageSend.InfoClass;

                    MemoryStream ms = new MemoryStream(messageSend.DataBuffer);
                    BinaryReader br = new BinaryReader(ms);

                    for (int i = 0; i < entryCount && ms.Position < ms.Length; i++)
                    {
                        long   currentOffset   = ms.Position;
                        int    nextEntryOffset = br.ReadInt32();
                        int    valueNameLength = br.ReadInt32();
                        int    dataType        = br.ReadInt32();
                        int    dataLength      = br.ReadInt32();
                        byte[] valueName       = br.ReadBytes(valueNameLength);
                        byte[] data            = br.ReadBytes(dataLength);

                        VALUE_DATA_TYPE type = (VALUE_DATA_TYPE)dataType;
                        descrption += "Name:" + Encoding.Unicode.GetString(valueName, 0, valueNameLength);
                        descrption += " Type:" + type.ToString();
                        descrption += " Data:" + ValueTypeData(type, dataLength, data) + Environment.NewLine;

                        ms.Position = currentOffset + nextEntryOffset;
                    }

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Create_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Post_Create_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Pre_Open_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Post_Open_KeyEx:
                {
                    descrption += FormatCreateDescription(messageSend);
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Load_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Load_Key:
                {
                    descrption += "SourceFile:" + Encoding.Unicode.GetString(messageSend.DataBuffer, 0, (int)messageSend.DataBufferLength);
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Replace_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Replace_Key:
                {
                    descrption += "NewFileName:" + Encoding.Unicode.GetString(messageSend.DataBuffer, 0, (int)messageSend.DataBufferLength);
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Query_KeyName:
                case FilterAPI.RegCallbackClass.Reg_Post_Query_KeyName:
                {
                    break;
                }

                default: descrption = "unsupported registry callback class:" + regCallbackClass.ToString(); break;
                }
            }
            catch (Exception ex)
            {
                descrption = "Format description failed, return error:" + ex.Message;
            }

            return(descrption);
        }