SUDO for CMD

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Eureka!
Posts: 136
Joined: 25 Jul 2019 18:25

SUDO for CMD

#1 Post by Eureka! » 28 Jul 2019 13:15

Just discovered this forum a couple of days ago and I have to say that it contains a wealth on information and groundwork research on batch mechanics. Very interesting!

One of the things I noticed is the hybrid VBSsript - batch approach used in several threads to run commands elevated.

Here is a pure batch way to accomplish the same:

SUDO.cmd

Code: Select all

@echo off

:: Create dummy script
	set RANDOM=>"%temp%\%~n0.ELEVATE"

:: File association: Run .ELEVATE always elevated
	reg add HKCU\Software\Classes\.elevate /ve /D MaartenElevate /F >nul
	reg add HKCU\Software\Classes\MaartenElevate\Shell\runas\command /ve /D "cmd.exe /c pushd \"%%w\" & start \"%~n0\" %%*" /F >nul

:: Execute dummy .ELEVATE script
	"%temp%\%~n0.ELEVATE" %*

:: Clean up
	reg delete HKCU\Software\Classes\.elevate /F >nul
	reg delete HKCU\Software\Classes\MaartenElevate /F >nul
	del /Q "%temp%\%~n0.ELEVATE"
If you start SUDO.cmd without parameters, it wll start an elevated CMD.exe. Working directory is the same as the originating CMD.
You can run internal commands as well as external commands. E.g. both SUDO dir or SUDO notepad dummy.txt will work.


How this works
  1. Create a dummy file extension (.elevate)
  2. Associate this file extension with *one* verb: RunAs.
    RunAs is Windows' predefined verb used to elevate.
    When there is no default verb defined, it will open the alphabetically first verb. Which implies that with one verb defined, that one will be used (I did my own groundwork research ;))
  3. That verb (RunAs) will cause this command to execute (elevated because of the RunAs):
    "cmd.exe /c pushd \"%%w\" & start \"%~n0\" %%*"
    Where:
    • %%w is a Windows shell variable passed to the verb. it is the current working directory
    • %%* are the SUDO parameters passed through to CMD
    • \"%~n0\" ("SUDO") is only used as the window title.
  4. Start a dummy .elevate file
  5. This will trigger the RunAs routine, causing elevation.

To summarize: a command like SUDO notepad "C:\Windows\System32\drivers\etc\hosts", started from C:\temp will (elevated) run:
cmd.exe /c pushd "C:\Temp" & start "SUDO" notepad "C:\Windows\System32\drivers\etc\hosts"

It shouldn't be too hard to integrate this method in a script that needs elevation.

Notes
It is more SU that SUDO, but I liked that name better ...
Last edited by Eureka! on 05 Aug 2019 12:10, edited 1 time in total.

bakemonogatari
Posts: 21
Joined: 08 Jul 2019 05:22

Re: Run elevated commands / programs / shell

#2 Post by bakemonogatari » 02 Aug 2019 11:34

thank you, it works very well.

Eureka!
Posts: 136
Joined: 25 Jul 2019 18:25

Re: Run elevated commands / programs / shell

#3 Post by Eureka! » 03 Aug 2019 10:22

Thank you for your feedback :thumbsup:
(I started to think the forum went dead ..)

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: SUDO for CMD

#4 Post by siberia-man » 07 Feb 2020 01:59

Very interesting solution. I have just two questions

1. Could there be the restrictions on modifying the registry?
2. I found how to simplify this solution. It works on my PC. Will it work on others?

Code: Select all

@echo off

:: Create dummy script
type nul >"%TEMP%\%~n0.elevate"

:: File association: Run .elevate always elevated
reg add "HKCU\Software\Classes\.elevate\shell\runas\command" /ve /d "cmd.exe /c cd /d \"%%w\" & start %%*" /f >nul

:: Execute dummy script
"%TEMP%\%~n0.elevate" %*

:: Clean up
reg delete "HKCU\Software\Classes\.elevate" /f >nul
del /q "%TEMP%\%~n0.elevate"
Last edited by siberia-man on 08 Feb 2020 23:00, edited 1 time in total.

Eureka!
Posts: 136
Joined: 25 Jul 2019 18:25

Re: SUDO for CMD

#5 Post by Eureka! » 07 Feb 2020 07:12

siberia-man wrote:
07 Feb 2020 01:59
1. Could there be the restrictions on modifying the registry?
All registry keys are Current User settings and not under control of TrustedInstaller, so there should be no restrictions.
Are you experiencing any?

