Files
metasploit-gs/lib/msf/core/modules/external/bridge.rb
T
2017-04-26 18:08:08 -05:00

105 lines
2.1 KiB
Ruby

# -*- coding: binary -*-
require 'msf/core/modules/external'
require 'msf/core/modules/external/message'
require 'open3'
class Msf::Modules::External::Bridge
attr_reader :path, :running
def meta
@meta ||= describe
end
def run(datastore)
unless self.running
m = Msf::Modules::External::Message.new(:run)
m.params = datastore.dup
send(m)
self.running = true
end
end
def get_status
if self.running
n = receive_notification
if n && n['params']
n['params']
else
close_ios
self.running = false
n['response'] if n
end
end
end
def initialize(module_path)
self.running = false
self.path = module_path
self.env = {
'PYTHONPATH' => File.expand_path('../python', __FILE__)
}
end
protected
attr_writer :path, :running
attr_accessor :ios
attr_accessor :env
def describe
resp = send_receive(Msf::Modules::External::Message.new(:describe))
close_ios
resp['response']
end
# XXX TODO non-blocking writes, check write lengths, non-blocking JSON parse loop read
def send_receive(message)
send(message)
read_json(message.id, self.ios[1])
end
def send(message)
input, output, status = ::Open3.popen3(env, [self.path, self.path])
self.ios = [input, output, status]
case Rex::ThreadSafe.select(nil, [input], nil, 0.1)
when nil
raise "Cannot run module #{self.path}"
when [[], [input], []]
m = message.to_json
write_message(input, m)
else
raise "Error running module #{self.path}"
end
end
def receive_notification
input, output, status = self.ios
case Rex::ThreadSafe.select([output], nil, nil, 10)
when nil
nil
when [[output], [], []]
read_json(nil, output)
end
end
def write_message(fd, json)
fd.write(json)
end
def read_json(id, fd)
begin
resp = fd.readpartial(10_000)
JSON.parse(resp)
rescue EOFError => e
{}
end
end
def close_ios
input, output, status = self.ios
[input, output].each {|fd| fd.close rescue nil} # Yeah, yeah. I know.
end
end