powershellpathpsexec

Run PsExec with relative


I try to run a script on a remote computer with PsExec.

C:\static\path\to\thePSTools\Folder\PsTools\PsExec.exe $IPAddress -i -s -u $Login -p $LoginPassword Powershell $PathToFile

But I just can run the the PsExec Command when writing like the code above, meaning, running PsExec from an absolute Path.

The thing is when my Program is installed on another machine, then I don't know the static path of my PsExec. So I need a relative Path. I tried a few things but none of it worked

Like this with Push-Location:

Push-Location $PSToolsPath PsExec.exe $IPAddress /accepteula $PathToFile

Or something like this:

$Path + PsExec.exe $IPAddress /accepteula $PathToFile

But I can't run it.

I know how to get the relative Path, but the question is, how to run, or is it even possible.

I am open for any edit on my question. Since its kind of complicated to explain.


Solution

  • Don't use PSExec. While useful, PSExec is a CLI program for running commands over WinRM. PowerShell already has PSRemoting built in (WinRM is the backbone of PSRemoting) and you can use New-PSSession, Enter-PSSession, Invoke-Command, etc. in order to access remote machines you control access to:

    Note: You must use a server name to connect to the server by default. If the server is not part of your domain or you want to use an IP, you must configure your local WinRM settings to trust that IP or server name. Alternatively, you can configure WinRM over SSL to avoid having to trust servers by IP, but your client server will need to both trust the certificate presented by WinRM over SSL, and the Subject or Subject-Alternative Name of the certificate must validate based on the name or IP you connect with.

    WinRM and PSRemoting do not allow you to ignore SSL errors.

    # Your remote machine credential
    $cred = Get-Credential
    
    # Run commands in a one off remote session
    Invoke-Command -ComputerName $serverName -Credential $cred { "hello" }
    
    # Create a PSSession so we can run commands over the same session at different times
    $session = New-PSSession -ComputerName $serverName -Credential $cred
    
    # Invoke-Command with an existing PSSession
    Invoke-Command -ComputerName $serverName -Credential $cred -Session $session { "hello" }
    
    # Enter-PSSession lets you open an interactive terminal within a remote PowerShell session
    Enter-PSSession -ComputerName $serverName -Credential $cred -Session $session
    
    # To leave a PSSession you've entered with Enter-PSSession
    Exit-PSSession
    exit
    

    Note that exit is not an alias of Exit-PSSession, it just has the same effect when you exit the remote session as when you exit a local session.


    If you must use PSExec (for example, PSRemoting doesn't let you run stuff as the SYSTEM user directly, but PSExec does), then one of two things must be true to execute psexec.exe:

    The following is not just true for PSExec, but for any program run on Windows, MacOS, or Windows due to their Unix roots or influences. Each one shares the PATH concept, and without this, you must know where the program exists on disk or "you ain't runnin' it".

    If you don't know where the program is installed and it's not on the PATH, your only other option is to copy from media or download it where you know it will be stored on disk.


    Well... I lied a bit

    There is one way you can locate psexec.exe (or another program) if you are certain it exists on the system. You can search the filesystem for it. The more files you have and the lower your IOPS are will extend the time it takes for the search to complete. If you find the executable, you can execute it with the call operator &:

    Warning: Be careful with this approach. If multiple executables exist which have the same name but are different versions or different programs entirely, you could accidentally end up executing the wrong version, wrong program altogether, or worst-case scenario, a malicious actor could place a modified or fake psexec.exe designed to steal your credentials or otherwise cause damage to your environment. You have been warned.

    If you go this route, check the known checksum of the program you search for. The below example does not include this but you can use Get-FileHash to obtain a found psexec.exe's checksum, and compare it to the known correct checksum.

    $foundPsExec = Get-ChildItem C:\ -Recurse -File -Include psexec.exe -EA Continue |
      Select-Object -First 1
    
    if( $foundPsExec ) {
      & $foundPsExec.FullName
    }
    

    Allow me to explain a few things from the above example: