Start-Process cannot execute psexec.exe - powershell

I have working script that use Invoke-Expression to execute psexec in Powershell ISE
<# $password is encrypted password, need to unencrypt to pass it to psexec #>
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$enable_command = "D:\PSTools\PsExec.exe $comp -u Administrator -p $str -accepteula powershell.exe c:\share\ps_enable.ps1"
Invoke-Expression $enable_command
I don't want to use Invoke-Expression because it outputs data, including PLAINTEXT password onto Powershell ISE console. But this script with Start-Process doesn't work
<# $password is encrypted password, need to unencrypt to pass it to psexec #>
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
Start-Process -FilePath D:\PSTools\PsExec.exe -ArgumentList '$comp', '-u', 'Administrator', '-p', '$str', '-accepteula', 'powershell.exe', 'c:\share\ps_enable.ps1'
How to fix?

How about just capturing the Invoke-Expression in a variable, or piping it to Out-Null?
$CmdOutput = Invoke-Expression $enable_command
or
Invoke-Expression $enable_command | Out-Null
Edit: Ok, I forgot that PSExec likes to use StdErr as a method for displaying some of it's text, and that portion would not be captured by these. What you can do is redirect StdErr to StdOut, and either pipe to Out-Null or capture it as suggested. Try this:
$CmdOutput = Invoke-Expression $enable_command 2>&1

Related

Powershell: Start-Process doesn't pass arguments to cmd.exe

These are the commands run in a powershell console (Windows 10):
$username = 'Username'
$password = 'Password'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-Process powershell.exe -Credential $credential -WindowStyle Hidden -ArgumentList "Start-Process cmd.exe -Verb RunAs -ArgumentList 'value'"
These commands work fine except that once you open cmd.exe as administrator via another user, by running this command:
echo %1
It gives me back:
%1
Literally. Instead I expect:
value
What am I doing wrong?
I just answered a question where the solution can be found using the script I provided there, with a few modifications, and invoking the chain of commands in a particular way:
RunAsProxy.ps1
# First arg should be the script path
$script = $args[0]
# Rest of args should be any script parameters
$scriptArgs = $args[1..$args.Count] -join ' '
$startProcessArgs = #{
Wait = $true
Verb = 'RunAs'
FilePath = 'cmd.exe'
ArgumentList = "/c ""$script"" $scriptArgs"
}
Start-Process #startProcessArgs
exit $LASTEXITCODE
Then call RunAsProxy.ps1 as follows as the user you want to run as, then elevate:
$command = "Command_you_want_to_run_from_cmd.exe"
$arguments = "any arguments to the program"
Start-Process -Cred $credential powershell.exe "-File ./RunAsProxy.ps1 $command $arguments"
The way this works is pretty much what you attempted, but using a pre-defined script to handle the elevation. But as you discovered you cannot call -Credential and -Verb in the same invocation on Start-Process. So this works more easily than defining the code in-line:
Run RunAsProxy.ps1 as the target user
RunAsProxy.ps1 will run cmd.exe with the provided arguments and elevate the process.
Note that if RunAsProxy.ps1 is not in the current directory you would need to provide the relative or full path to it.

Calling script in elevated mode with more than one named argument

Test.ps1
Param (
[String]$CountryCode,
[String]$FilesPath,
[String]$KeepassDatabase,
[String]$KeepassKeyFile,
[String]$EventLog,
[String]$EventSource
)
Write-Host 'Ok' -ForegroundColor Yellow
Write-Host $PSBoundParameters
Start-Sleep -Seconds 5
The goal is to call the script with named parameters in elevated mode. When using named parameters without $Credential, it works fine. The window pops up and the word Ok is displayed:
$StartParams = #{
ArgumentList = "-File `"Test.ps1`" -verb `"runas`" -FilesPath `"S:\Files`" -CountryCode `"XXX`""
}
Start-Process powershell #StartParams
When I add the Credential argument it also pops-up but I can't see anything:
$StartParams = #{
Credential = Get-Credential
ArgumentList = "-File `"Test.ps1`" -verb `"runas`" -FilesPath `"S:\Files`" -CountryCode `"XXX`""
}
Start-Process powershell #StartParams
Am I missing something super obvious here? Even when using the same credentials as the logged on user, I can't see the text.
You need to specify an absolute path to the file. The new PowerShell-process (which will run as admin) doesn't run in the same working directory as your current session.
Try:
$StartParams = #{
FilePath = "powershell.exe"
Credential = Get-Credential
Verb = "RunAs"
ArgumentList = "-File `"c:\temp\Test.ps1`" -FilesPath `"S:\Files`" -CountryCode `"XXX`""
}
Start-Process #StartParams
If you only know the relative path, use Resolve-Path to convert it. Ex:
ArgumentList = "-NoExit -File `"$(Resolve-Path test.ps1 | Select-Object -ExpandProperty Path)`" -FilesPath `"S:\Files`" -CountryCode `"XXX`""
You should also look into string format or here-string so you can avoid escaping every double quote. It makes your life easier:
#Using here-string (no need to escape double quotes)
ArgumentList = #"
-NoExit -File "$(Resolve-Path test.ps1 | Select-Object -ExpandProperty Path)" -FilesPath "S:\Files" -CountryCode "XXX"
"#
#Using string format
ArgumentList = '-NoExit -File "{0}" -FilesPath "{1}" -CountryCode "{2}"' -f (Resolve-Path test.ps1 | Select-Object -ExpandProperty Path), "S:\Files", "XXX"

Powershell command-line with Autologon.exe

