灵感来自今天的 DailyWTF 文章。
作者声称,C:\Program.exe
单击快捷方式(例如)时将执行文件C:\Program Files\Doom 2\doom2.exe -nomusic
。
据推测,Windows 首先尝试C:\Program
使用参数进行调用Files\Doom 2/doom2.exe -nomusic
。
如果没有C:\Program.exe
,则尝试C:\Program Files\Doom
使用参数2/doom2.exe -nomusic
。
如果没有C:\Program Files\Doom.exe\
,它最终会尝试C:\Program Files\Doom 2\doom2.exe -nomusic
并成功。
在我看来这完全是胡说八道。我简直不敢相信事情竟然会这样发展。一位评论者说得好:
我很难相信任何发布的 Windows 版本都曾采用过 OP 描述的反复试验方法。
我绝对相信 Windows 的发布版本默认具有愚蠢的行为。我亲身经历过很多次。
我不相信 Windows 的发布版本有这正如文章中所描述的那样,这是非常愚蠢的行为。这是一个非常严重的安全漏洞,直到某篇 Daily WTF 随机投稿揭露它,才被人们注意到,至少在十年后,因为那一定是 XP 之前的 Windows 版本。
为了清晰起见进行编辑:以下是我自己测试的方法。
- 将 notepad.exe 复制到 C:\program.exe
- 运行 C:\program files\Internet explorer\iexplore.exe
- 记事本打开。这是意料之中的,因为它找到了名为 C:\program 的文件
- 将 progam.exe 移动到 C:\program files\Internet.exe
- 运行 C:\program files\Internet explorer\iexplore.exe
根据本文作者的说法(以及微软的这篇文章),记事本应该仍会打开。但是它却没有打开,命令失败并显示以下消息:
C:\program is not recognized as an internal or external command, operable program or batch file.
再次强调,我并不是在争论文章中关于将调用 C:\program 的说法。我争论的是 Windows 会递归尝试每个目录,直到找到匹配项。
那么,任何版本的 Windows 都以这种方式运行吗?
答案1
自从添加了长文件名以来,从 Windows 95 到 Windows 7,每个版本的 Windows 都以这种方式工作。
这是行为记录:
这应用程序名称参数可以是无效的。在这种情况下,模块名称必须是 命令行字符串。如果您使用的是包含空格的长文件名,请使用带引号的字符串来指示文件名的结束位置和参数的开始位置;否则,文件名会产生歧义。例如,考虑字符串“c:\program files\sub dir\program name”。此字符串可以用多种方式解释。系统会尝试按以下顺序解释各种可能性:
c:\program.exe files\sub dir\program name c:\program files\sub.exe dir\program name c:\program files\sub dir\program.exe name c:\program files\sub dir\program name.exe
至于为什么它这样问——这样它不会破坏无法正确处理文件名中空格的程序。
编辑
看来“运行”命令不会这样运行 - 它必须添加一些额外的逻辑来处理这种情况。但是尝试从其他任何地方运行 - 包括CreateProcess
直接使用该函数,这是大多数应用程序运行命令所用的方法。
看看这个行为的实际效果:
- 打开管理命令提示符
- 跑步:
copy c:\Windows\System32\notepad.exe c:\program.exe
- 跑步:
c:\Program Files\Internet Explorer\iexplore.exe
- 记事本会打开并提示你找不到
Files\Internet Explorer\iexplore.exe
c:\Program Files\Internet Explorer\iexplore.exe
在运行选项中输入,IE 将正确打开。
编辑2就您的示例而言C:\program files\internet.exe
;我认为这是命令行解释器在作祟。它试图处理命令行并将其标记为由空格分隔的参数。因此,它将其C:\program
作为第一个标记,并将其解释为程序名称,其余部分则作为参数。
为了进行测试,我创建了一个CreateProcess
直接调用的小应用程序,它的行为与文档中所述完全一致。您的C:\program files\internet.exe
示例将启动C:\program files\internet.exe
。因此,行为似乎取决于命令的运行方式 - 某些东西可能在将命令行传递给之前对其进行了处理CreateProcess
。
示例程序:
#include <Windows.h>
void main()
{
STARTUPINFO si = {0};
si.cb= sizeof(si);
PROCESS_INFORMATION pi = {0};
CreateProcess(NULL, "c:\\program files\\internet explorer\\iexplore.exe",
NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
答案2
我只是想对之前的答案做些补充。
虽然可以通过努力、糟糕的编程(不是 RTFM)或由该特定防病毒程序引起的无法验证的完美风暴来强制执行此行为,但没有什么会导致本文描述的行为。绝对不可能正确创建的快捷方式(例如,以引号为目标的“C:\Program Files\Microsoft\Office\Word.exe”)运行 C:\Program.exe。Firefox 也是如此。见鬼,基本上不可能创建无法正确转义的快捷方式,因为它是智能完成的。
如果您在桌面上创建指向 Firefox 的快捷方式,它将被正确转义。如果您右键单击 -> 属性并尝试删除引号,即使 C:\Program.exe 存在,它也会在您点击应用时自动插入它们。当它解析它时,我猜它要么优先考虑文件夹,要么将最后一个“\”之前的所有内容视为路径的一部分。只有在 Program 和 Files 之间插入两个空格时,它才会被解析为指向带有参数的 C:\Program.exe。如果您可以在文本编辑器中编辑快捷方式(它不是纯文本),它可能会起作用。
与快捷方式非常相似,运行对话框也能正确解析字符串。只有在相对低级的命令控制台中,它才会错误地调用 C:\Program.exe,但不会尝试其他各种可能性。也就是说,它会错误地尝试调用“C:\Program.exe”,但不会尝试调用“C:\Program Files\Internet.exe”或其他任何内容,即使存在这些可能性。它会返回一个错误,表示找不到 C:\Program.exe。
除此之外,当 C:\ 文件夹中有 Program.exe 时,它会在启动时发出警告并询问您是否要重命名它。这已在 XP、Vista、Windows 7 中得到验证,我现在可以验证 Windows 8(http://goo.gl/eeNCp)。或许这在 Windows 9x 中是可能的,但我对此表示怀疑。
底线是,这是显而易见的,没有 Windows 程序员会犯这个错误。