Add framework.uuid_db as a JSONHashFile
parent
9d7e54f360
commit
513a81e340
|
@ -73,7 +73,7 @@ class Framework
|
||||||
require 'msf/core/plugin_manager'
|
require 'msf/core/plugin_manager'
|
||||||
require 'msf/core/db_manager'
|
require 'msf/core/db_manager'
|
||||||
require 'msf/core/event_dispatcher'
|
require 'msf/core/event_dispatcher'
|
||||||
|
require 'rex/json_hash_file'
|
||||||
|
|
||||||
#
|
#
|
||||||
# Creates an instance of the framework context.
|
# Creates an instance of the framework context.
|
||||||
|
@ -91,6 +91,7 @@ class Framework
|
||||||
self.datastore = DataStore.new
|
self.datastore = DataStore.new
|
||||||
self.jobs = Rex::JobContainer.new
|
self.jobs = Rex::JobContainer.new
|
||||||
self.plugins = PluginManager.new(self)
|
self.plugins = PluginManager.new(self)
|
||||||
|
self.uuid_db = Rex::JSONHashFile.new(::File.join(Msf::Config.config_directory, "payloads.json"))
|
||||||
|
|
||||||
# Configure the thread factory
|
# Configure the thread factory
|
||||||
Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: self)
|
Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: self)
|
||||||
|
@ -187,6 +188,12 @@ class Framework
|
||||||
# unloading of plugins.
|
# unloading of plugins.
|
||||||
#
|
#
|
||||||
attr_reader :plugins
|
attr_reader :plugins
|
||||||
|
#
|
||||||
|
# The framework instance's payload uuid database. The payload uuid
|
||||||
|
# database is used to record and match the unique ID values embedded
|
||||||
|
# into generated payloads.
|
||||||
|
#
|
||||||
|
attr_reader :uuid_db
|
||||||
|
|
||||||
# The framework instance's db manager. The db manager
|
# The framework instance's db manager. The db manager
|
||||||
# maintains the database db and handles db events
|
# maintains the database db and handles db events
|
||||||
|
@ -243,6 +250,7 @@ protected
|
||||||
attr_writer :jobs # :nodoc:
|
attr_writer :jobs # :nodoc:
|
||||||
attr_writer :plugins # :nodoc:
|
attr_writer :plugins # :nodoc:
|
||||||
attr_writer :db # :nodoc:
|
attr_writer :db # :nodoc:
|
||||||
|
attr_writer :uuid_db # :nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
class FrameworkEventSubscriber
|
class FrameworkEventSubscriber
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
# -*- coding => binary -*-
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
require 'msf/core/payload/uuid'
|
|
||||||
require 'json'
|
|
||||||
|
|
||||||
#
|
|
||||||
# This module provides a flat file database interface for managing UUIDs
|
|
||||||
#
|
|
||||||
class Msf::Payload::UUID::DB
|
|
||||||
|
|
||||||
attr_accessor :info, :path
|
|
||||||
|
|
||||||
def initialize(path)
|
|
||||||
self.info = {}
|
|
||||||
self.path = path
|
|
||||||
@lock = Mutex.new
|
|
||||||
@last = 0
|
|
||||||
reload
|
|
||||||
end
|
|
||||||
|
|
||||||
# Save the file, but prevent thread & process contention
|
|
||||||
def save(action={})
|
|
||||||
@lock.synchronize do
|
|
||||||
::File.open(path, ::File::RDWR|::File::CREAT) do |fd|
|
|
||||||
fd.flock(::File::LOCK_EX)
|
|
||||||
|
|
||||||
# Reload and merge if the file has changed recently
|
|
||||||
if fd.stat.mtime.to_f > @last
|
|
||||||
self.info = parse_data(fd.read).merge(self.info)
|
|
||||||
end
|
|
||||||
|
|
||||||
if action[:register_uuid]
|
|
||||||
params = (action[:params] || {}).merge({ type: 'uuid' })
|
|
||||||
self.info[ action[:register_uuid] ] = params
|
|
||||||
end
|
|
||||||
|
|
||||||
if action[:register_url]
|
|
||||||
params = (action[:params] || {}).merge({ type: 'url' })
|
|
||||||
self.info[ action[:register_uurl] ] = params
|
|
||||||
end
|
|
||||||
|
|
||||||
if action[:remove_uuid]
|
|
||||||
self.info.delete(action[:delete_uuid])
|
|
||||||
end
|
|
||||||
|
|
||||||
fd.rewind
|
|
||||||
fd.write(JSON.pretty_generate(self.info))
|
|
||||||
fd.sync
|
|
||||||
fd.truncate(fd.pos)
|
|
||||||
|
|
||||||
@last = Time.now.to_f
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Load the file from disk
|
|
||||||
def load
|
|
||||||
@lock.synchronize do
|
|
||||||
::File.open(path, ::File::RDWR|::File::CREAT) do |fd|
|
|
||||||
fd.flock(::File::LOCK_EX)
|
|
||||||
@last = fd.stat.mtime.to_f
|
|
||||||
self.info = parse_data(fd.read(fd.stat.size))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Reload if the file has changed
|
|
||||||
def reload
|
|
||||||
return unless ::File.exists?(path)
|
|
||||||
return unless ::File.stat(path).mtime.to_f > @last
|
|
||||||
load
|
|
||||||
end
|
|
||||||
|
|
||||||
def register_uuid(uuid, params)
|
|
||||||
save(register_uuid: uuid, params: params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_uuid(uuid)
|
|
||||||
save(remove_uuid: uuid)
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_uuid(uuid)
|
|
||||||
reload
|
|
||||||
self.info[uuid]
|
|
||||||
end
|
|
||||||
|
|
||||||
def register_url(url, params)
|
|
||||||
save(register_url: url, params: params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_url(url)
|
|
||||||
save(remove_url: url)
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_url(url)
|
|
||||||
reload
|
|
||||||
self.info[url]
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def parse_data(data)
|
|
||||||
return {} if data.to_s.strip.length == 0
|
|
||||||
begin
|
|
||||||
JSON.parse(data)
|
|
||||||
rescue JSON::ParserError => e
|
|
||||||
# TODO: Figure out the appropriate error handling path
|
|
||||||
raise e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
# -*- coding => binary -*-
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
#
|
||||||
|
# This class provides a thread-friendly hash file store in JSON format
|
||||||
|
#
|
||||||
|
module Rex
|
||||||
|
class JSONHashFile
|
||||||
|
|
||||||
|
attr_accessor :path
|
||||||
|
|
||||||
|
def initialize(path)
|
||||||
|
self.path = path
|
||||||
|
@lock = Mutex.new
|
||||||
|
@hash = {}
|
||||||
|
@last = 0
|
||||||
|
synced_update
|
||||||
|
end
|
||||||
|
|
||||||
|
def [](k)
|
||||||
|
synced_update
|
||||||
|
@hash[k]
|
||||||
|
end
|
||||||
|
|
||||||
|
def []=(k,v)
|
||||||
|
synced_update do
|
||||||
|
@hash[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def keys
|
||||||
|
synced_update
|
||||||
|
@hash.keys
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(k)
|
||||||
|
synced_update do
|
||||||
|
@hash.delete(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear
|
||||||
|
synced_update do
|
||||||
|
@hash.clear
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Save the file, but prevent thread & process contention
|
||||||
|
def synced_update(&block)
|
||||||
|
@lock.synchronize do
|
||||||
|
::File.open(path, ::File::RDWR|::File::CREAT) do |fd|
|
||||||
|
fd.flock(::File::LOCK_EX)
|
||||||
|
|
||||||
|
# Reload and merge if the file has changed recently
|
||||||
|
if fd.stat.mtime.to_f > @last
|
||||||
|
parse_data(fd.read).merge(@hash).each_pair do |k,v|
|
||||||
|
@hash[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
res = nil
|
||||||
|
|
||||||
|
# Update the file on disk if new data is written
|
||||||
|
if block_given?
|
||||||
|
res = block.call
|
||||||
|
fd.rewind
|
||||||
|
fd.write(JSON.pretty_generate(@hash))
|
||||||
|
fd.sync
|
||||||
|
fd.truncate(fd.pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
@last = fd.stat.mtime.to_f
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def parse_data(data)
|
||||||
|
return {} if data.to_s.strip.length == 0
|
||||||
|
begin
|
||||||
|
JSON.parse(data)
|
||||||
|
rescue JSON::ParserError => e
|
||||||
|
# elog("JSONHashFile @ #{path} was corrupt: #{e.class} #{e}"
|
||||||
|
{}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue