A few weeks back I was on a live call with a Tier 2 analyst who was trying to pull sign-in activity for a user account we suspected was compromised. I sat there on mute for a full ten minutes watching him click through three different admin portals, filter the same data four different ways, and finally export a CSV that was half garbage. The whole time I was thinking "this is a three line PowerShell command." When I finally said something and ran it for him, he watched the output fly by and went quiet for a second before saying "I had no idea you could do that."

That conversation is the reason I'm writing this article. I've been in cybersecurity for years now, working my way up from help desk to SOC analyst to senior engineer to managing a cybersecurity engineering team. The one constant across every single one of those roles has been PowerShell. Not because it's flashy. Because it quietly does about 80% of the work that people waste their whole day clicking through GUIs to accomplish.

If you're a SOC analyst, a security engineer, or someone trying to break into this field, PowerShell is one of the highest leverage skills you can build. I'm going to walk through the five commands I actually use every single day. Not a giant list. Just the five that pay for themselves over and over, with the exact syntax I use and why each one matters. If you can internalize these five, you will immediately level up how fast you can investigate, triage, and respond.

Quick note before we dive in

Everything in this article is built for Windows-heavy environments because that's where 90% of SOC work happens. A few of these commands require you to install specific PowerShell modules (the Active Directory module and the Microsoft Graph SDK are the main ones). I'll flag those as we go. None of the commands here are going to land you in jail, but as always, only run this stuff in environments where you have explicit authorization. This is not a disclaimer I'm putting in for fun. I've seen analysts fired for running enumeration commands in places they had no business running them.

1. Get-WinEvent with a FilterHashtable

If you take one thing away from this article, let it be this command. Get-WinEvent is the PowerShell equivalent of your SIEM's search bar for anything that lives in Windows event logs. Every SOC analyst in a Windows shop should know this one by muscle memory.

Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    ID        = 4624
    StartTime = (Get-Date).AddHours(-24)
} | Select-Object TimeCreated, @{N='User';E={$_.Properties[5].Value}}, 
    @{N='SrcIP';E={$_.Properties[18].Value}}

This pulls every successful logon (Event ID 4624) in the last 24 hours and formats it into a clean table with timestamp, username, and source IP. If you've ever had to investigate a suspected account takeover, you know how valuable this is. Without this command, you're clicking around in Event Viewer for twenty minutes trying to filter down to what you actually want to see.

Why this one matters.

The FilterHashtable is the important part. A lot of analysts write Get-WinEvent with a Where-Object clause afterwards and then wonder why their queries take forever. FilterHashtable pushes the filter down to the event log API itself, which is orders of magnitude faster. On a domain controller with millions of events, the difference is the query finishing in two seconds versus timing out entirely.

Common Event IDs I filter on almost every week. 4624 for successful logons, 4625 for failed logons, 4672 for privileged logons, 4688 for process creation (if command line auditing is enabled), 4720 for user account creation, 4732 for group membership changes, and 4104 for PowerShell script block logging. Memorize those seven and you'll handle 90% of Windows investigations without looking up a single thing.

2. Get-ADUser with Filter and Properties

If your shop has Active Directory (and it probably does), the AD module is a gift. Get-ADUser looks simple but most analysts never use it beyond the basic form, which leaves a ton of value on the table.

