List All Failed Logon Attempts in Windows

Have you ever noticed when you open up the RDP port to the outside world that it takes somewhat between 3 to 24 hours only before BOT’s starts hammering with logon attempts?
It’s really annoying how you just can’t be left alone online without someone or something to start attacking you right away.. Urh!

Anyway; just keep a good firewall (Windows Firewall and Defender should be plenty good to be honest) and a sturdy password, and you should be safe in most cases.
Oh and keep that “Guest” account “Locked n’ Blocked”.
So; if you should be that person who expose your RDP out to the web and wonder just out of curiosity how much hammering is occurring on that “door” then keep on reading.

RDP Port

RDP is short for “Remote Desktop Protocol” port. It’s the network port that Windows uses to allow you to connect to another computer remotely.
By default, RDP uses port 3389. When you open Remote Desktop on your computer and connect to another machine, your computer reaches out over the internet or network through port 3389 to establish a connection.
Since this port is standard for RDP, it’s often targeted by hackers. Some say that for better security, users should change the RDP port to a different port number externally.
This is NOT true!
Bot’s usually scan IP addresses in a range, and if your Public IP answer and identifies itself as the RDP port the Bot registers that. The scan may also appear or end up on a search engine called “Shodan” that many Bot’s uses to select targets faster.

How to see who’s knocking on the door?

For this experiment we’re going to use PowerShell.
This script will read the Windows event log which register all logon attempts successful or not.
We need to scrape out 3 things:

  • Source IP address
  • Number of attempts
  • First seen date

We also want to remove unnecessary information such as events that contains successful attempts as this is ourselves logging on, and attempts done by the system, and events that is coming from the localhost (IP:127.0.0.1).
The event ID we need to look for is 4625. If you open up the event viewer on your computer, you can also sort the view to only show this specific event ID, but what makes this script stand out is the sorting part, and that you need to scroll though tons of unwanted information. It also groups the attempts the unique source IP address, and ask if you want to export the list to a CSV file

So to run the script you need to copy the code below,
and paste it into notepad and save the file as a .PS1 file.
You can also download the script by clicking here..
Once you have the file, you need to run it as an administrator as it requires to read from a system log.
The best way is to find PowerShell from the start menu, and then run it as Admin by right clicking on it.
Then you need to navigate to the file you just created/downloaded, and execute it from there.

I have divided the script into chucks and commented on each one so you can see what each one does.
Also, please feel free to use and modify this to your need if you must.

Happy hunting, and learn something new every day!

<#	
================
Created by:   	Jan Brekke
Organization: 	DigitalBrekke
Filename:     	FailedLogons.ps1
URL: https://github.com/janbrekke/Failed-Logon-Attempts
===============
.DESCRIPTION
	Scrape, list, and dump all failed logon attempts.
	Useful when you have RDP port open to WAN.
#>

# This defines the start date as three months ago from today
$StartDate = (Get-Date).AddMonths(-3)
$EndDate = Get-Date

# This defines the event ID 4625 and where to find the log
$Events = Get-WinEvent -FilterHashtable @{
    LogName = 'Security'
    Id = 4625
    StartTime = $StartDate
    EndTime = $EndDate
} | ForEach-Object {

    # This goes through each event to find "Source Network Address"
    $SourceNetworkAddress = ($_.Properties | Where-Object { $_.Value -match '(\d{1,3}\.){3}\d{1,3}' }).Value

    # This sort out only valid addresses and drops localhost
    if ($SourceNetworkAddress -and $SourceNetworkAddress -ne '::1' -and $SourceNetworkAddress -ne '127.0.0.1') {
        [PSCustomObject]@{
            IPAddress     = $SourceNetworkAddress
            TimeGenerated = $_.TimeCreated
        }
    }
}

# This group by IP and count how many attempts, and sort by the count in a descending order
$GroupedEvents = $Events | Group-Object -Property IPAddress | Sort-Object Count -Descending

# This specify and prepare the output with IP addresses, the count of attempts, and the first seen timestamp
$Output = $GroupedEvents | ForEach-Object {
    [PSCustomObject]@{
        IPAddress = $_.Name
        Count     = $_.Count
        FirstSeen = ($_.Group | Sort-Object TimeGenerated | Select-Object -First 1).TimeGenerated
    }
}

# This creates the table format
$Output | Format-Table -AutoSize

# This displays the total count of unique IP addresses
$totalUniqueIPs = $Output.Count
$totalAttempts = ($GroupedEvents | Measure-Object -Property Count -Sum).Sum

Write-Host "Total Unique IP Addresses:" $totalUniqueIPs
Write-Host "Total Failed Logon Attempts:" $totalAttempts

# This simply ask the user if they would like to export it to a CSV file
$Export = Read-Host "Would you like to export the results to a CSV file? (Y/N)"
if ($Export -eq 'Y' -or $Export -eq 'y') {
    $FilePath = "$env:USERPROFILE\Desktop\FailedLogonAttempts.csv"
    $Output | Export-Csv -Path $FilePath -NoTypeInformation -Encoding UTF8
    Write-Host "Results exported to $FilePath"
}

Script is also listed on our GitHub account:
https://github.com/janbrekke/Failed-Logon-Attempts