A listing of the more widely-used PowerShell commands and a brief explanation about each command is provided below. Some commands can be referenced by an alias or cmdlet name, while other commands can only be referenced by a cmdlet name.
CSV
REST
HTTP
Do you want to run a PowerShell command on a remote computer or server? Then you don’t need to open a remote desktop connection, because you can just use the PowerShell Invoke-Command for that.
Invoke-Command allows you to run PowerShell commands and scripts on one or more remote computers. while redirecting the results to your own console. This makes it a great cmdlet to manage remote devices quickly.
In this article
In this article, we are going to take a look at what is required to use Invoke-Command and how to use the cmdlet.
Adversaries may abuse PowerShell commands and scripts for execution.
PowerShell is a powerful interactive command-line interface and scripting environment included in the Windows operating system. (Citation: TechNet PowerShell)
Adversaries can use PowerShell to perform a number of actions, including discovery of information and execution of code
Sigma rule (View on GitHub)
Powershell XML Execute Command Adversaries may abuse PowerShell commands and scripts for execution. PowerShell is a powerful interactive command-line interface and scripting environment included in the Windows operating system. (Citation: TechNet PowerShell) Adversaries can use PowerShell to perform a number of actions, including discovery of information and execution of code- - - - all of selection_* #Fucntion to manipulate the data
Function writeToServer
{ param($server,$Time) # Data preparation for loading data into SQL table $InsertResults = @" INSERT INTO [ServerTimeSync].[dbo].[ServerTimes](SystemName,ShownTimeOnServer) VALUES ('$SERVER','$Time') "@ #call the invoke-sqlcmdlet to execute the query Invoke-sqlcmd @params -Query $InsertResults } foreach ($COMPUTER in $COMPUTERS){ icm $COMPUTER -ScriptBlock {$ENV:COMPUTERNAME $computer get-date -Format "MM-dd-yyyy hh:mm:ss tt" $script:sdate = get-date -Format "MM-dd-yyyy hh:mm:ss tt" } writeToServer $computer $script:sdate
}asked Aug 22, 2023 at 11:31
You can only pass (the values of) local variables TO a remote command, via the
$using:scope.$using:references are embedded directly in the remote script block and are an alternative to passing values via arguments (parameters), using-ArgumentList– see this answer for examples. In both cases only the value of a local variable is getting passed, not the variable object itself.
- That is, you fundamentally cannot set variables for the caller from a remote script block.
Note that the above applies to all out-of-runspace / cross-process calls, e.g. also to Start-Job – see this answer for details.
You can also streamline your command by using parallel processing:
Invoke-Command -ComputerName $COMPUTERS -ScriptBlock { Get-Date -Format "MM-dd-yyyy hh:mm:ss tt"
} | ForEach-Object { writeToServer $_.PSComputerName $_ }If you pass multiple computer names to
Invoke-Command‘s-ComputerNameparameter, processing occurs in parallel, but the ordering of the outputs isn’t guaranteed to match the order in which the names were passed.
answered Aug 22, 2023 at 12:02
67 gold badges673 silver badges862 bronze badges
This is how you utilize $using: correctly
$MyString = 'Test 123'
Invoke-Command . -ScriptBlock {Write-Output $MyString} # produces no output because $MyString is empty
Invoke-Command . -ScriptBlock {Write-Output $using:MyString} # produces correct output because $MyString contains the string$MyString = 'Test 123'
$Capture = Invoke-Command . -ScriptBlock {Write-Output $using:MyString}
Write-Host $Captureanswered Aug 22, 2023 at 12:11
David Trevor
1 gold badge9 silver badges31 bronze badges
Windows DFIR notes are no longer maintained on InfoSec-Notes. Updated versions can be found on: artefacts.help.
Windows PowerShell version 2.0, and prior versions, provide few useful audit settings, thereby limiting the availability of evidence (such as a command history).
Microsoft-Windows-PowerShell\Analytic.etl(non default)
Microsoft-Windows-WinRM\Analytic.etl(non default)
The events linked to remote PowerShell activity, conducted through the WinRM service, are detailed in the Lateral movements section.
Additionally, if enabled, AppLocker will record PowerShell activity in the Microsoft-Windows-AppLocker\MSI and Script hive.
Note that PowerShell 2.0, and prior versions, provide limited logging capacities and thereby limit the availability of evidence, such as the interactive command history executed through PowerShell console.
-Enc/-e-nop/bypassIEX/Invoke-ExpressionICM/Invoke-commandNet.WebClient/io.DownloadString/DownloadFile///http/ftp/cifs/smb/ etc.
While the occurrence of these keywords may entail malicious activities, their absence is not a formal proof of lack of malicious PowerShell activity as PowerShell code can be deeply obfuscated.
The PSDecode PowerShell script can be used to deobfuscate malicious PowerShell scripts that have several layers of encodings.
PowerShell Windows events
| Hive | Event ID | Conditions | Description |
|---|---|---|---|
| |||
| |||
PowerShell 2.0 |
| ||
PowerShell 2.0 |
| ||
| |||
PowerShell 3.0 | |||
| |||
Microsoft-Windows-WinRM\Operational WinRM events on destination host. | |||
Microsoft-Windows-WinRM\Operational WinRM events on source host. | |||
Microsoft-Windows-AppLocker\MSI and Script | Require |
| |
Microsoft-Windows-AppLocker\MSI and Script | Require |
| |
Requires |
Wrapping Up
The PowerShell Invoke-Command is a great tool to manage remote computers. It allows you to quickly execute a command without the need to open a remote desktop. Especially when you need to run the command on multiple computers at once.
Make sure that you also look at the New-PSSession cmdlet, this is really a better option when you need to execute multiple commands on a remote computer.
I hope you found this article helpful, if you have any questions, just drop a comment below.
Using the Invoke-Command
The Invoke-Command in PowerShell allows you to run a command or script on a remote computer. When you need to run multiple commands on a remote computer, then it’s better to use the New-PSSession cmdlet.
The structure of the Invoke-Command is pretty straightforward, but nevertheless, there are still quite a few options (parameters) that we can use:
| Parameter | Description |
|---|---|
| ComputerName | Computername or IP Address to run the command on. For multiple computer, separate the names with a comma , |
| Credential | Credentials to connect to remote computer |
| FilePath | Specifies the path to a local script to run on the remote computer(s) |
| AsJob | Run the remote command as background job on the local computer |
| InDisconnectedSession | Used to run the command in a disconnected session on the remote computer |
| ScriptBlock | Script or command to run |
| ArgumentList | Used to pass arguments to the cmdlet in the scriptblock |
Invoke-Command -ComputerName la-srv-dc01 {Get-ComputerInfo}
This will run the command Get-ComputerInfo on the domain controller (la-srv-dc01) and return the results to the console.
Running a Script
The example below works fine, but it’s a bit harder to read this way:
Invoke-Command -ComputerName la-srv-dc01 -ScriptBlock {Get-CimInstance Win32_LogicalDisk | Select-Object DeviceID, MediaType, @{Name="FreeSpace (GB)"; Expression={"{0:N2}" -f ($_.FreeSpace / 1GB)}}}$script = { Get-CimInstance Win32_LogicalDisk | Select-Object DeviceID, MediaType, @{Name="FreeSpace (GB)"; Expression={"{0:N2}" -f ($_.FreeSpace / 1GB)}}
}
Invoke-Command -ComputerName la-srv-dc01 -ScriptBlock $scriptThe third option is to store the script on your local computer and refer to the script using the -FilePath parameter:
Invoke-Command -ComputerName la-srv-dc01 -FilePath c:\test\diskInfo.ps1
Run on Multiple Computers
One of the big advantages of the Invoke-Command cmdlet in PowerShell is that you can also run it on multiple computers simultaneously. There are a couple of options to do this, we can simply specify the computer names separated by a comma:
Invoke-Command -ComputerName la-srv-dc01, la-srv-app01, la-srv-file01 -FilePath c:\test\diskInfo.ps1
Another option to write this is to use a hashtable and splatting. Splatting the parameters will make your script easier to read when you need to add a lot of properties.
$parameters = @{ ComputerName = 'la-srv-dc01', 'la-srv-app01', 'la-srv-file01', 'la-win11-lab03' ScriptBlock = { Get-ComputerInfo } }
Invoke-Command @parametersWhen you need to run a command on many computers, let’s say a hundred or more, then you want to minimize the load on your local computer. For this, we can use the InDisconnectedSession parameter.
If you run the Invoke-Command cmdlet normally, then your local computer will connect to the remote computer, start the script, wait for the results, and disconnect. The waiting parts consume the most time and resources from your local computer, especially when connecting to 100 or more computers.
With the InDisconnectedSession parameter, the cmdlet will only connect to the remote computer, start the script, and then disconnect. This reduces the whole process time significantly.
$parameters = @{ ComputerName = (Get-Content -Path C:\Test\Servers.txt) InDisconnectedSession = $true FilePath = '\\lazyadmin\scripts\InstallWinUpdates.ps1'
}
Invoke-Command @parametersUsing Credentials
You will need to have permission on the remote computer to run the PowerShell commands. When running the command on a server you probably won’t have the correct permission from your local workstation.
Invoke-Command -ComputerName la-srv-dc01 -Credential lazyadmin\administrator -Scriptblock {Get-ComputerInfo}Just like with most PowerShell cmdlets, you can also pass a credential object to the -Credential cmdlet. This method is especially handy when you want to run multiple commands or need to run different commands on different remote computers:
$cred = Get-Credential
Invoke-Command -ComputerName la-srv-dc01 -Credential $cred -Scriptblock {Get-ComputerInfo}Include Local Variables
$path = "c:\test"
Invoke-Command -ComputerName la-srv-dc01 -Scriptblock {Get-Childitem -Path $path}The example above isn’t going to work. The remote computer, in this case la-srv-dc01, doesn’t know what the variable $path is, so it won’t return any results.
$path = "c:\test"
Invoke-Command -ComputerName la-srv-dc01 -Scriptblock {Get-Chiditem -Path $Using:path}Prerequisites Invoke-Command
To check if a remote computer accepts Remote Management, we can use a simple PowerShell command, Test-WSMan
Test-WSMan -Computername la-srv-dc01
If you get an error that you cannot connect to the destination, then the service Windows Remote Management is not running. To enable it we can use the PowerShell cmdlet Enable-PSRemoting on the remote computer:
Enable-PSRemoting
The advantage of this command is that it not only starts the Remote Management services but also sets it to start automatically and creates the required exception rule in the firewall.
But even a better option is to create a new Group Policy Object (GPO). This way you can easily enable the Remote Management service on multiple computers or servers.
You can find the policy setting in Computer Configuration > Windows Settings > Security Settings > System Services.
Firewall rule
We can use the same GPO to create the inbound rule as well.
- Navigate to Computer Configuration > Windows Settings > Security Settings > Windows Defender Firewall with Advanced Security
- Right-click on Inbound Rules and select New Rule
- Select Predefined and choose Windows Remote Management
- Select the rule with profile Domain, Private
- Choose Allow the connection and click finish
Make sure that the new policies are updated on the server/client, by using the GPUpdate command.


