Run script on remote computer and pass creds to remote script - powershell-4.0

Requirement: must be run from local machine on remote machine with creds passed to the remote machine script.
$server = 'SRV1'
$credential = Get-Credential
$credentials = Get-Credential
Invoke-Command -ComputerName $server -Credential $credential -ScriptBlock {
C:\foo.ps1 $credentials
}
foo.ps1 requires functions that need $credentials
Inside foo.ps1
param($credentials)

You can't use the Variable $credentials in the scriptBlock on the other computer without passing it as a parameter:
Pass arguments to a scriptblock in powershell

Related

Powershell Running Command Line as Admin User

So I have automation that logs into a Windows Server 2019 machine as one user, but then needs to run a command (Invoke-AdminCommand is application specific, not a built-in Windows cmdlet) as an admin user (and I do not want to add the logged in user as an Admin). I've followed answers from here (if you think this is a duplicate question) and none have worked. In the script I do a "whoami" to be sure the session is the correct user, and it is. But the command returns an application specific error stating the user does not have the correct permissions. If I RDP into the same machine as the admin user and run the same command through a Powershell CLI - it works fine.
$username = "domain\adminUser"
$password = "**********" | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $username,$password
$s = New-PSSession -credential $cred
$sc = {
whoami
Invoke-AdminCommand -Register -Verbose
}
Invoke-Command -Session $s -Scriptblock $sc
Remove-PSSession $s
You may be hitting the double-hop problem. You are remoting to another server to run another command which itself requires authentication. If you can't lean on CredSSP (security risk) or proper account delegation (potentially high overhead in effort to maintain delegations at volume but this is the correct way to go about it).
Note: Basic auth will also work around this issue but I highly highly highly do not recommend using basic auth without at least setting up WinRM over SSL and removing non-HTTPS WinRM listeners.
Whether you are using Kerberos (without proper delegation or CredSSP) or NTLM (at all as NTLM cannot forward tokens) as the authentication scheme you can work around this by passing the credential information into Invoke-Command and building the credential in that script block, and using Start-Process to start it as a different user. Note that if you needed to elevate for UAC, the code would be different and this code will only work when you don't need UAC elevation:
# We will create the SecureString inside the Invoke-Command block
$password = "********"
# Use of a Dictionary instead of positional arguments and `param` in the block
# is a little trick you can use here.
Invoke-Command -Session $s -ArgumentList #{ Username = $username; Password = $password } {
$cred =
[PSCredential]::new($args.Username, ( $args.Password | ConvertTo-SecureString -AsPlainText -Force ))
# Placeholder for next part
}
So this is the boilerplate for what you want. You send the credentials to the remote server and build it there. How you execute this at # Placeholder for next part will depend on what exactly you are running:
External Command (executable)
Use Start-Process to run the program as the other user
Start-Process -Wait -Credential $cred program.exe -ArgumentList "arguments to the program here"
Any cmdlet which accepts a -Credential parameter or any command which accepts username and password arguments
Pass the credential argument directly to the cmdlet/function, or pass $args.Username and $args.Password to an external command which has username/password parameters directly. The below however exemplifies using this with a cmdlet and the -Credential parameter.
# Note that some cmdlets don't take a credential for whatever reason
# and may have -Username and -Password arguments instead.
Invoke-AdminCommand -Credential $cred -Register -Verbose
Any Function or Cmdlet which does not accept a -Credential parameter or username/password arguments
This is similar to the first example, but this example specifically targets running a bit of PowerShell code as another user for the code you want.
# This can be invoked without splatting but am using splatting for readability
$spArgs = #{
Credential = $cred
FilePath = 'powershell.exe' # You can use `pwsh.exe` for PS Core if necessary
ArgumentList = "-Command ""exampleProgram.exe -username $($args.Username) -password $($args.Password)"""
Wait = $true
NoNewWindow = $true
}
Start-Process powershell.exe

Retrieving Windows Defender Status remotely

I am using the following script to retrieve Windows Defender status remotely.
$password = ConvertTo-SecureString “myPassword” -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential (“myUserNamer”, $password)
$sessionOption = New-CimSessionOption -Protocol WsMan
$session = New-CIMSession -ComputerName myMachineName -Credential $credentials -SessionOption
Get-MpPreference -CimSession $session
However, I am quite new to PowerShell scripting and related protocols. Is this the best way of retrieving this information when I may have to run it over hundreds of computers?
Does it need to be for all the machines or selected ones?
For example:
You could run a remote session on the machine you need and then run the command.
Enter-PSSession [VMname]
Get-MpComputerStatus
Replace [VMname] with the name of the VM/Computer you're looking for.
Enter-PSSession Computer-01
Get-MpComputerStatus
If that's what you're looking for.