siberia-man wrote:
07 Feb 2020 01:59
2. I found how to simplify this solution. It works on my PC. Will it work on others?
Yes, that will work. That is the way Windows did things in older versions of Windows (previous millennium era).
And thanks to backwards compatibility that still works today.

I decided to go for the ProgID approach that even CMD uses these days (through assoc and ftype).

Note: these utilities only look at Local Machine registry entries and don't understand Current User settings. Otherwise I would probably have used assoc .elevate=MaartenElevate / ftype MaartenElevate= .....

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: SUDO for CMD

#6 Post by siberia-man » 07 Feb 2020 11:47

Are you experiencing any?
No. I asked because I remember Windows have a lot of uncertain restrictions. After migrating from WIN7 to WIN10 I encountered trouble with executing mklink /d which was permitted under WIN7 and is not permitted under WIN10. I started to look for solution how to elevate privileges easily as much as possible. I invented the script using PowerShell which runs elevated CMD. Comparing with your short and elegant script I see that mine looks ugly. It runs powershell which starts new process cmd which finally starts application. I leave it here just for fun.

Code: Select all

::NAME
::
::    sudo - execute a command with the elevated privileges
::
::SYNOPSIS
::
::    sudo
::    sudo COMMAND [OPTIONS]
::
::DESCRIPTION
::
::sudo allows to run a command with optional arguments with the elevated
::privileges. By default, if no any options specified, it runs the
::command interpreter. The command can be any of binary executables,
::batch scripts or documents supposed to be open.
::
::REQUIREMENTS
::
::The script requires PowerShell to be installed on the system.
@echo off

if /i "%~1" == "/?" goto :print_usage
if /i "%~1" == "/h" goto :print_usage

call :check_reqs || goto :EOF

setlocal

set "SUDO_HIDDEN="

if "%~1" == "" (
	call :sudo /s /k cd /d "%CD%"
	goto :EOF
)

for %%x in ( .bat .cmd ) do if /i "%~x1" == "%%x" (
	call :sudo /s /k cd /d "%CD%" "&&" %*
	goto :EOF
)

set "SUDO_HIDDEN=-WindowStyle Hidden"
call :sudo /c start /d "%CD%" %*

goto :EOF


:sudo
endlocal && powershell -Command Start-Process "cmd.exe" -Args '%*' %SUDO_HIDDEN% -Verb RunAs
goto :EOF


:print_usage
for /f "tokens=* delims=:" %%s in ( 'findstr "^::" "%~f0"' ) do echo:%%s
goto :EOF


:check_reqs
for %%p in ( powershell.exe ) do if "%%~$PATH:p" == "" (
	echo:%%~p is required>&2
	exit /b 1
)
goto :EOF
Last edited by siberia-man on 08 Feb 2020 23:02, edited 1 time in total.

jfl
Posts: 226
Joined: 26 Oct 2012 06:40
Location: Saint Hilaire du Touvet, France
Contact:

Re: SUDO for CMD

#7 Post by jfl » 08 Feb 2020 04:19

This works great indeed!

Now, what would be very nice is to find a way to redirect stdin/stdout/stderr from the elevated shell, back into the original shell. 8)
(Like Unix' sudo does!)

Eureka!
Posts: 136
Joined: 25 Jul 2019 18:25

Re: SUDO for CMD

#8 Post by Eureka! » 08 Feb 2020 05:42

I like the idea, but that would be very hard to realize.
Modern Windows uses privilege isolation (UIPI) and that prevents processes started as a regular user to "talk to" elevated processes.
You would probably need to write your own terminal window to handle that ..


@siberia-man:
I saw that you also replaced PUSHD with CD.
Elevated CMD will default start in %windir%\system32.
Replace it with CD /D if you have more than one volume available in your system.

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: SUDO for CMD

#9 Post by siberia-man » 08 Feb 2020 23:10

Thank you for your comment. Indeed I used CD instead PUSHD to avoid possible POPD in the shell. And I forgot that CD works within a drive by default. I fixed my mistake in all my examples in this thread.

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: SUDO for CMD

#10 Post by siberia-man » 14 Sep 2020 08:46

a way to redirect stdin/stdout/stderr from the elevated shell, back into the original shell
It looks like it is solved in gsudo. Sorry, it's C#, not a pure batch.

Post Reply