Scanning Windows network for defense (rapidly)

Jackbox

Active Member
Jan 2, 2016
197
96
74
Sometimes you realize "Oh yeah, we are on a Windows network."

This assumes you are bound to a domain e.g. Active Directory. You would also need tools for remoting with PowerShell. You need to install RSAT, a possible way to automate this is shown here. Otherwise figure it out by searching "install rsat Windows".

When you do that, you can and should think "We are the 80% market share..."

For those times when you are ever so slightly paranoid, at least find comfort in knowing you can ping your whole domain somewhat quickly to know what you are likely dealing with. Most attackers do not disable ICMP first thing, I do not think. That behavior may flag a cautionary beacon to an IT team with a network sensor like Nagios, SolarWinds... https://www.nagios.com/solutions/ping-monitoring/ // https://forum.mikrotik.com/viewtopic.php?t=78594 .. etc

Anyways, we can cover detecting an unresponsive ICMP host that is really there later on. Onwards for now!

Open PowerShell and run the following (mirror for the psm1):
Code:
mkdir wickt
cd wickt
wget https://gallery.technet.microsoft.com/scriptcenter/Multithreaded-PowerShell-0bc3f59b/file/114248/1/TestConnectionAsync.psm1 -OutFile TestConnectionAsync.psm1
Import-Module .\TestConnectionAsync.psm1
Get-ADComputer -Filter 'samAccountName -like "*"' | foreach { $_.Name } > targets.txt
Get-Content .\targets.txt | Test-ConnectionAsync -MaxConcurrent 100 -Quiet | findstr "True" > living.txt

Now you should at least have a rough idea where your living systems are, that is assuming nothing is interfering with pinging your targets. Try both Ethernet and WiFi? Ideally you want to be least restricted when carrying out this step of host discovery because if you are in a closet and can only talk to a few blinky boxes, you are whale hunting in outer freakin' space.

You can check for system patches now, like this:
Code:
Get-HotFix -Description Security* -ComputerName 01ComputerNameHere -Credential Domain1\Username1

You could use your living.txt list to check for a specific patch:
Code:
PS> $A = Get-Content -Path ./Servers.txt
PS> $A | ForEach-Object { if (!(Get-HotFix -Id KB957095 -ComputerName $_))
         { Add-Content $_ -Path ./Missing-KB957095.txt }}

There is also a PowerShell module for doing the hotfix checking.

If you see a Windows machine no longer updating, that is probably a reason to say "Wtf m8?"

Get last 100 security logs:
Code:
GET-EVENTLOG -Logname Security -Newest 100 -Computername 1OfficeComputerName

Specific event IDs:
Code:
GET-EVENTLOG -Logname Security -Newest 100 -Computername 1OfficeComputerName | where { $_.InstanceID -eq '4799'}

Make sure to run PowerShell as admin, since you need this permission to access Security event logs.

Logon types are different and important at times for example:
GET-EVENTLOG -Logname Security -Newest 10 -Computername OfficeComputerName1 | where { $_.Message | findstr /C:"Logon Type"}

Will show you everything in a single line, with "Fl",
Code:
GET-EVENTLOG -Logname Security -Newest 20 -Computername OfficeComputerName1 | where { $_.Message | findstr /C:"Logon Type"} | Format-List -Property *

Code:
GET-EVENTLOG -Logname Security -Newest 15 -Computername OfficeComputerName1 | where { $_.Message | findstr "Logon"} | Fl

Code:
GET-EVENTLOG -Logname Security -Newest 15 -Computername OfficeComputerName1 | where { $_.InstanceId | findstr "4624"} | Fl

Code:
GET-EVENTLOG -Logname Security -Newest 100 -Computername OfficeComputerName1 | where { $_.InstanceId | findstr "4624"} | Fl | findstr "Account Name"

Code:
GET-EVENTLOG -Logname Security -Newest 100 -Computername OfficeComputerName1 | where { $_.InstanceId | findstr "4624"} | Fl -Property "EventID", MachineName, Index, TimeGenerated

