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); }