编辑二进制注册表项

时间:2013-05-23 19:38:19

标签: c# internet-explorer binary registry hex

我正在尝试以编程方式在Internet Explorer中配置一些选项,如:

  1. 允许ActiveX过滤
  2. 允许脚本
  3. 等。
  4. 它们都存储在注册表中,因此我可以使用。

    轻松编辑它们
    public void EditKey(String keyPath, String keyName, Int32 newValue)
        {
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyPath, true))
            {
                if (key != null)
                    key.SetValue(keyName, newValue, RegistryValueKind.DWord);
            }
        }
    

    这是我的问题:

    我需要在工具中添加一个网站 - > Internet Explorer中的兼容性视图设置。

    经过一番研究,我看到这个网站列表存储在:

    HKEY_CURRENT_USER \ Software \ Microsoft \ Internet Explorer \ BrowserEmulation \ ClearableListData \ UserFilter.
    

    问题是这个密钥是二进制密钥所以它有点困难,首先解码其中的内容并进行编辑

    我发现每个存储的网站之间都有一个分隔符:

    binary key

    您清楚地看到网站:123.com和456.com在列表中。我需要在该列表中添加一个网站,但这里可以说这个分隔符似乎随机改变了。

    我在我想要的网站上构建了一个预定义的分隔符,所以它看起来像这样:

    private void ReadBinaryKey()
        {
            byte[] newWebsite = new byte []
            {
                0x0C,0x00,0x00,0x00,0xA8,0x82,0x8F,0x0D,
                0xC1,0x57,0xCE,0x01,0x01,0x00,0x00,0x00,
                0x08,0x00,0x32,0x00,0x30,0x00,0x32,0x00,
                0x30,0x00,0x2E,0x00,0x6E,0x00,0x65,0x00,
                0x74,0x00
            };
    
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(PATH_CVS, true))
            {
                if (key != null)
                {
                    var value = (byte[])key.GetValue("UserFilter");
    
                    // need to set my value here key.SetValue("UserFilter", newWebSite)
                }
            }        
        }
    

    我没有尝试过,因为我已经知道它根本不起作用。问题是随机分隔符。还有其他方法可以满足我的需求吗?任何帮助将不胜感激。

    感谢。

3 个答案:

答案 0 :(得分:1)

这是有效的代码。我在Ryoichi Fukushima创建的代码中添加了一些代码。 我做的主要区别是我在字节数组中添加了域数。我在IE11,IE10中进行了测试。

