BugTraq
Defense in depth -- the Microsoft way (part 29): contradicting, ambiguous, incomplete documentation Feb 21 2015 02:43PM
Stefan Kanthak (stefan kanthak nexgo de)
Hi @ll,

the MSDN documents the BRAINDEAD behaviour of the functions
CreateProcess() <https://msdn.microsoft.com/en-us/library/ms682425.aspx>,
CreateProcessAsUser() <https://msdn.microsoft.com/en-us/library/ms682429.aspx>
CreateProcessWithLogonW() <https://msdn.microsoft.com/en-us/library/ms682431.aspx>
CreateProcessWithTokenW() <https://msdn.microsoft.com/en-us/library/ms682434.aspx>
for an unquoted "long" pathname of the executable in command lines:

| [...] the module name must be the first white space-delimited token in
| the lpCommandLine string. If you are using a long file name that contains
| a space, use quoted strings to indicate where the file name ends and the
| arguments begin; otherwise, the file name is ambiguous.
| For example, consider the string "c:\program files\sub dir\program name".
| This string can be interpreted in a number of ways. The system tries
| to interpret the possibilities in the following order: ~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 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
...
| [...] the first white space-delimited token of the command line
| specifies the module name. If you are using a long file name that
| contains a space, use quoted strings to indicate where the file name
| ends and the arguments begin [...] If the file name does not contain
| an extension, .exe is appended. [...] if the file name contains a path,
| .exe is not appended. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~

1. self-contradictory/ambiguous:

If the second underlined clause of the documentation were correct,
and the usual definition of path(name) ['] is assumed (so "c:\",
"c:\program files\sub" and "c:\program files\sub dir\program"
qualify as pathnames), the interpretation of the string
"c:\program files\sub dir\program name"
given above would be wrong.

The interpretation given above but matches the observed behaviour
of the CreateProcess*() functions, therefore the underlined clause
of the documentation is WRONG and should be removed!

2. incomplete/ambiguous:

the documentation does not specify what "tries to interpret the
possibilities" exacly means: using the example given above, is
CreateProcess*() expected to skip
"c:\program.exe", "c:\program files\sub.exe" and/or
"c:\program files\sub dir\program.exe" if they exist but are not
executable

a) due to invalid file contents?

Observed behaviour:
CreateProcess*() tries to execute c:\program.exe etc. and returns
ERROR_BAD_EXE_FORMAT, ERROR_EXE_MARKED_INVALID,
ERROR_INVALID_EXE_SIGNATURE, etc.

b) due to insufficient permissions?

Observed behaviour:
CreateProcess*() tries to execute c:\program.exe etc. and returns
ERROR_ACCESS_DENIED!

c) because they are an unsupported or unknown [²] reparse point?

Observed behaviour:
CreateProcess*() tries to execute c:\program.exe etc. and returns
ERROR_CANT_ACCESS_FILE, ERROR_ACCESS_DENIED, ERROR_FILE_NOT_FOUND,
etc.

d) because they are a directory (including directories overlaid with
a reparse point), a mount point, a junction to a directory or a
symlink to a directory?

Observed behaviour:
in contradiction to MSKB 812486 [³] CreateProcess*() does not
try to execute a directory c:\program.exe etc. and skips it.

Skipping over directories or reparse points targetting
directories is but surprising behaviour, since
CreateProcess*("<directory>", NULL, ...) and
CreateProcess*(NULL, "<directory>", ...) return
(as expected) ERROR_ACCESS_DENIED!

3. incomplete/surprising:

The observed behaviour for
CreateProcess(NULL, "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe", ...)
is: CreateProcess*() tries to execute "C:\Program.exe" and
"C:\Program Files (x86)\Internet.exe", but NOT
"C:\Program Files.exe"

WTF?
Why is "C:\Program Files.exe" NOT a "possibility to try"?

4. incomplete:

when CreateProcess*() is called (for example) with the command
line "c:\program files\sub dir\program name" and plays try&error,
the executed application does NOT receive the original command line,
but a MODIFIED command line:

- "c:\program files\sub.exe" dir\program name
- "c:\program files\sub dir\program.exe" name
- "c:\program files\sub dir\program.exe name.exe"

i.e. the pathname of the found executable gets quoted if it contains
a space.

The documentation of the function GetCommandLine()
<https://msdn.microsoft.com/en-us/library/ms683156.aspx>
but misses this completely!

Stay tuned!

regards
Stefan Kanthak

['] as soon as a name contains a single '\' or ':' it is a pathname!
Cf. <https://msdn.microsoft.com/en-us/library/aa365247.aspx>

[²] <https://msdn.microsoft.com/en-us/library/aa365503.aspx>:

| When the file system opens a file

or directory (obvious omission added)

| with a reparse point, it attempts to find the file system filter
| associated with the data format identified by the reparse tag.
| If a file system filter is found, the filter processes the file

or directory (obvious omission added)

| as directed by the reparse data. If a file system filter is not
| found, the file open operation fails.

[³] <https://support.microsoft.com/kb/812486/en-us>:

| * There is a file or folder on your computer's hard disk that
| has the same name as a file or folder in the path to the
| service's executable file.
|
| For example, if the path of the executable file for a service
| is C:\Program Files\MyProgram\MyService.exe, and if a folder
| that is named C:\Program also exists on your hard disk, Windows
| locates the C:\Program folder on your hard disk before the
| C:\Program Files\MyProgram\My Service.exe file, and then tries
| to run it.

[ reply ]


 

Privacy Statement
Copyright 2010, SecurityFocus