CreateProcess() Windows API Command-Line Utility
A complete, robust command-line utility to construct highly customized calls to the CreateProcess() Windows API to start new processes. Released under a MIT or LGPL license.
This project is intended primarily for use from batch files (.bat) to execute other programs. If it can be done with CreateProcess(), it can be done with this command-line program.
Why would you need this? One use-case would be for programs that don't play nice even with the 'start' command. For example, Apache 'httpd.exe' hangs the command-line even with 'start /B /MIN' but running this program with
/f=DETACHED_PROCESS to start Apache and it runs completely in the background. I developed this initially for Apache (way overkill for one feature), but I've had need for this program for other things on many different occasions, including starting processes from scripting languages that don't offer sufficient facilities on Windows.
Learn about security tokens, advanced usage of the CreateProcess command-line tool, and much more:
- Command-line action!
- Verbose mode tells you exactly how CreateProcess() will be called. No more guessing!
- Can redirect stdin, stdout, and stderr to TCP/IP sockets. Avoid blocking on anonymous pipes or storing output in files!
- Can use named mutexes and semaphores to control how many processes can run at the same time.
- Start elevated processes (UAC support).
- Start child processes as any valid user without requiring the user's credentials. Including the powerful NT AUTHORITY\SYSTEM account!
- Pre-built binaries using Visual Studio (statically linked C++ runtime, minimal file size of ~162K, direct Win32 API calls).
- Console and Windows subsystem variants.
- Unicode support.
- Offers almost everything CreateProcess() offers plus a couple of nice extras (e.g. output the process ID to a file).
- Has a liberal open source license. MIT or LGPL, your choice.
- Sits on GitHub for all of that pull request and issue tracker goodness to easily submit changes and ideas respectively.
Running the command by itself will display the options:
(C) 2021 CubicleSoft. All Rights Reserved. Syntax: createprocess [options] EXEToRun [arguments] Options: /v Verbose mode. /w[=Milliseconds] Waits for the process to complete before exiting. The default behavior is to return immediately. If Milliseconds is specified, the number of milliseconds to wait. Return code, if any, is returned to caller. /pid=File Writes the process ID to the specified file. /term Used with /w=Milliseconds. Terminates the process when the wait time is up. /runelevated Calls CreateProcess() as a high Integrity Level elevated process. /w should be specified before this option. May trigger elevation. Not compatible with /term when not elevated. /elevatedtoken Uses an elevated token to create a child process. May create a temporary SYSTEM service to copy the primary token via undocumented Windows kernel APIs. /systemtoken Uses a SYSTEM token to create a child process. May create a temporary SYSTEM service to copy the primary token via undocumented Windows kernel APIs. /usetoken=PIDorSIDsAndPrivileges Uses the primary token of the specified process ID, or a process matching specific comma-separated user/group SIDs and/or a process with specific privileges. May trigger elevation. See /elevatedtoken. /createtoken=Parameters Creates a primary token from scratch. May trigger elevation. See /elevatedtoken. Uses an undocumented Windows kernel API. The 'Parameters' are semicolon separated: UserSID; GroupSID:Attr,GroupSID:Attr,...; Privilege:Attr,Privilege:Attr,...; OwnerSID; PrimaryGroupSID; DefaultDACL; SourceInHex:SourceLUID /mergeenv Merges the current environment with another user environment. Use with /elevatedtoken, /systemtoken, /usetoken, /createtoken. /mutex=MutexName Creates a mutex with the specified name. Use the named mutex with /singleton or other software to detect an already running instance. /singleton[=Milliseconds] Only starts the target process if named /mutex is the only instance. If Milliseconds is specified, the number of milliseconds to wait. /semaphore=MaxCount,SemaphoreName Creates a semaphore with the specified name and limit/count. Use the named semaphore with /multiton to limit the number of running processes. /multiton[=Milliseconds] Checks or waits for a named /semaphore. If Milliseconds is specified, the number of milliseconds to wait. /f=PriorityClass Sets the priority class of the new process. There is only one priority class per process. The 'PriorityClass' can be one of: ABOVE_NORMAL_PRIORITY_CLASS BELOW_NORMAL_PRIORITY_CLASS HIGH_PRIORITY_CLASS IDLE_PRIORITY_CLASS NORMAL_PRIORITY_CLASS REALTIME_PRIORITY_CLASS /f=CreateFlag Sets a creation flag for the new process. Multiple /f options can be specified. Each 'CreateFlag' can be one of: CREATE_DEFAULT_ERROR_MODE CREATE_NEW_CONSOLE CREATE_NEW_PROCESS_GROUP CREATE_NO_WINDOW CREATE_PROTECTED_PROCESS CREATE_PRESERVE_CODE_AUTHZ_LEVEL CREATE_SEPARATE_WOW_VDM CREATE_SHARED_WOW_VDM DEBUG_ONLY_THIS_PROCESS DEBUG_PROCESS DETACHED_PROCESS INHERIT_PARENT_AFFINITY /dir=StartDir Sets the starting directory of the new process. /desktop=Desktop Sets the STARTUPINFO.lpDesktop member to target a specific desktop. /title=WindowTitle Sets the STARTUPINFO.lpTitle member to a specific title. /x=XPositionInPixels Sets the STARTUPINFO.dwX member to a specific x-axis position, in pixels. /y=YPositionInPixels Sets the STARTUPINFO.dwY member to a specific y-axis position, in pixels. /width=WidthInPixels Sets the STARTUPINFO.dwXSize member to a specific width, in pixels. /height=HeightInPixels Sets the STARTUPINFO.dwYSize member to a specific height, in pixels. /xchars=BufferWidthInCharacters Sets the STARTUPINFO.dwXCountChars member to buffer width, in characters. /ychars=BufferHeightInCharacters Sets the STARTUPINFO.dwYCountChars member to buffer height, in characters. /f=FillAttribute Sets the STARTUPINFO.dwFillAttribute member text and background colors. Multiple /f options can be specified. Each 'FillAttribute' can be one of: FOREGROUND_RED FOREGROUND_GREEN FOREGROUND_BLUE FOREGROUND_INTENSITY BACKGROUND_RED BACKGROUND_GREEN BACKGROUND_BLUE BACKGROUND_INTENSITY /f=StartupFlag Sets the STARTUPINFO.dwFlags flag for the new process. Multiple /f options can be specified. Each 'StartupFlag' can be one of: STARTF_FORCEONFEEDBACK STARTF_FORCEOFFFEEDBACK STARTF_PREVENTPINNING STARTF_RUNFULLSCREEN STARTF_TITLEISAPPID STARTF_TITLEISLINKNAME /f=ShowWindow Sets the STARTUPINFO.wShowWindow flag for the new process. There is only one show window option per process. The 'ShowWindow' value can be one of: SW_FORCEMINIMIZE SW_HIDE SW_MAXIMIZE SW_MINIMIZE SW_RESTORE SW_SHOW SW_SHOWDEFAULT SW_SHOWMAXIMIZED SW_SHOWMINIMIZED SW_SHOWMINNOACTIVE SW_SHOWNA SW_SHOWNOACTIVATE SW_SHOWNORMAL /hotkey=HotkeyValue Sets the STARTUPINFO.hStdInput handle for the new process. Specifies the wParam member of a WM_SETHOKEY message to the new process. /socketip=IPAddress Specifies the IP address to connect to over TCP/IP. /socketport=PortNumber Specifies the port number to connect to over TCP/IP. /sockettoken=Token Specifies the token to send to each socket. Less secure than using /sockettokenlen and stdin. /sockettokenlen=TokenLength Specifies the length of the token to read from stdin. When specified, a token must be sent for each socket. /stdin=FileOrEmptyOrsocket Sets the STARTUPINFO.hStdInput handle for the new process. When this option is empty, INVALID_HANDLE_VALUE is used. When this option is 'socket', the /socket IP and port are used. When this option is not specified, the current stdin is used. /stdout=FileOrEmptyOrsocket Sets the STARTUPINFO.hStdOutput handle for the new process. When this option is empty, INVALID_HANDLE_VALUE is used. When this option is 'socket', the /socket IP and port are used. When this option is not specified, the current stdout is used. /stderr=FileOrEmptyOrstdoutOrsocket Sets the STARTUPINFO.hStdError handle for the new process. When this option is empty, INVALID_HANDLE_VALUE is used. When this option is 'stdout', the value of stdout is used. When this option is 'socket', the /socket IP and port are used. When this option is not specified, the current stderr is used. /attach[=ProcessID] Attempt to attach to a parent OR a specific process' console. Also resets standard handles back to defaults.
C:\>createprocess /f=DETACHED_PROCESS "C:\Program Files\Apache\httpd.exe"
That starts Apache with a detached console so it runs entirely in the background.
C:\>whoami my-pc\john-doh C:\>whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ============================= ==================================== ======== SeShutdownPrivilege Shut down the system Disabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeUndockPrivilege Remove computer from docking station Disabled SeIncreaseWorkingSetPrivilege Increase a process working set Disabled SeTimeZonePrivilege Change the time zone Disabled C:\>set MYVAR=123 C:\>createprocess /w /systemtoken /mergeenv C:\Windows\System32\cmd.exe Microsoft Windows [Version 10.0.19042.867] (c) 2020 Microsoft Corporation. All rights reserved. C:\>whoami nt authority\system C:\>whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ========================================= ================================================================== ======== SeAssignPrimaryTokenPrivilege Replace a process level token Enabled SeLockMemoryPrivilege Lock pages in memory Enabled SeIncreaseQuotaPrivilege Adjust memory quotas for a process Enabled SeTcbPrivilege Act as part of the operating system Enabled SeSecurityPrivilege Manage auditing and security log Disabled SeTakeOwnershipPrivilege Take ownership of files or other objects Disabled SeLoadDriverPrivilege Load and unload device drivers Disabled SeDebugPrivilege Debug programs Enabled ... [It's a fairly lengthy list of powerful privileges] SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Enabled C:\>set MYVAR MYVAR=123
That starts a Command Prompt child process as NT AUTHORITY\SYSTEM (the most powerful user account in Windows) in the same console session of the parent non-elevated process with full SYSTEM privileges and merges the current environment variables with the SYSTEM user's environment variables.
Learn how the various
/...token options work by watching the video linked to at the top of this repo or just look at the insane diagram.
Even the most hardcore command-line enthusiast should be drooling right now due to brain melt. Be sure to check out the source code.
Windows Subsystem Variant
createprocess.exe is intended for use with console apps,
createprocess-win.exe is intended for detached console and GUI applications. Starting
createprocess.exe in certain situations will briefly flash a console window before starting the target process. Calling
createprocess-win.exe instead will no longer show the console window.
Why not just use
createprocess-win.exe starts as a Windows GUI application, there is the tendency for it to be run in the background and may not behave as expected with various handles. The software is a little bit trickier to work with as a result. It's also a few KB larger than
There is one additional option specifically for
/attach which attempts to attach to the console of the parent process (if any) and will also reset the standard handles. The
/attach option, if used, should generally be specified before other options.
The TCP/IP socket options represent a security risk so take proper precautions. Example usage can be seen in the ProcessHelper class.
In addition, passing SOCKET handles to the target process causes problems. Sometimes the target process works just fine and sometimes it doesn't. To deal with this issue, up to three threads are started, one for each of the standard handles. Each thread routes data between its socket handle and an associated anonymous pipe of the started process. As a consequence of using the TCP/IP socket option, the
/w option is always set so that the started process is waited on (i.e. so the threads can transfer data). This doesn't exactly matter as the
/w option would be used anyway by the caller when passing socket options.
The CreateProcess() API in MSDN Library has the intimate details on most options:
- PHP Process Helper Class - Uses this software to start processes on Windows in the background with non-blocking stdin/stdout/stderr via TCP/IP sockets.
- GetTokenInformation - Dumps information about Windows security tokens (SIDs, privileges, etc) as JSON.
- GetSIDInfo - Dumps information about Windows Security Identifiers (SIDs) as JSON.