0

I am attempting to use psexec to start a process in an interactive session that has already been opened. Both my machine and the remote machine are Windows 7. Using the command from within command prompt works fine, the executable is started and is visible in the GUI.

psexec64 -accepteula -nobanner \\hostname -u domain\user -p password -h -i 2 -d C:\workingdir\subfolder\application.exe

However, when I attempt to execute the same call within a PowerShell script, it does not work. See the full script for context.

# invalid args: $psExecArgs = "-accepteula", "-nobanner", "-u domain`\${username}", "-p ${password}", "-h", "-i ${sessionId}", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
# hangs: $psExecArgs = "-accepteula", "-nobanner", "-u domain`\${username}", "-p ${password}", "-h", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
$psExecArgs = "-accepteula", "-nobanner", "-h", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
& $EchoArgsPath $psExecArgs
$result = & $PsExecPath $psExecArgs #2>$null
  • When giving all of the same arguments, the value of $result is the psexec help as if an invalid argument is given.
  • When -i 2 is removed, psexec shows in the running processes list on my machine and appears to hang; no psexecsvc process is started on the remote machine.
  • When -u and -p are removed, psexec is started but as expected, the process starts in a non-interactive session on my account on the remote machine.

I see the same kind of behavior when using pslist and pskill so I replaced those with tasklist and taskkill. I have ensured that UAC is disabled and that I can map to the Admin$ share on the remote machine using the credentials I am providing.

While typing this question I found a question suggesting that stdin might be an issue but I'm not sure if it is relevant in my case.

M Michal
  • 3
  • 1
  • 2
  • You should be using invoke-command instead. PSExec is not appropriate for a professional enterprise due to it's CVE's. – Colyn1337 Jun 21 '17 at 19:09
  • @Colyn1337 I agree that Invoke-Command and PS Remoting would be a better option but I didn't see any way to run Invoke-Command in an existing interactive session. Perhaps an option is to use Invoke-Command (to connect remotely) in combination with PsExec (to launch in a local session) to achieve my same goal? – M Michal Jun 21 '17 at 20:58
  • Under no circumstances should you be using psexec in a professional environment, at all. If you need to do an action in someone else's session you should rethink your strategy. – Colyn1337 Jun 22 '17 at 14:01

2 Answers2

1

Debugging is always your friend - if you inspect the value of $psExecArgs (in the full script) during execution you will notice that you do not provide a value for $password. Which means that you are sending -p (nothing) to psexec, which again makes psexec hangs while waiting for password input.

C:\..\foobar.ps1
cmdlet foobar.ps1 at command pipeline position 1
Supply values for the following parameters:
hostname: myhostname
username: myusername
password: mypassword
sourcedirectory: c:\mysourcedir
targetdirectory: c:\mytargetdir
executablename: myexec.exe
Hit Line breakpoint on 'C:\...\foobar.ps1:34'
[DBG]: PS C:\Users\Zerqent>> $psExecArgs
-accepteula
-nobanner
\\myhostname
-u domain\myusername
-p 
qwinsta

To avoid this in powershell, make parameters mandatory https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_functions_advanced_parameters

Update: You should also separate the username and password part to be separate entries in the list. Basically everytime you have a space in the cmd-command you create a separate list entry. So your $psexecArgs would become:

$psExecArgs = "-accepteula", "-nobanner", "-u", "domain`\${username}", "-p", "${password}", "-h", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""

Not quite sure if that redirection will work, (#2>$null), or if that should also somehow be included in the list.

Zerqent
  • 336
  • 2
  • 8
  • You are correct, uncommenting the first `# hangs` line of code, one parameter is missing. I should have left the password argument in the function until I knew for sure that I would not need it. However, even when adding that parameter, the call to psexec hangs. The answer provided by techie007 resolved the issue but you've taught me that parameters can be marked as required for _functions_ as well as `CmdletBinding`. – M Michal Jun 21 '17 at 22:10
  • Yeah, I missed the other mistake. Se update in my answer. – Zerqent Jun 22 '17 at 09:55
0

Declaring a variable like $psExecArgs = "-accepteula", "-nobanner" makes an array of strings.

You are running whatever the strings say (using &) instead of launching a process and providing arguments, so the arguments would need to be simple strings as well (not an array of strings).

Then to further muddy it, if you were to provide the arguments in a single string ($psExecArgs = "-accepteula -nobanner"), that actually only appears as one argument to PSExec, and won't work either.

So, instead of trying to run the strings, one option is to use PowerShell's Start-Process command, which expects the arguments to be fed to it in an array (as you are currently doing).

Try changing command lines like:

& $PsExecPath $psExecArgs

to something like:

Start-Process $PsExecPath $psExecArgs

You'll have to handle the return code and errors a little differently, something like:

try {
  $process = (Start-Process -FilePath $psexec -ArgumentList $psExecArgs -NoNewWindow -PassThru)
} 
catch {
  Write-Output "Error launching process!" 
  Write-Output $_.Exception.Message
  $process = $null
}
finally {
  if ($process) {
    $process.WaitForExit()
    Write-Host "Process exit code: " $process.ExitCode
  }
}
techie007
  • 1,892
  • 17
  • 24
  • changing to Start-Process worked. I was never tipped off to any specific issue with the way I was passing the arguments because `echoargs` was showing that all 9 arguments were parsed correctly. `-u`, `-p`, and `-i` also contained the correct values and were printed like `Arg 5 is <-i 2>`. Is there some difference in the way the args are parsed that would cause this mismatch? – M Michal Jun 21 '17 at 21:40
  • 1
    One minor note, I had to use `Wait-Process -InputObject $process` to get the script to wait properly instead of using `$process.WaitForExit()`. – M Michal Jun 21 '17 at 22:16