Module: Msf::DBManager::Loot

Included in:
Msf::DBManager
Defined in:
lib/msf/core/db_manager/loot.rb

Instance Method Summary collapse

Instance Method Details

#delete_loot(opts) ⇒ Array

Deletes Loot entries based on the IDs passed in.

Parameters:

  • opts (:ids)
    Array

    Array containing Integers corresponding to the IDs of the Loot entries to delete.

Returns:

  • (Array)

    Array containing the Mdm::Loot objects that were successfully deleted.

Raises:

  • (ArgumentError)


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/msf/core/db_manager/loot.rb', line 131

def delete_loot(opts)
  raise ArgumentError.new("The following options are required: :ids") if opts[:ids].nil?

  ::ApplicationRecord.connection_pool.with_connection {
    deleted = []
    opts[:ids].each do |loot_id|
      loot = Mdm::Loot.find(loot_id)
      begin
        deleted << loot.destroy
      rescue # refs suck
        elog("Forcibly deleting #{loot}")
        deleted << loot.delete
      end
    end

    return deleted
  }
end

#find_or_create_loot(opts) ⇒ Object

Find or create a loot matching this type/data



5
6
7
# File 'lib/msf/core/db_manager/loot.rb', line 5

def find_or_create_loot(opts)
  report_loot(opts)
end

#loots(opts) ⇒ Object Also known as: loot

This methods returns a list of all loot in the database



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/msf/core/db_manager/loot.rb', line 12

def loots(opts)
  ::ApplicationRecord.connection_pool.with_connection {
    # If we have the ID, there is no point in creating a complex query.
    if opts[:id] && !opts[:id].to_s.empty?
      return Array.wrap(Mdm::Loot.find(opts[:id]))
    end

    opts = opts.clone() # protect the original caller's opts
    # Remove path from search conditions as this won't accommodate remote data
    # service usage where the client and server storage locations differ.
    opts.delete(:path)
    search_term = opts.delete(:search_term)
    data = opts.delete(:data)

    wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework)
    opts = opts.clone()
    opts.delete(:workspace)
    opts[:workspace_id] = wspace.id

    if search_term && !search_term.empty?
      column_search_conditions = Msf::Util::DBManager.create_all_column_search_conditions(Mdm::Loot, search_term)
      results = Mdm::Loot.includes(:host).where(opts).where(column_search_conditions)
    else
      results = Mdm::Loot.includes(:host).where(opts)
    end

    # Compare the deserialized data from the DB to the search data since the column is serialized.
    unless data.nil?
      results = results.select { |loot| loot.data == data }
    end

    results
  }
end

#report_loot(opts) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/msf/core/db_manager/loot.rb', line 48

def report_loot(opts)
  return if not active
::ApplicationRecord.connection_pool.with_connection {
  wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework)
  opts = opts.clone()
  opts.delete(:workspace)
  path = opts.delete(:path) || (raise RuntimeError, "A loot :path is required")

  host = nil
  addr = nil

  # Report the host so it's there for the Proc to use below
  if opts[:host]
    if opts[:host].kind_of? ::Mdm::Host
      host = opts[:host]
    else
      host = report_host({:workspace => wspace, :host => opts[:host]})
      addr = Msf::Util::Host.normalize_host(opts[:host])
    end
  end

  ret = {}

  ltype  = opts.delete(:type) || opts.delete(:ltype) || (raise RuntimeError, "A loot :type or :ltype is required")
  ctype  = opts.delete(:ctype) || opts.delete(:content_type) || 'text/plain'
  name   = opts.delete(:name)
  info   = opts.delete(:info)
  data   = opts[:data]
  loot   = wspace.loots.new

  if host
    loot.host_id = host[:id]
  end
  if opts[:service] and opts[:service].kind_of? ::Mdm::Service
    loot.service_id = opts[:service][:id]
  end

  loot.path         = path
  loot.ltype        = ltype
  loot.content_type = ctype
  loot.data         = data
  loot.name         = name if name
  loot.info         = info if info
  loot.workspace    = wspace
  msf_assign_timestamps(opts, loot)
  loot.save!

  ret[:loot] = loot
}
end

#update_loot(opts) ⇒ Mdm::Loot

Update the attributes of a Loot entry with the values in opts. The values in opts should match the attributes to update.

Parameters:

  • opts (Hash)

    Hash containing the updated values. Key should match the attribute to update. Must contain :id of record to update.

Returns:

  • (Mdm::Loot)

    The updated Mdm::Loot object.



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/msf/core/db_manager/loot.rb', line 104

def update_loot(opts)
  ::ApplicationRecord.connection_pool.with_connection {
    wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework, false)
    # Prevent changing the data field to ensure the file contents remain the same as what was originally looted.
    raise ArgumentError, "Updating the data attribute is not permitted." if opts[:data]
    opts = opts.clone()
    opts.delete(:workspace)
    opts[:workspace] = wspace if wspace

    id = opts.delete(:id)
    loot = Mdm::Loot.find(id)

    # If the user updates the path attribute (or filename) we need to update the file
    # on disk to reflect that.
    if opts[:path] && File.exist?(loot.path)
      File.rename(loot.path, opts[:path])
    end

    loot.update!(opts)
    return loot
  }
end