天天看点

关于那些没有标准答案的问题一览

有时候,有一些问题没有一个标准的答案,或者,即使它有答案,但是这个答案也是没有实际意义的。今天我们就来列举几个来看看。

问题:我怎么知道当前系统里有多少个指向一个共享内存对象的引用?

即使有办法知道,当你得到答案之后的几毫秒,你的答案已经是错误的了。为什么?因为有人可能在你获取引用数之后立即打开了一个新的引用句柄。这就是”由于无法避免的竞争条件所导致的无意义答案”的一个例子。

问题:在不进入一个临界区的前提下,我如何确定这个临界区是未锁定的?

和上面一样,当你得到答案后,可能立即会有另一个线程决定进入该临界区,从而让你刚刚得到的答案变成了错误的答案。

问题:我如何确定当前系统上是否安装有一个键盘钩子?

和上面一样,当你得到”肯定没有,一切安全”的答案后,可能会有人立即安装一个钩子。

这个问题实际上会更严重,因为一般对这个问题感兴趣的人,通常会想要实现一个安全的键盘访问功能。但是这个时候,可能有人已经安装了一个键盘钩子,这就意味着,他们已经将代码挂接到你的进程中了(毕竟它是一个钩子嘛)。他们很容易将IsKeyboardHooked给Hook掉,并让其直接返回FALSE。

现在当你的程序询问系统,当前是否有安装键盘钩子,在上面的情况下,你会直接得到一个”愉快的”答案:”没有,一切安全”。接下里你会”盲目自信”地相信这个答案,并认为系统里没有安装键盘钩子。这实际上是不可信的,只是因为这个是某个人Hook掉真实代码后伪造的一个假答案。

你无法从系统本身内部可靠地推断该系统的安全性

这就像是试图向自己证明我没有疯一样。

系统本身可能已经受到攻击,因此你的所有推理都可以被虚拟化。此外,你的程序可能在虚拟机环境中运行,在这种情况下,虚拟机中缺少键盘钩子并不能证明什么。键盘记录可能发生在虚拟机的宿主软件中。

从用户界面的角度来说,桌面是一个安全边界。一旦你让某人在你的桌面上运行,这就意味着你信任他们。 因为现在他们可以向你的程序发送随机消息、注入钩子、攻击你的窗口句柄、编辑你的菜单,并且通常还会在各种应用程序进程中晃来晃去,图谋不轨。

这就是为什么让Windows服务与桌面交互是一个如此可怕的错误。通过允许和桌面交互,你就开始信任那些不应该信任的安全上下文了。 当然,它可以让你的Windows服务操控该桌面上的对象,但同时,它也可以让该桌面上的对象操控你的服务。这是一把双刃剑,在亲自行动之前,最好弄清楚其中的利害关系。

总结

安全问题无小事,切不可高估人性。

这又使我想起了目前正在开发的拓扑梅尔智慧办公平台(Topomel Box),我在其中引入了契约式编程的理念,对于一个组件,它不应该相信任何从外部输入的数据,它应该怀疑一切,并对数据进行有效性校验,只有通过了检验才开始它的进一步动作,也即:所有组件之间都暗含一个个确定的契约,只有满足了契约所订立的约束,才会得到相应的服务。

尼采:如果你长时间凝视深渊,深渊也在凝视你。

最后