private const string CLEARABLE_LIST_DATA = @"Software\Microsoft\Internet Explorer\BrowserEmulation\ClearableListData";
    private const string USERFILTER = "UserFilter";

    private static string[] GetDomains()
    {
        string[] domains;

        using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
        {
            byte[] filter = regkey.GetValue(USERFILTER) as byte[];
            domains = GetDomains(filter);
        }

        return domains;
    }

    /* IT'S DANGER!! */
    // You shouldn't call until it becomes completely obvious that UNKNOWN parameter is meaning.
    private static void AddUserFilter(string domain)
    {
        string[] domains = GetDomains();
        foreach (string item in domains)
        {
            if (item==domain)
            {
                return;
            }
        }

        using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(CLEARABLE_LIST_DATA))
        {
            byte[] filter = regkey.GetValue(USERFILTER) as byte[];
            if(filter==null) filter=new byte[0];
            byte[] newReg = GetAddedValue(domain, filter);

            regkey.SetValue(USERFILTER, newReg, Microsoft.Win32.RegistryValueKind.Binary);
        }
    }

    private static void RemoveUserFilter(string domain)
    {
        using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
        {
            byte[] filter = regkey.GetValue(USERFILTER) as byte[];
            byte[] newReg = GetRemovedValue(domain, filter);

            if (GetDomains(newReg).Length == 0)
                regkey.DeleteValue(USERFILTER);
            else
                regkey.SetValue(USERFILTER, newReg, Microsoft.Win32.RegistryValueKind.Binary);
        }
    }

    private static byte[] GetFilter()
    {
        byte[] filter;
        using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
        {
            filter = regkey.GetValue(USERFILTER) as byte[];
        }
        return filter;
    }

    private static string[] GetDomains(byte[] filter)
    {
        List<string> domains = new List<string>();

        int length;
        int offset_filter = 24;
        int totalSize = filter.Length;

        while (offset_filter < totalSize)
        {
            length = BitConverter.ToUInt16(filter, offset_filter + 16);
            domains.Add(System.Text.Encoding.Unicode.GetString(filter, 16 + 2 + offset_filter, length * 2));
            offset_filter += 16 + 2 + length * 2;
        }

        return domains.ToArray();
    }

    private static byte[] GetAddedValue(string domain, byte[] filter)
    {
        byte[] SEPARATOR = new byte[] { 0x0C, 0x00, 0x00, 0x00 };
        byte[] CONSTANT = new byte[] { 0x01, 0x00, 0x00, 0x00 };
        byte[] UNKNOWN = BitConverter.GetBytes(DateTime.Now.ToBinary());

        List<byte> newReg = new List<byte>();
        byte[] binDomain = System.Text.Encoding.Unicode.GetBytes(domain);

        newReg.AddRange(filter);
        newReg.AddRange(SEPARATOR);
        /************************************************************************************************/
        newReg.AddRange(UNKNOWN); // IT'S IRRESPONSIBLE!!  Setting 0x00 is preferable to adding DateTime
        /************************************************************************************************/
        newReg.AddRange(CONSTANT);
        newReg.AddRange(BitConverter.GetBytes((UInt16)domain.Length));
        newReg.AddRange(binDomain);

        byte[] newSize = BitConverter.GetBytes((UInt16)(newReg.Count - 12));
        newReg[12] = newSize[0];
        newReg[13] = newSize[1];

        string[] domains = GetDomains();
        byte[] newCount = BitConverter.GetBytes((UInt16)(domains.Length + 1));
        newReg[8] = newCount[0];
        newReg[9] = newCount[1];

        newReg[20] = newCount[0];
        newReg[21] = newCount[1];

        return newReg.ToArray();
    }

    private static byte[] GetRemovedValue(string domain, byte[] filter)
    {
        byte[] newReg;
        int length;
        int offset_filter = 24;
        int offset_newReg = 0;
        int totalSize = filter.Length;

        newReg = new byte[totalSize];
        Array.Copy(filter, 0, newReg, 0, offset_filter);
        offset_newReg += offset_filter;

        while (offset_filter < totalSize)
        {
            length = BitConverter.ToUInt16(filter, offset_filter + 16);
            if (domain != System.Text.Encoding.Unicode.GetString(filter, offset_filter + 16 + 2, length * 2))
            {
                Array.Copy(filter, offset_filter, newReg, offset_newReg, 16 + 2 + length * 2);
                offset_newReg += 16 + 2 + length * 2;
            }
            offset_filter += 16 + 2 + length * 2;
        }
        Array.Resize(ref newReg, offset_newReg);
        byte[] newSize = BitConverter.GetBytes((UInt16)(offset_newReg - 12));
        newReg[12] = newSize[0];
        newReg[13] = newSize[1];

        return newReg;
    }

答案 1 :(得分:0)

也许...

0x00-0x0B : header
0x0C-0x0D : "TOTAL BYTES-12" (UInt16)
0x0E-0x17 : constant A
0x18-0x1B : separator
0x1C-0x23 : UNKNOWN(id? NOT registered datetime...)
0x24-0x27 : constant B
0x28-0x29 : length of target domain(UInt16, ex. example.com is 0x0B,0x00)
0x2A-     : target domain (UNICODE)
[repeat separator...target domain]

样本...

private const string CLEARABLE_LIST_DATA = @"Software\Microsoft\Internet Explorer\BrowserEmulation\ClearableListData";
private const string USERFILTER = "UserFilter";

private static string[] GetDomains()
{
    string[] domains;

    using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
    {
        byte[] filter = regkey.GetValue(USERFILTER) as byte[];
        domains = GetDomains(filter);
    }

    return domains;
}

/* IT'S DANGER!! */
// You shouldn't call until it becomes completely obvious that UNKNOWN parameter is meaning.
private static void AddUserFilter(string domain)
{
    using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(CLEARABLE_LIST_DATA))
    {
        byte[] filter = regkey.GetValue(USERFILTER) as byte[];
        byte[] newReg = GetAddedValue(domain, filter);

        regkey.SetValue(USERFILTER, newReg, Microsoft.Win32.RegistryValueKind.Binary);
    }
}