Get-ADUser -Filter {LastLogonDate -lt (Get-Date).AddDays(-90) -and Enabled -eq $true} `
  -Properties LastLogonDate, PasswordLastSet, MemberOf |
  Select-Object Name, SamAccountName, LastLogonDate, PasswordLastSet

This one finds every enabled user account that hasn't logged in for 90 days. Why would I care? Because those are exactly the accounts an attacker wants. Forgotten service accounts, test accounts from two years ago, that one contractor who left in January. If an attacker compromises one of those, nobody notices because nobody was watching them.

Why this one matters.

Stale accounts are one of the most commonly abused identity weaknesses in a Windows environment. If you're on a SOC team, running a version of this query once a week and flagging anomalies to your IAM team is high leverage defensive work that almost nobody does. As an engineering manager, when I see a candidate in an interview who has actually done this kind of account hygiene work, I lean in hard.

Quick variant I use for hunting privileged accounts. Swap the filter to find anyone in Domain Admins or Enterprise Admins. That's a one line pivot for almost every domain-level incident I've ever worked on.

Get-ADGroupMember -Identity "Domain Admins" -Recursive |
  Get-ADUser -Properties LastLogonDate, PasswordLastSet

If that output shocks you (it usually does the first time you run it in a real environment), welcome to why privileged access management is the industry it is. I can't tell you how many engagements I've been on where the Domain Admins group had twice as many members as the security team expected.

3. Get-CimInstance Win32_Process

When an EDR alert hits your queue and you need to actually look at what's running on a workstation, this is the command. Yes, Get-Process exists. No, it's not good enough. Get-CimInstance gives you parent process IDs, command lines, and process creation times that Get-Process just does not surface.

Get-CimInstance Win32_Process |
  Select-Object ProcessId, ParentProcessId, Name, CommandLine, CreationDate |
  Sort-Object CreationDate -Descending |
  Format-Table -AutoSize

This gives you a clean table of every running process, its parent, and the exact command line that launched it. This is the stuff you want when you're investigating "is there something weird on this box." An attacker running rundll32.exe with a suspicious DLL or powershell.exe launched from Outlook is the kind of thing that jumps off the screen when you can actually see the full command line and parent relationship.

Why this one matters.

Process trees are where a huge percentage of actual incidents get detected. If you see winword.exe as the parent of cmd.exe as the parent of powershell.exe, that is almost always bad. You cannot see that relationship in Task Manager. You cannot see it with Get-Process. You need this command.

I've got a full working reference I put together that goes deeper into how to actually triage a suspicious process tree, including the full "is this box compromised or not" live response script I use. It's the kind of thing that would have saved me years of fumbling through incidents early in my career. More on that at the end.

4. Get-MgAuditLogSignIn for Cloud Investigations

This is the command I referenced in the story that opened this article. If your environment runs on Entra ID (the artist formerly known as Azure AD, which most environments now do), this command is the one that separates senior engineers from Tier 1 analysts.

Import-Module Microsoft.Graph.Reports
Connect-MgGraph -Scopes "AuditLog.Read.All"

Get-MgAuditLogSignIn -Filter "userPrincipalName eq 'jane.doe@yourcompany.com' and createdDateTime ge $((Get-Date).AddDays(-30).ToString('yyyy-MM-ddTHH:mm:ssZ'))" -All |
  Select-Object CreatedDateTime, AppDisplayName, IpAddress, 
    @{N='Location';E={"$($_.Location.City), $($_.Location.CountryOrRegion)"}},
    @{N='Status';E={$_.Status.ErrorCode}}

This pulls 30 days of sign-ins for a specific user, formatted into a table with timestamps, application, IP address, location, and result code. In any cloud-first environment, this is the single most valuable account takeover investigation command in your toolkit. You can see at a glance if the user suddenly signed in from a country they've never been to, or if there's a pattern of failed attempts from a weird IP range.

Why this one matters.

Identity is the new perimeter. Most modern breaches do not involve dropping a rootkit on a server anymore. They involve an attacker phishing a session cookie, then signing in as the user, then pivoting from there. The investigations that used to require flipping through on-prem logs now require flipping through Entra sign-in logs, and knowing this one command takes that from a 20 minute GUI click session to a 30 second scripted query.

Pro tip. You can pipe this straight into Export-Csv and hand the CSV to your IR lead or legal team. I've done this in actual breach scenarios where we needed timeline data fast. The Graph SDK is a little finicky to set up the first time, but once it's configured on your analyst workstation, this is a command you'll run weekly at minimum.

I spent an entire chapter on the Microsoft Graph API in the PowerShell for Cybersecurity reference I put together, because this one topic alone has saved me probably 200 hours of work across my career. If you want to actually understand how Graph auth works, how to handle pagination, and how to build your own enrichment functions, that chapter alone is worth the download.

5. Invoke-RestMethod for Threat Intel Enrichment

The last one on the list is the most general purpose, but also the one that opens the most doors once you understand it. Invoke-RestMethod is how you talk to any REST API from PowerShell. Every threat intel platform, every SIEM, every EDR has a REST API. Once you can call it from PowerShell, you can enrich your investigations without ever leaving the terminal.

Here's a simple example using VirusTotal to check whether a URL is known to be malicious.

$apiKey = "YOUR_API_KEY_HERE"
$url    = "http://suspicious.example.com/payload.exe"
$headers = @{ "x-apikey" = $apiKey }

$encodedUrl = [System.Convert]::ToBase64String(
    [System.Text.Encoding]::UTF8.GetBytes($url)
).TrimEnd('=')

Invoke-RestMethod -Uri "https://www.virustotal.com/api/v3/urls/$encodedUrl" `
                  -Headers $headers -Method Get |
  Select-Object -ExpandProperty data |
  Select-Object -ExpandProperty attributes |
  Select-Object last_analysis_stats, reputation

