In this post you’re going to learn about PowerShell jobs. Then in the next post I’ll show you PowerShell remoting and security and then in Part 24 we’ll explore PowerShell scripting.
We’re on the home stretch now.. let’s go!
The first time I heard about PowerShell jobs I thought: okay sign me up; whose hiring?
haha
Okay, that was a lame joke but I had to put it here. In PowerShell, a job is simply a command that’s running in the background. Thank of it like the GUI equivalent of minimizing a window. It’s still running but it’s out of view. You can run the command asynchronously so you can still do other things while the job runs quietly in the shadows.
You can also schedule jobs using Job Triggers and Job Options. This is being used by the good guys and bad guys though. As malicious actors have been using scheduled PowerShell jobs to maintain persistence on compromised machines. And the worst part is that no one is looking for this…
You can always check the status of the job at anytime but it’s not in the foreground which is what makes it so powerful.
The basic cmdlets
There are a ton of cmdlets related to jobs but you really only need to know a few:
- Start-Job
- Get-Job
- Receive-Job
- Stop-Job
- Get-ScheduledJob
- Register-ScheduledJob
- New-JobTrigger
- New-ScheduledJobOption
It looks like a lot but it’s not bad. Remember you can find all these using Get-Help *job*
.
So let’s kick off our job with Start-Job
, check on its progress with Get-Job
and then see the results with Receive-Job
. Then we’ll stop it from running. This is basically just a quick exercise to help you get a feel for how jobs work in PowerShell.
start-job -name infinitePing -ScriptBlock {Test-Connection -ComputerName DoesntExist }
Now let’s check on the job:
Get-Job
We can see the State is running and HasMoreData
is True meaning it still has more data to give us.
Now we can use Receive-Job
with the -Keep
parameter to save the data to the screen. (it offers no job security… okay another bad joke) Without -Keep
it’ll dump from memory but the information won’t stick around for us to analyze it. In other words, the HasMoreData
field would show False so we wouldn’t have any data to see.
And then stop it from running with Stop-Job
Using PowerShell to Schedule Job
To make the jobs persist we need to create scheduled jobs. These will show up in the Windows Task Scheduler just like anything else but you get to do it through PowerShell!
Usually when I do this I start with the Trigger and finish with the Options and I save everything to variables to make everything nice and tidy.
I also heavily rely on tab completion to see what triggers, parameters and options I have as I type them out.
Scheduled Job example
So we can create a trigger. Let’s make the job run everyday at 2am.
$trigger = New-JobTrigger -Daily -At 2AM
And we can create some options.
$options = New-ScheduledJobOption -RunElevated -ContinueIfGoingOnBatt
ery
Remember you can also type Get-Help New-ScheduledJobOption -Full
see see what these parameters mean but you can probably figure this out now.
Then to create the scheduled job we can use Register-ScheduledJob
. I’m going to make a scheduled task that looks runs every day at 2am and checks to see if any new services were installed on the server. This would create an event with EventID 7045 and should definately be investigated because malware often likes to install itself as a service to persist on a victims machine.
Register-ScheduledJob -Name GetProcessCreationEvents -ScriptBlock { Get-EventLog -LogName system | Where-Object { $_.EventID -eq 7045 } -Trigger $trigger -ScheduledJobOption $options }
Bam! And we can even trigger the job now to test it even before it’s scheduled to run:
Start-Job -DefinitionName GetProcessCreationEvents
And then view it in the task manager
taskschd.msc
Just drill down to Microsoft, Windows, PowerShell and you’ll see your scheduled task waiting for you.
w00t