Defense in depth -- the Microsoft way (part 14): incomplete, misleading and dangerous documentation Nov 24 2013 06:39PM
Stefan Kanthak (stefan kanthak nexgo de)
Hi @ll,

here's another (well-known, but undocumented) idiosyncrasy of Windows'
CreateProcess*() functions with a "nice" side-effect:-P

From <http://msdn.microsoft.com/library/ms682425.aspx>:

| BOOL WINAPI CreateProcess(
| _In_opt_ LPCTSTR lpApplicationName,
| _Inout_opt_ LPTSTR lpCommandLine,
| To run a batch file, you must start the command interpreter; set
| lpApplicationName to cmd.exe and set lpCommandLine to the following
| arguments: /c plus the name of the batch file.

This is but wrong (and of course dangerous too: you should NEVER set
lpApplicationName to an unqualified filename, but ALWAYS use the fully
qualified pathname; see <http://support.microsoft.com/kb/2269637>
and <http://support.microsoft.com/kb/2389418>)!

Now the REAL behaviour (of Windows NT4, Windows NT5.x, Windows NT6.x):

CreateProcess("<pathname>.cmd", ...)
CreateProcess("<pathname>.bat", ...)
CreateProcess(NULL, "<pathname>.cmd[ ...]", ...)
CreateProcess(NULL, "<pathname>.bat[ ...]", ...)

(and of course CreateProcessAsUser(), CreateProcessWithLogonW() and
CreateProcessWithTokenW() too) execute a rogue program CMD.EXE from
the 'application directory' (i.e. the directory where the program that
calls CreateProcess*() is located) instead of the expected %COMSPEC%
alias %SystemRoot%\System32\cmd.exe, with the command line set to
"cmd /c \"<pathname>.cmd\"" resp. "cmd /c <pathname>.cmd[ ...]".

From <http://msdn.microsoft.com/library/ms682425.aspx>:

| lpCommandLine [in, out, optional]
| If the file name does not contain an extension, .exe is appended.
| If the file name does not contain a directory path, the system
| searches for the executable file in the following sequence:
| 1. The directory from which the application loaded.
| 2. The current directory for the parent process.
| 3. The 32-bit Windows system directory.

JFTR: ShellExecute*() calls CreateProcess*() to start <pathname>.bat
and <pathname>.cmd, so Windows Explorer (and of course any
other program calling ShellExecute*() too) start CMD.EXE from
their 'application directory' or the 'current working directory'

The 'application directory' of Windows Explorer is %SystemRoot%,
and Windows Explorer sets the 'current working directory' to the
path of the file to be opened.

%SystemRoot%\System32\CMD.EXE is found via the documented search
path ... until someone creates a CMD.EXE in %SystemRoot% or the
'current working directory' (i.e. the directory where
<filename>.bat or <filename>.cmd is located).

FIX (for ShellExecute*() and Windows Explorer):

change the value of the default registry entries of
from @="%1 %*"
to @=expand:"%SystemRoot%\\System32\\cmd.exe /C Call \"%L\" %*"
or @=expand:"\"%COMSPEC%\" /C Call \"%L\" %*"

Additionally, see <http://support.microsoft.com/kb/905890> as well
as <http://msdn.microsoft.com/library/aa365527.aspx> and set

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager]

stay tuned
Stefan Kanthak

PS: when <filename>.bat or <filename>.cmd are started from Windows
Explorer the console window of the new process shows the icon of
the CMD.EXE found in the 'current working directory' (i.e. the
directory where <filename>.bat or <filename>.cmd is located), not
the icon of the command processor %SystemRoot%\System32\cmd.exe
... independent of the above mentioned fixes!

But that's just another of Windows' many idiosyncrasies!


2013-10-23 informed vendor

2013-10-24 vendor replies: see


2013-10-24 NO, this does NOT describe the behaviour of CreateProcess()
or ShellExecute() for *.CMD and *.BAT

2013-10-24 vendor replies: MSRC case 15734 opened


2013-11-18 requested status from vendor

2013-11-24 no answer, report published

[ reply ]


Privacy Statement
Copyright 2010, SecurityFocus