This pulls the reputation of a URL from VirusTotal and spits out a clean summary of how many engines flagged it. When a phishing alert lands in your queue and you want a quick sanity check on whether the destination is already known bad, this is your command.

Why this one matters.

Enrichment is what separates a decent analyst from a great one. If you're investigating a suspicious IP, a URL, a file hash, or a domain, being able to pivot into VirusTotal, AbuseIPDB, URLScan, Shodan, or whatever threat intel platform your team uses without leaving PowerShell means you can do in 30 seconds what would otherwise take five minutes of tab switching. Multiply that by the hundred alerts in your queue, and it changes your whole day.

Writing your own enrichment function. Once you've done this a few times, you'll want to wrap it in a PowerShell function so you can call Get-URLReputation <url> and have it just work. That's the kind of toolbelt mindset that turns Tier 1 analysts into detection engineers.

Why These Five Matter More Than Anything Else

I get asked all the time what the "most important" PowerShell commands to learn are. People expect a list of 50 things, all memorized by heart. The truth is that if you know the five above, cold, you can handle almost anything a SOC analyst or junior engineer is going to run into. The remaining knowledge is context specific to your environment.

The pattern behind all five of these is the same. You learn a command that gives you raw data, and then you learn how to filter, select, and sort that data until it answers the question you're trying to answer. That skill is way more valuable than memorizing cmdlet syntax. It's also exactly what I look for in interviews when I ask candidates to walk me through how they'd investigate something using PowerShell.

Final Thoughts

PowerShell is the single most underrated skill in cybersecurity. I say that as someone who has interviewed dozens of candidates where a stacked resume collapsed the moment I asked a basic PowerShell question. I say it as someone who has watched senior engineers use this tool to cut investigation times by 80%. And I say it as someone who has lost entire afternoons clicking through admin portals because I didn't know the command that would have pulled the data in one line.

If you want the full working reference I wish someone had handed me when I was breaking into this field, I put together a 100+ page guide called PowerShell for Cybersecurity. It covers everything from fundamentals to Active Directory hunting to Entra ID investigation to the Microsoft Graph API, plus a set of ready to run IR playbooks, an interview question bank, and a full chapter on decoding obfuscated PowerShell you'll see in actual incidents. The whole thing is built to sit on your second monitor while you're investigating. I made it the resource I wish I'd had at every stage of my own career, from Tier 1 SOC analyst to where I am now.

Try the five commands above. Run them against your own environment (assuming you have authorization). You'll be amazed at how much more efficient your investigations get in your first week. Once you see how much time PowerShell saves, you'll want to go deeper, and that's what the guide is for.

Good luck out there.

Make sure to check out the full 100+ page reference guide for Powershell for Cybersecurity Here!

FAQ

Do I need to be an administrator to run these commands?

Most of them require some level of privilege. Get-WinEvent on the Security log requires admin rights on the local machine. Get-ADUser requires at minimum a domain user account with read access to AD (most domain accounts have this). Get-MgAuditLogSignIn requires the AuditLog.Read.All Graph permission, which your Entra admin would need to grant.

Which PowerShell version should I be using?

PowerShell 7 is where the ecosystem is moving. It's cross-platform, faster, and has better module support. That said, Windows PowerShell 5.1 is still what ships on most Windows servers and is what a lot of the AD tooling is optimized for. In a SOC, you'll bounce between both.

How do I install the Active Directory and Microsoft Graph modules?

The Active Directory module comes with RSAT (Remote Server Administration Tools). On Windows 10 and 11, you install it through Optional Features. The Microsoft Graph SDK installs with Install-Module Microsoft.Graph from an elevated PowerShell prompt.

Are these commands safe to run in production?

Read operations like the ones in this article are almost always safe. The commands here are all reading data, not changing anything. That said, your organization may have monitoring on PowerShell activity, so always check that you have authorization to run enumeration commands in a given environment before you fire them off.

What should I learn after these five?

Learn process hunting, file system forensics, and the Microsoft Graph API at a deeper level. Those are the three areas that will let you handle almost any investigation scenario a SOC analyst or engineer is going to face.