Tag Archive: WinRM

Remotely enable PSRemoting and Unrestricted PowerShell Execution using PsExec and PSSession, then run PSRecon

Option 1 — WMI:
PS C:\> wmic /node:”″ process call create “powershell -noprofile -command Enable-PsRemoting -Force” -Credential Get-Credential

Option 2 – PsExec:
PS C:\> PsExec.exe \\ -u [admin account name] -p [admin account password] -h -d powershell.exe “Enable-PSRemoting -Force”


PS C:\> Test-WSMan
PS C:\> Enter-PSSession
[]: PS C:\> Set-ExecutionPolicy Unrestricted -Force


Option 1 — Execute locally in-memory, push evidence to a share, and lock the host down:
[]: PS C:\> IEX (New-Object Net.WebClient).DownloadString(‘https://github.com/gfoss/PSRecon/psrecon.ps1’)
[]: PS C:\> Copy-Item PSRecon_* -Recurse [network share]
[]: PS C:\> rm PSRecon_* -Recurse -Force
[]: PS C:\> Invoke-Lockdown; exit

Option 2 — Exit PSSession, execute PSRecon remotely, send the report out via email, and lock the host down:
[]: PS C:\> exit
PS C:\> .\psrecon.ps1 -remote -target -sendEmail -smtpServer -emailTo greg.foss[at]logrhythm.com -emailFrom psrecon[at]logrhythm.com -lockdown

Be careful! This will open the system up to unnecessary risk!!
You could also inadvertently expose administrative credentials when authenticating to a compromised host.
If the host isn’t taken offline, PSRemoting should be disabled along with disallowing Unrestricted PowerShell execution following PSRecon

Finding remote session connected to your computer?
who is running a (hidden) remote PowerShell on your machine? Here’s a simple one-liner:
Get-WSManInstance -ConnectionURI (‘http://{0}:5985/wsman’ -f $env:computername) -ResourceURI shell -Enumerate
It will return anyone connecting via port 5985 to your machine. However, if you’re not running in a domain environment,
you first have to enable non-Kerberos connections
(remember that without Kerberos, you no longer know for sure that the target computer really is the computer it pretends
to be):
Set-Item WSMan:\localhost\Client\TrustedHosts * -Force


Event forwarding (also called SUBSCRIPTIONS) is a mean to send Windows event log entries from source computers to a collector. A same computer can be a collector or a source.

There are two methods available to complete this challenge – collector initiated and source initiated:

Parameter Collector Initiated Source Initiated
Socket direction (for firewall rules) Collector –> Source Collector –> Source
Initiating machine Collector Source
Authentication Type Kerberos Kerberos / Certificates

This technology uses WinRM (HTTP protocol on port TCP 5985 with WinRM 2.0, else TCP 80) . Be careful with the Window firewall and configure it to allow WinRM incoming requests.

WinRM is the ‘server’ component and WinRS is the ‘client’ that can remotely manage the machine with WinRM configured.

Differences you should be aware of:

WinRM 1.1
Vista and Server 2008
Port 80 for HTTP and Port 443 for HTTPS

WinRM 2.0
Windows 7 and Server 2008 R2
Port 5985 for HTTP and Port 5986 for HTTPS

WinRM 1.1 can also be downloaded and installed on pre-R2 2003 and XP from here.

Windows Server 2008 Core:

In order to forward events from a 2008 Server that is not R2, you will need to make a few changes. The first change is the default listening port, it needs to be changed from TCP 80 to TCP 5985. Additionally you may need to start the Windows Event Collector Service.

net start wecsvc
winrm set winrm/config/listener?Address=*+Transport=HTTP @{Port=”5985”}

Basic configuration:

on source computers and collector computer:  winrm quickconfig     and add the collector computer account to the local administrators group

To verify a listener has been created type winrm enumerate winrm/config/listener

WinRM Client Setup

Just to round off this quick introduction to WinRM, to delete a listener use winrm delete winrm/config/listener?address=*+Transport=HTTP

on collector computer: wecutil qc. Add the computer account of the collector computer to the Event Log Readers Group on each of the source computers

on collector computer: create a new subscription from event viewer (follow the wizard)

WinRS: WinRS (Windows Remote Shell) is the client that connects to a WinRM configured machine (as seen in the first part of this post). WinRS is pretty handy, you’ve probably used PSTools or SC for similar things in the past. Here are a few examples of what you do.

Connecting to a remote shell
winrs -r:http://hostnameofclient "cmd"
Stop / Starting remote service
winrs -r:http://hostnameofclient "net start/stop spooler"
Do a Dir on the C drive
winrs -r:http://hostnameofclient "dir c:\"


Forwarded Event Logs:

This is configured using ‘subscribers’, which connect to WinRM enabled machines.

To configure these subscribers head over to event viewer, right click on forwarded events and select properties. Select the 2nd tab along subscriptions and press create.

This is where you’ll select the WinRM enabled machine and choose which events you would like forwarded.


Right click the subscription and select show runtime status.

Error 0x80338126

Now it took me a minute or two to figure this one out. Was it a firewall issue (this gives the same error code), did I miss some configuration steps? Well no, it was something a lot more basic than that. Remember earlier on we were talking about the port changes in WinRM 1.1 to 2.0?

That’s right, I was using server 2008 R2 to set the subscriptions which automatically sets the port to 5985. The client I configured initially was server 2008 so uses version 1.1. If you right click the subscription and click properties -> advanced you’ll be able to see this. I changed this to port 80 and checked the runtime status again.

[DC2.domain.local] – Error – Last retry time: 03/02/2011 20:20:30. Code (0x5): Access is denied. Next retry time: 03/02/2011 20:25:30.”

Head back to the advanced settings and change the user account from machine account to a user with administrative rights. After making these changes the forwarded events started to flow.

Subscriptions Advanced

Additional considerations:

In a workgroup environment, you can follow the same basic procedure described above to configure computers to forward and collect events. However, there are some additional steps and considerations for workgroups:

  • You can only use Normal mode (Pull) subscriptions
  • You must add a Windows Firewall exception for Remote Event Log Management on each source computer.
  • You must add an account with administrator privileges to the Event Log Readers group on each source computer. You must specify this account in the Configure Advanced Subscription Settings dialog when creating a subscription on the collector computer.
  • Type winrm set winrm/config/client @{TrustedHosts="<sources>"} at a command prompt on the collector computer to allow all of the source computers to use NTLM authentication when communicating with WinRM on the collector computer. Run this command only once. Where <sources> appears in the command, substitute a list of the names of all of the participating source computers in the workgroup. Separate the names by commas. Alternatively, you can use wildcards to match the names of all the source computers. For example, if you want to configure a set of source computers, each with a name that begins with “msft”, you could type this command winrm set winrm/config/client @{TrustedHosts="msft*"} on the collector computer. To learn more about this command, type winrm help config.

If you configure a subscription to use the HTTPS protocol by using the HTTPS option in Advanced Subscription Settings , you must also set corresponding Windows Firewall exceptions for port 443. For a subscription that uses Normal (PULL mode) delivery optimization, you must set the exception only on the source computers. For a subscription that uses either Minimize Bandwidth or Minimize Latency (PUSH mode) delivery optimizations, you must set the exception on both the source and collector computers.

If you intend to specify a user account by using the Specific User option in Advanced Subscription Settings when creating the subscription, you must ensure that account is a member of the local Administrators group on each of the source computers in step 4 instead of adding the machine account of the collector computer. Alternatively, you can use the Windows Event Log command-line utility to grant an account access to individual logs. To learn more about this command-line utility, type wevtutil sl -? at a command prompt.











1st: Event forwarding between computers in a Domain


2nd: Event forwarding between computers in workgroup


Additional article talking about Event forwarding too:



  • If you want target Dell (Quest) ARS service using powershell v2 and you are located behind a firewall:

Web Site Config Wizard not only connects to IIS to create new IIS site, but also connects to ARS Admin Service and improts new customization settings.

To do that it need to connect to remote  ARS  Admin Service via its native API (DCOM/RPC).

For a list of ports that need to be open to connect to ARS Admin Service via firewall, please see this KB article:


  • If you want to use Powershell v2 scripts targeting W2k8 R2 or above and you are located behind a firewall:

You must request to open the following FW ports:

WinRM 1.1 and earlier:  The default HTTP port is 80, and 443 in HTTPS

WinRM 2.0:  The default HTTP port is 5985 and 5986 in HTTPS


WinRM troubleshooting: http://blogs.technet.com/b/jonjor/archive/2009/01/09/winrm-windows-remote-management-troubleshooting.aspx

Powershell remoting how-to ?

How to use Powershell remoting ?

WinRM is the ‘server’ component and WinRS is the ‘client’ that can remotely manage the machine with WinRM configured.

Differences you should be aware of:

WinRM 1.1
Vista and Server 2008
Port 80 for HTTP and Port 443 for HTTPS

WinRM 2.0
Windows 7 and Server 2008 R2
Port 5985 for HTTP and Port 5986 for HTTPS

WinRM 1.1 can also be downloaded and installed on pre-R2 2003 and XP from here.

1) on remote computer,
start: enable-PSRemoting
or execute:
winrm quickconfig -q
2) Remotely on mgmt wks running Windows 7 or Windows 2008 R2:
Create a remote session on target computer:
New-PSSession -computername computer1
Enter the session on a target computer:
enter-PSSession -computername computer1
…. execute actions remotely
dism /online /get-features /format:table
3) Exit a session from a remote computer:
4) List remote sessions opened:
5) Remove a remote sessions:
Remove-PSSession <number>
Creating powershell sessions
$sessions= New-PSSession computer1,computer2,omputer3
you can view the sessions by outputing the $sessions variable
Invoke-Command { Get-ChildItem } -session $sessions ; this command executes the get-childitem cmdlet on computerX but doesn’t close the connection.
Invoke-Command { Get-ChildItem } -session $sessions -asjob ; same above, but runs in the background
Finding remote session connected to your computer?
who is running a (hidden) remote PowerShell on your machine? Here’s a simple one-liner:Get-WSManInstance -ConnectionURI (‘http://{0}:5985/wsman’ -f $env:computername) -ResourceURI shell -Enumerate
It will return anyone connecting via port 5985 to your machine. However, if you’re not running in a domain environment,
you first have to enable non-Kerberos connections
(remember that without Kerberos, you no longer know for sure that the target computer really is the computer it pretends
to be):Set-Item WSMan:\localhost\Client\TrustedHosts * -Force
Running a scriptblock on multiple remote computers ?
$Workload = {
$TestText = Get-Content “C:\test.txt”
$WebServices = Get-WebService | ? {$_.Name -eq “foo”}
Invoke-Command -Session $remoteSession -ScriptBlock $Workload
Invoke-Command { Get-ChildItem env:co* } -computername computer1,computer2
Running a scriptbloxk as a background job on a remote computer
Invoke-Command { Get-ChildItem $env:Systemroot -include *.log -recurse} -computername computer1 -asjob
=> get-job <id> ; check the status  of all the jobs started
=> receive-job <id> ; returns the output from all the jobs that were started
Benefits of Creating a PowerShell Job?
Large complex PowerShell script blocks could take ages to complete, consequently this processing could tie-up your command  line.
Thus it’s better to have a ‘Job’ run in the background and free-up your keyboard so that you can issue other instructions.
Another benefit of creating a job is that thanks to the -keep parameter you can review the results again and again.
There are two strategies for employing ‘Jobs’;
either append the parameter -asJob to a cmdlet such as Invoke-Command,
or else create a new job id with start-Job followed by a PowerShell instruction in a scriptBlock.
Employing the -AsJob Parameter Strategy:
This strategy relies on appending -asJob to a cmdlet such as invoke-Command, the results of the  scriptBlock are stored as a job.  The PowerShell commands between the scriptBlock {braces} run in the background on the remote machine, however the results are automatically saved locally as a new job ID.
All that you see on-screen is a record that the job is running, however, you can check the state of all jobs with get-Job.
Remember that you do not see the actual data until you run a sister command receive-Job.
Invoke-Command -computer computer1 -scriptBlock {get-Service} -asJob
Note: In real-life you may want to modify the cmdlet with a ‘where-Object’ clause, for example, {get-service | where{$_.status -eq “Running”}}
I rarely pay attention to the object nature of PowerShell, however, when it comes to jobs,
it really helps to think of each item as an object, which we can then recall and manipulate, for example, we can pipe the output to format-table  and select just the properties we are most interested in.
Thanks to the -computer parameter, asJob runs the command on the remote machine, even though the job object itself is stored on the local computer.  Incidentally, -asJob works not only with invoke-Command, but also with get-WmiObect.
Employing the Start-Job Strategy:Here is the PowerShell instruction to research members of the job family:
get-command -noun job
The Basics: Start-Job -scriptBlock {cmdlet(s)}
Start-Job -scriptBlock {get-eventlog “System”}
$Session = NewPSSession ComputerName $RemoteComputer
InvokeCommand Session $Session ScriptBlock {StartJob ScriptBlock {GetProcess} Name myJob}
$Result = InvokeCommand Session $Session ScriptBlock {ReceiveJob Name myJob Keep}
While there is a PowerShell cmdlet called ‘Stop-Job’ you don’t normally need to issue this command,  PowerShell’s  intelligence automatically stops the job when all the instructions have completed.  Thus the only need for Stop-Job  is when you have made a mistake in a very long script, for instance, it’s looping.
The only puzzle with Start-Job is how do you access the data?  Get-Job merely lists the objects, it does not show their  contents.
To solve that mystery we employ the ‘Receive’ verb as you will see in the next example.
Key Cmdlet: Receive-Job
Receive-Job is the crucial member of the job family because it enables us to check the results of running the scriptBlock with start-Job.  As a preliminary I always run get-Job so that I can make a note of the job name or unique ID number.  All things considered, it’s essential that receive-Job has a name or number so that it can decide which object to read, and then write the results to your screen.
receive-job job19 -keep
The first time I ran receive-Job the command completed successfully but it removed all the data from the object
(HasMoreData – False).  This is why I now append the -keep parameter, so that I can run the command again and the data  is still in the object.
More good news, because each job is an object, you pipe can the results into format-table, and thus control the output.
receive-job job19 -keep | format-table name, property1 etc*
* Since your ‘job’ is different from mine, you need to research the names of its properties.
If you cannot remember then refer back to the scriptBlock in the original Start-Job instruction.
Cleaning up with Remove-Job One side effect of experimenting is creating lots of failed jobs, thus it’s useful to have a clean-up, and for this task  run Remove-Job *.  The famous * wildcard zaps all jobs in the cache.  If you preferred you could just remove a named job. Even better, try the -state switch.
remove-Job -state failed