private static void RemoveUserFilter(string domain)
{
    using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
    {
        byte[] filter = regkey.GetValue(USERFILTER) as byte[];
        byte[] newReg = GetRemovedValue(domain, filter);

        if (GetDomains(newReg).Length == 0)
            regkey.DeleteValue(USERFILTER);
        else
            regkey.SetValue(USERFILTER, newReg, Microsoft.Win32.RegistryValueKind.Binary);
    }
}

private static byte[] GetFilter()
{
    byte[] filter;
    using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
    {
        filter = regkey.GetValue(USERFILTER) as byte[];
    }
    return filter;
}

private static string[] GetDomains(byte[] filter)
{
    List<string> domains = new List<string>();

    int length;
    int offset_filter = 24;
    int totalSize = filter.Length;

    while (offset_filter < totalSize)
    {
        length = BitConverter.ToUInt16(filter, offset_filter + 16);
        domains.Add(System.Text.Encoding.Unicode.GetString(filter, 16 + 2 + offset_filter, length * 2));
        offset_filter += 16 + 2 + length * 2;
    }

    return domains.ToArray();
}

private static byte[] GetAddedValue(string domain, byte[] filter)
{
    byte[] SEPARATOR = new byte[] { 0x0C, 0x00, 0x00, 0x00 };
    byte[] CONSTANT = new byte[] { 0x01, 0x00, 0x00, 0x00 };
    byte[] UNKNOWN = BitConverter.GetBytes(DateTime.Now.ToBinary());

    List<byte> newReg = new List<byte>();
    byte[] binDomain = System.Text.Encoding.Unicode.GetBytes(domain);

    newReg.AddRange(filter);
    newReg.AddRange(SEPARATOR);
    /************************************************************************************************/
    newReg.AddRange(UNKNOWN); // IT'S IRRESPONSIBLE!!  Setting 0x00 is preferable to adding DateTime
    /************************************************************************************************/
    newReg.AddRange(CONSTANT);
    newReg.AddRange(BitConverter.GetBytes((UInt16)domain.Length));
    newReg.AddRange(binDomain);

    byte[] newSize = BitConverter.GetBytes((UInt16)(newReg.Count - 12));
    newReg[12] = newSize[0];
    newReg[13] = newSize[1];

    return newReg.ToArray();
}

private static byte[] GetRemovedValue(string domain, byte[] filter)
{
    byte[] newReg;
    int length;
    int offset_filter = 24;
    int offset_newReg = 0;
    int totalSize = filter.Length;

    newReg = new byte[totalSize];
    Array.Copy(filter, 0, newReg, 0, offset_filter);
    offset_newReg += offset_filter;

    while (offset_filter < totalSize)
    {
        length = BitConverter.ToUInt16(filter, offset_filter + 16);
        if (domain != System.Text.Encoding.Unicode.GetString(filter, offset_filter + 16 + 2, length * 2))
        {
            Array.Copy(filter, offset_filter, newReg, offset_newReg, 16 + 2 + length * 2);
            offset_newReg += 16 + 2 + length * 2;
        }
        offset_filter += 16 + 2 + length * 2;
    }
    Array.Resize(ref newReg, offset_newReg);
    byte[] newSize = BitConverter.GetBytes((UInt16)(offset_newReg - 12));
    newReg[12] = newSize[0];
    newReg[13] = newSize[1];

    return newReg;
}

答案 2 :(得分:0)

以下是我阅读此数据的方法:

Bytes  Description
00-07  Header (Appears to be constant "41,1f,00,00,53,08,ad,ba")
08-11  Int64 Total # of entries in the list
12-15  Int64 Total # of bytes to follow including this number. (DataLen + 4)
16-19  Int64 Version (seems to always be 1)
20-??  Repeating entries.

Entry Format
Bytes  Description
00-03  Int64   Entry Number  (Increments for each entry)
04-07  Int64   Entry Header (Seems to be constant at 12 (0xC))
08-11  Int64   Unknown - Checksum?
12-15  Int64   Unknown - Timestamp?
16-19  Int64   Unknown - Always 1
20-21  Int32   Length of data to follow  (an entry of abc.com would be 7)
22-??  Unicode Chars for the website/address