【问题标题】:HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\TimeZoneKeyName corrupt?HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\TimeZoneKeyName 损坏?
【发布时间】:2015-02-27 06:50:12
【问题描述】:

我正在尝试确定 Windows 系统的当前时区。以下代码 sn-p (大致)基于@MattJohnson 在此线程上的回答:Getting local timezone identifier when OS display language is non-english

    using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(
                                   @"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"))
    {
       if (registryKey != null)
       {
          string windowsTimeZoneId = registryKey.GetValue("TimeZoneKeyName") as string;
          if (string.IsNullOrEmpty(windowsTimeZoneId))
             windowsTimeZoneId = registryKey.GetValue("StandardName") as string;
          if (!string.IsNullOrEmpty(windowsTimeZoneId))
          {
             int i = windowsTimeZoneId.IndexOf('\0');
             if (i != -1)
                windowsTimeZoneId = windowsTimeZoneId.Remove(i);
             return ConvertFromWindowsId(windowsTimeZoneId);
          }
       }
    }

如果我在第一行“if (string.IsNullOrEmpty(windowsTimeZoneId))”上放置一个断点,那么这就是我在 Visual Studio 调试器中看到的:

这里发生了什么? RegistryKey.GetValue() 正在返回一个装箱的字符串,但为什么它没有检测到两个十六进制 00 字节并在那里终止字符串?

到目前为止,我已经在我的两台 PC 上对此进行了测试。这是来自运行 Windows 7 64 位的版本。另一个运行 Windows 7 32 位,除了它说返回的字符串的长度是 128 个字符而不是 127 个字符之外,它是相同的。

使用 regedit.exe 查看注册表项时,它看起来很好,只显示“浪漫标准时间”。

有点谷歌搜索出现了这个问题https://social.msdn.microsoft.com/Forums/sqlserver/en-US/eca7ad76-c910-46be-8fb9-876c7cde5c69/registry-read-time-zone-info-differ-when-code-build-on-40-framework-on-host-system-win-7-64-bit?forum=csharpgeneral否则我找不到任何东西。

该程序是使用 Visual Studio 2012 构建的,目标是 .Net 2.0。

如您所见,我添加了代码以将这种“损坏”结果考虑在内,但如果有人能向我解释这里发生了什么,甚至可能如何避免整个问题。

编辑:

该程序是使用 Visual Studio 2012 构建的,目标是 .Net 2.0。

嗯,情节变厚了。这种说法并不完全正确。上面显示的代码树桩位于针对 .Net 2.0 构建的库程序集中,但它是从针对 .Net 4.0 的程序调用的。现在我尝试从一个针对 .Net 2.0 的程序调用它,没有问题,RegistryKey.GetValue() 只返回“浪漫标准时间”。因此,正如 MSDN 上的帖子所暗示的那样,它似乎确实与 .Net Framework 4.0 有关。

编辑 2 - 开始认为这是“正常的”

这对于 SO 来说有点离题,但如果有人能看一下我在 Superuser.com 上的相关帖子,我将不胜感激,因为我在那里没有得到即时满足,我想解决这个问题,所以我知道我是否仍然应该恐慌。谢谢。

https://superuser.com/questions/859031/possible-malware-modification-of-windows-registry-entry

【问题讨论】:

  • 非常有趣的细节。另请注意,浪漫标准时间适用于欧洲 - 而不是墨西哥。所以这不是故意的,因为值在同一个字符串中是不相关的。
  • @Matt:我怀疑多余的数据是随机的,只是分配缓冲区时内存中发生的任何事情。看起来 Windows 本身正在这样做;如果我删除多余的内容,然后更改时区,它会重新出现。每次看起来都是相同的数据,但我还没有尝试重新启动机器,看看是否让它看起来有什么不同。

标签: .net windows timezone registry


【解决方案1】:

在注册表中设置字符串或多字符串值时,Windows 不检查语义;它只存储提供的任何二进制内容,长度由程序员指定。这意味着字符串可以过早地以空值终止,或者相反,根本不以空值终止。 (顺便说一句,这确实有安全隐患:虽然我不认为过早的空终止可能会带来风险,但无法处理字符串不是空终止的情况的本机代码可能会。)

根据 Hans(在他删除的答案中)的说法,如果字符串过早地以空值终止,4.x 之前的 .NET 版本将忽略额外数据,而 4.x 包含它。这就是为什么您在开始使用 4.x 后才注意到该问题的原因。

至于为什么这个特定的值会过早地以空值终止,这似乎是微软的粗心大意。如果您删除额外数据,然后更改时区,额外数据会重新出现。因此,这样做似乎是 Windows 本身。这些数据在我看来是随机的,所以我不相信这是故意的。事实上,这在技术上可能构成数据泄露漏洞,尽管可能没有实际影响。

我建议您搜索 null 并在必要时截断字符串。可能存在不存在的情况,例如,如果条目已被第三方代码修改,或者如果 MS 最终发布更新并修复问题,或者,当然,如果您正在运行 . NET 2.x。所以你需要处理这两种情况。

(如果我有时间,下周回去工作时,我会在虚拟机上安装一个干净的 Windows 副本,并确认问题存在且绝对不存在第三方软件。如果是这样,我'会考虑报告它 - 我怀疑 MS 会发布补丁,但它可能会在未来版本的 Windows 中得到修复。)

【讨论】:

  • 非常感谢您查看此内容以及您的良好解释。现在我又可以轻松入睡了。 (汉斯的回答让我非常沮丧,我正准备联系一位新客户,并警告他们我可能无意中用一种无法检测到的病毒感染了他们的大约 300 台电脑。那会让我很受他们欢迎。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 2021-12-04
  • 2022-07-08
  • 2010-11-15
相关资源
最近更新 更多