Tag Archive: pssession

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


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