But eventually, this may get annoying trying to pick apart the 'Message:' text and all of the subtext within like "Logon Type". A solution exists! Mark Berry writes an awesome post on the difference between Get-EventLog and Get-WinEvent here.

Code:
Get-WinEvent -FilterHashtable @{logname='security' ; id=4624;starttime=' 8/14/2019 1:00:00 PM ';endtime=' 8/14/2019 9:09:40 PM'}

Coolest sh*t ever, try this:
Code:
Get-WinEvent -FilterHashTable @{Logname='security';ID=4624}| Select-Object -Property TimeCreated,MachineName, Message | Fl

Code:
Get-WinEvent -MaxEvents 25 -FilterHashTable @{Logname='security';ID=4624}| Select-Object -Property @{Name='Logon Type';Expression={$_.Properties[8].Value}}, TimeCreated, MachineName, @{Name='AuthPackage';Expression={$_.Properties[14].Value}}, @{Name='User';Expression={$_.Properties[5].Value}}

Code:
Get-WinEvent -ListLog * -ComputerName OfficeComputerName1

Code:
Get-WinEvent -ComputerName OfficeComputerName1 -MaxEvents 15 -FilterHashTable @{logname='security' ; id=4624;starttime=' 8/14/2019 1:00:00 PM ';endtime=' 8/14/2019 9:09:40 PM'} | Fl

Code:
Get-WinEvent -MaxEvents 100 -FilterHashtable @{LogName='security'; id=4624} | Where-Object -FilterScript {($_.Properties[8].Value -eq 3) -or ($_.Properties[8].Value -eq 11)} | fl Message

Get-WinEvent -ComputerName OfficeComputerName1 -MaxEvents 10 -FilterHashtable @{LogName='security'; id=4624} | Where-Object -FilterScript {($_.Properties[8].Value -eq 3) -or ($_.Properties[8].Value -eq 11)} | fl Message

Not matching certain usernames
Code:
Get-WinEvent -MaxEvents 10 -FilterHashtable @{LogName='security'; id=4624} | Where-Object -FilterScript {($_.Properties[5].Value -ne "securityadminuser") -and ($_.Properties[5].Value -ne "firewalluser")} | fl *

Code:
Get-WinEvent -ComputerName OfficeComputerName1 -MaxEvents 20 -FilterHashTable @{Logname='security';ID=4624} | Select-Object -Property TimeCreated,LogonType, @{Name='AccountName';Expression={$_.Properties[5].Value}}, @{Name='AccountDomain';Expression={$_.Properties[6].Value}} | Where{$_.AccountName -notmatch 'SYSTEM|LOCAL|NETWORK'}

This bottom one gives you a great idea of what you are really looking at, but keep in mind that $_.Properties[8].Value is going to give you the Logon Type, highly useful for investigating a potential compromise.

Example remote usage looks like this:

Code:
Get-WinEvent -ComputerName OfficeComputerName1 -MaxEvents 20 -FilterHashTable @{Logname='security';ID=4624} | Select-Object -Property TimeCreated,LogonType, @{Name='AccountName';Expression={$_.Properties[5].Value}}, @{Name='AccountDomain';Expression={$_.Properties[6].Value}}, @{Name='LType';Expression={$_.Properties[8].Value}} | Where{$_.AccountName -notmatch 'SYSTEM|LOCAL|NETWORK'}

And if you really want to monitor for suspicious logon types, then research the different ones and hunt the suspicious numbers down. A network logon (3) is one indicator to be suspicious of, especially if you see a large number scattered across many machines.

Keep in mind you may be able to run Get-EventLog in some cases whilst Get-WinEvent will require RPC, "Get-WinEvent : The RPC server is unavailable"

You can swap "OfficeComputerName1" for localhost or just completely remove all the.. -ComputerName OfficeComputerName1 text ;)
 
Last edited:
Top