Has anyone made the 'Autologon.exe for Windows v3.10' work with PowerShell v5.1?
Execution 1:
As administrator the following is run:
.\Autologon.exe -n guest10 -d test.com -p Password1 -accepteula yes
Error 1:
Execution 2:
As administrator in powershell the following is run:
.\Autologon.exe guest10 test.com Password1
Error2: Nothing happens
Execution 3:
As administrator in powershell the following is run:
$obj=.\Autologon.exe
$name ="guest10"
$domain="test"
$pass="Password1"
& $obj $name $domain $pass
Error3:
The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name, a script block, or a CommandInfo object.
I generally use Start-Process with the ArgumentList parameter to run programs with arguments:
$autologon = "C:\folder\Autologon.exe"
$username = "guest10"
$domain = "domain"
$password = "Password1"
Start-Process $autologon -ArgumentList $username,$domain,$password
Or you can put them directly into the command:
Start-Process "C:\folder\Autologon.exe" -ArgumentList "guest10","domain","Password1"
This worked for me:
Start-Process -FilePath $exePath -ArgumentList "/accepteula", $user, $domain, $password -Wait
It's very picky about quote placement.

Starting Powershell elevated from PSExec (enable-psremoting)

I'm trying to enable-psremoting with PSexec on my servers with the following command:
psexec.exe \\server cmd /c "echo . | powershell (-verb runas -argumentlist (enable-psremoting -force))"
but it doesn't work. I'm guessing I'm messing up my double quotes. Any help?
Sune:)
Thanks for commenting all! I found out how to do it, and this is the completed code:
$user = "youruser"
$p = Read-Host "Enter domain password for $adminuser"
cls
$expression1 = "enable-psremoting -force"
$commandBytes1 = [System.Text.Encoding]::Unicode.GetBytes($expression1)
$encodedCommand1 = [Convert]::ToBase64String($commandBytes1)
$expression2 = "Set-ExecutionPolicy remotesigned -Force”
$commandBytes2 = [System.Text.Encoding]::Unicode.GetBytes($expression2)
$encodedCommand2 = [Convert]::ToBase64String($commandBytes2)
$expression3 = "Restart-Service winrm”
$commandBytes3 = [System.Text.Encoding]::Unicode.GetBytes($expression3)
$encodedCommand3 = [Convert]::ToBase64String($commandBytes3)
foreach ($server in (get-content c:\temp\enablepsremotinglist.txt))
{
echo " "
echo "Running on $server"
echo "--------------------------------------- "
echo " "
psexec.exe \\$server -h -u no\$user -p $p cmd /c "echo . | powershell -EncodedCommand $encodedCommand1"
psexec.exe \\$server -h -u no\$user -p $p cmd /c "echo . | powershell -EncodedCommand $encodedCommand2"
psexec.exe \\$server -h -u no\$user -p $p cmd /c "echo . | powershell -EncodedCommand $encodedCommand3"
}
I hope this can be of help to someone else one day:)
PS: Please keep in mind that this send your adminpassword as clear text..
It looks like you are trying to invoke PowerShell to run elevated. This might not be possible to do remotely... I was able to get this to work against a machine without UAC enabled (2003 server):
$c = Get-Credential
$u = $c.UserName
$p = $c.GetNetworkCredential().Password
$path = "C:\SysinternalsSuite"
& "$path\psexec.exe" \\server -u $u -p $p powershell.exe -Command "Enable-PSRemoting -Force"
For some reason though I had to press enter a couple times on the shell for it to keep spitting out output and eventually return me to a prompt. Not sure what's up with that...
You don't need PSExec for that. Check this script by PowerShell developer Lee.
http://poshcode.org/2141

PSExec never completes when run inside start-job

I'm trying to execute a cmd file on a list of 48 computers. I don't want to execute and wait for completion sequentially because each cmd takes about 10 minutes to complete. WinRM isn't an option. Neither is WMI. PSExec is an option....but I can't seem to make it work inside of Start-Job.
I'm doing something like:
$sb = {
param
(
$computer = "serverw01",
$userid = "domain2\serviceid",
$password = 'servicepw',
$command = "cd /d d:\ && updateAll.cmd"
)
d:\eps\pstools\PsExec.exe -u $userid -p $password "\\$($computer)" cmd /c $command
}
foreach ($computer in Get-Content "D:\Data\serverlist.txt") {
Start-Job $sb -ArgumentList $computer
}
This creates a bunch of jobs....but the never complete and if I Receive-Job on any of them i get back
PS> get-job | receive-job -Keep
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
PsExec v1.98 - Execute processes remotely
Copyright (C) 2001-2010 Mark Russinovich
Sysinternals - www.sysinternals.com
it executes just fine if I run the function like:
& $sb -computer "serverw01"
Initiating script is run in Powershell v2.0 on Server 2008r2 box
I've tried it on a box in domain2 while logged in with a domain admin userid (same result).
Try this for the psexec command, ensuring you include "-d" to not wait for response, and put the computer variable right after psexec:
d:\eps\pstools\psexec "\\$($computer)" /accepteula -u $userid -p $password -d cmd /c $command
This hanging issue occurs on Win2003 and Win2008 servers.
Most people solve this issue with a workaround like echoing and piping so that powershell gets some input from STDIN.
But there exists a solution within powershell. Just start powershell with the option -inputformat none like:
powershell -inputformat none -command ...
please try the -accepteula parameter to psexec
like
d:\eps\pstools\PsExec.exe -accepteula -u $userid -p $password
from
$computerList = Get-Content "D:\Data\serverlist.txt"
$sb =
{
param($name)
}
$computer = $name
$userid = "domain2\serviceid"
$password = 'servicepw'
$command = "cd /d d:\ && updateAll.cmd"
d:\eps\pstools\PsExec.exe -u $userid -p $password \\$computer cmd /c $command
{
}
foreach ($computer in $computerLinst) {
Start-Job $sb -ArgumentList $computer
}