How to correctly decrypt account credentials and pass them to Add-LocalGroupMember command

I am trying to create a script which adds currently logged on user account to local admin group which is to be deployed as SCCM package to freshly deployed computers in one particular AD OU group. I have encoded a service account credentials using a .key seed and stored them in a .txt file. Unfortunately I'm unable to retrieve/pass the current user account to aforementioned command.
I've tried running package with administrative rights option enabled, skipping credential encode and using various methods without success outside of lab, hence why I had to request a service account which would have enough rights to get the job done. Ive also tried various ways of identifying user accounts, however this is the only one which retrieves the actual account of windows user rather than the one under which PS session is running.
$User = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$Computer = $env:COMPUTERNAME $svcAcc = "xxx\xx-xx" $PasswordFile = ".\Password.txt" $KeyFile = ".\AES.key" $key = Get-Content $KeyFile
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $svcAcc,(Get-Content $PasswordFile | ConvertTo-SecureString -Key $key)
Invoke-Command -ComputerName $Computer -Credential $Cred -ScriptBlock {Add-LocalGroupMember -Group "Administratorer" -Member $User}
I expected the $User variable to be passed correctly as when I run [System.Security.Principal.WindowsIdentity]::GetCurrent().Name selection, correct details are shown. Instead I get an error
Cannot validate argument on parameter 'Member'. The argument is null or empty"
Any pointers would be greatly appreciated
Everything within the scriptblock is executed on the remote machine. That remote machine does not have access to the local variable "$User"
Use the -ArgumentList parameter to pass the $user variable to the Scriptblock.
Invoke-Command -ComputerName $Computer -ScriptBlock {Add-LocalGroupMember -Group "Administratorer" -Member $args[0]} -ArgumentList $User

How to execute a command on cmd of another system in same network

How can I execute a command in cmd of another computer which is in the same network without any help of software like PsExec.
I have the system name and the credentials to login to the system.
IS there any way to do this using command prompt or with PowerShell
Thanks for any helps
The best way is using WinRM and Invoke-Command cmdlet. Read more about it here: http://technet.microsoft.com/en-us/library/hh849719.aspx
It allows you to write something like:
Invoke-Command -ComputerName server01 -Credential domain01\user01 -ScriptBlock {Get-Culture}
Using WMI:
$WMI_Params =
#{
Class = 'Win32_Process'
Name = 'Create'
ArgumentList = 'Notepad.exe'
Credential = $Creds
}
Foreach ($Computer in $Computers)
{ Invoke-WmiMethod #WMIParams -ComputerName $Computer }

Using Powershell's Invoke-Command to call a batch file with arguments

I want to use Powershell in order to call a batch file on remote machines. This batch file has arguments. Here's what I have so far:
$script = "\\fileshare\script.cmd"
$server = $args[0]
$args [string]::join(',',$args[1 .. ($args.count-1)])
Invoke-Command -computername $server {$script + ' ' + $args}
After a bit of searching, I found that the Invoke-Command function runs its scriptblock in a whole new process, so you can't put variables in it (they won't get expanded). That's what the -ArgumentList tag is for. So I tried this instead...
Invoke-Command -computername $server {\\fileshare\script.cmd} -ArgumentList "FirstArgument"
That didn't work either... my batch script tells me it's not being passed any arguments. I can't find anything that explicitly says so, but it looks like the -ArgumentList parameter only works on Powershell scripts (it won't feed them to a batch script).
Any ideas how I can use Invoke-Command to call a batch file with arguments?
When you pass the argument list to the scriptblock, try to "receive them" using a PARAM directive. Like this:
Invoke-Command -computername $server {PARAM($myArg) \\fileshare\script.cmd $myArg} -ArgumentList "FirstArgument"
or you can just use the $args automatic variable:
Invoke-Command -computername $server {\\fileshare\script.cmd $args} -ArgumentList "FirstArgument"
The arguments will be passed as arguments to the scriptblock and not directly to your cmd. You have to do:
Invoke-Command {param($script,$arg1) &$script $arg1 } -computername $server -ArgumentList $script,"FirstArgument"
or
Invoke-Command {&$args[0] $args[1] } -computername $server -ArgumentList $script,"FirstArgument"
PS: I don't know what you are doing with $args [string]::join(',',$args[1 .. ($args.count-1)]), it is a syntax error

Resources