如果一个注册表表项的值类型为REG_SZ,请注意了,它并不意味着这个字符串一定会以一个空字符串结束。从底层实现的角度来说,注册表仅仅是一个层次化组织的名值数据库而已。
所以,你可以使用一些小技巧来”欺骗”注册表。 很多人都会欺骗注册表。你会发现有很多本应该被设置为REG_DWORD的值被存储成了一个4个字节的REG_BINARY。(这部分是 Windows 95 注册表的保留,它不支持 REG_DWORD。)
下面的程序代码是一个如何在注册表查询字符串的长度的一个例子。
如果你运行这个例子程序,则你会得到如下的结果:
发生了什么?
首先,我们调用的RegSetValueExW给出了一个错误的字符串长度,它宣称字符串的长度为2个字节,而实际值为6个字节。(2个宽字符加上一个结束字符) 而注册表尽职尽责地记录下这个谎言,并将其报告给后面的API调用。
第一次调用RegQueryValueExW询问字符串有多大,注册表报告值2,因为这是最初存储该值时给出的值。
为了表明确实没有空终止符,我们要求注册表将这两个字节的数据读入我们的缓冲区,用特殊值预先填充缓冲区,以便我们可以查看哪些内容已更新,哪些内容未更新。
瞧,这些值是从注册表中读取的,并且只读取了两个字节。 sz[0]包含字符“1”,而sz[1]保持未初始化。
安全隐患
如果你的程序假定注册表中的字符串总是以空字符结尾,那么如果遇到非空字符结尾的字符串,你可能会被误导,从而导致缓冲区溢出。(例如,如果你使用strcpy来复制它。)
总结
我们需要实际测试,从而探究事物的本质。表面上给人的感觉,往往它是不靠谱的。 重复,请实际做研究!
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。 本文来自:《Beware of non-null-terminated registry strings》
最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。 我想:你值得拥有。
|