Skip to content

Commit 08b62db

Browse files
committed
Pass loot contents over the API and write file
1 parent 49f5256 commit 08b62db

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

lib/metasploit/framework/data_service/proxy/loot_data_proxy.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ module LootDataProxy
33
def report_loot(opts)
44
begin
55
data_service = self.get_data_service()
6+
if !data_service.is_a?(Msf::DBManager)
7+
opts[:data] = Base64.urlsafe_encode64(opts[:data]) if opts[:data]
8+
end
69
data_service.report_loot(opts)
710
rescue Exception => e
811
puts "Call to #{data_service.class}#report_loot threw exception: #{e.message}"

lib/metasploit/framework/data_service/remote/http/remote_loot_data_service.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ module RemoteLootDataService
44
include ResponseDataHelper
55

66
LOOT_PATH = '/api/1/msf/loot'
7-
LOOT_SEARCH_PATH = LOOT_PATH + "/search"
87

98
def loot(opts = {})
109
json_to_open_struct_object(self.get_data(LOOT_PATH, opts), [])
@@ -21,9 +20,4 @@ def find_or_create_loot(opts)
2120
def report_loots(loot)
2221
self.post_data(LOOT_PATH, loot)
2322
end
24-
25-
def do_loot_search(search)
26-
response = self.post_data(LOOT_SEARCH_PATH, search)
27-
return response.body
28-
end
2923
end

lib/msf/core/auxiliary/report.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ def store_loot(ltype, ctype, host, data, filename=nil, info=nil, service=nil)
416416
conf[:workspace] = myworkspace
417417
conf[:name] = filename if filename
418418
conf[:info] = info if info
419+
conf[:data] = data if data
419420

420421
if service and service.kind_of?(::Mdm::Service)
421422
conf[:service] = service if service

lib/msf/core/db_manager/http/servlet/loot_servlet.rb

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,52 @@ def self.get_loot
2727

2828
def self.report_loot
2929
lambda {
30-
job = lambda { |opts| get_db().report_loot(opts) }
30+
31+
job = lambda { |opts|
32+
# This regex does a best attempt to determine if opts[:data] is valid Base64
33+
# See https://stackoverflow.com/questions/8571501/how-to-check-whether-the-string-is-base64-encoded-or-not
34+
if opts[:data] =~ /^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$/
35+
opts[:data] = Base64.urlsafe_decode64(opts[:data]) if opts[:data]
36+
end
37+
38+
# This code is all for writing out the file locally.
39+
# It is copied from lib/msf/core/auxiliary/report.rb
40+
# We shouldn't duplicate it so a better method should be used
41+
if ! ::File.directory?(Msf::Config.loot_directory)
42+
FileUtils.mkdir_p(Msf::Config.loot_directory)
43+
end
44+
45+
ext = 'bin'
46+
if opts[:name]
47+
parts = opts[:name].to_s.split('.')
48+
if parts.length > 1 and parts[-1].length < 4
49+
ext = parts[-1]
50+
end
51+
end
52+
53+
case opts[:content_type]
54+
when /^text\/[\w\.]+$/
55+
ext = "txt"
56+
end
57+
# This method is available even if there is no database, don't bother checking
58+
host = Msf::Util::Host.normalize_host(host)
59+
60+
ws = (opts[:workspace] ? opts[:workspace] : 'default')
61+
name =
62+
Time.now.strftime("%Y%m%d%H%M%S") + "_" + ws + "_" +
63+
(host || 'unknown') + '_' + opts[:type][0,16] + '_' +
64+
Rex::Text.rand_text_numeric(6) + '.' + ext
65+
66+
name.gsub!(/[^a-z0-9\.\_]+/i, '')
67+
68+
path = File.join(Msf::Config.loot_directory, name)
69+
full_path = ::File.expand_path(path)
70+
File.open(full_path, "wb") do |fd|
71+
fd.write(opts[:data])
72+
end
73+
74+
get_db().report_loot(opts)
75+
}
3176
exec_report_job(request, &job)
3277
}
3378
end

0 commit comments

Comments
 (0)