Skip to content

Commit ac5d270

Browse files
committed
Land rapid7#7031, Revert rapid7#6729
2 parents fd07da3 + d5d0b9e commit ac5d270

File tree

3 files changed

+68
-49
lines changed

3 files changed

+68
-49
lines changed

lib/msf/core/data_store.rb

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
# -*- coding: binary -*-
2-
3-
require 'set'
4-
52
module Msf
63

74
###
@@ -16,19 +13,17 @@ class DataStore < Hash
1613
# Initializes the data store's internal state.
1714
#
1815
def initialize()
19-
@options = Hash.new
20-
@imported = Hash.new
21-
@imported_by = Hash.new
22-
@original_keys = Set.new
16+
@options = Hash.new
17+
@imported = Hash.new
18+
@imported_by = Hash.new
2319
end
2420

2521
#
2622
# Clears the imported flag for the supplied key since it's being set
2723
# directly.
2824
#
2925
def []=(k, v)
30-
add_key(k)
31-
k = k.downcase
26+
k = find_key_case(k)
3227
@imported[k] = false
3328
@imported_by[k] = nil
3429

@@ -49,32 +44,31 @@ def []=(k, v)
4944
# Case-insensitive wrapper around hash lookup
5045
#
5146
def [](k)
52-
super(k.downcase)
47+
super(find_key_case(k))
5348
end
5449

5550
#
5651
# Case-insensitive wrapper around store
5752
#
5853
def store(k,v)
59-
add_key(k)
60-
super(k.downcase, v)
54+
super(find_key_case(k), v)
6155
end
6256

6357
#
6458
# Case-insensitive wrapper around delete
6559
#
6660
def delete(k)
67-
super(k.downcase)
61+
super(find_key_case(k))
6862
end
6963

70-
# Override Hash's to_h method so we can include the original case of each key
71-
# (failing to do this breaks a number of places in framework and pro that use
72-
# serialized datastores)
73-
def to_h
74-
@original_keys.reduce({}) do |acc, key|
75-
acc[key] = self[key]
76-
acc
77-
end
64+
65+
#
66+
# Updates a value in the datastore with the specified name, k, to the
67+
# specified value, v. This update does not alter the imported status of
68+
# the value.
69+
#
70+
def update_value(k, v)
71+
self.store(k, v)
7872
end
7973

8074
#
@@ -134,16 +128,15 @@ def import_options_from_s(option_str, delim = nil)
134128
# Imports options from a hash and stores them in the datastore.
135129
#
136130
def import_options_from_hash(option_hash, imported = true, imported_by = nil)
137-
option_hash.each_pair do |key, val|
131+
option_hash.each_pair { |key, val|
138132
import_option(key, val, imported, imported_by)
139-
end
133+
}
140134
end
141135

142136
def import_option(key, val, imported=true, imported_by=nil, option=nil)
143137
self.store(key, val)
144138

145-
key = key.downcase
146-
@options[key] = option
139+
@options[key] = option
147140
@imported[key] = imported
148141
@imported_by[key] = imported_by
149142
end
@@ -152,9 +145,21 @@ def import_option(key, val, imported=true, imported_by=nil, option=nil)
152145
# Serializes the options in the datastore to a string.
153146
#
154147
def to_s(delim = ' ')
155-
@original_keys.reduce('') do |acc, key|
156-
acc << "#{key}=#{self[key]}#{delim}"
148+
str = ''
149+
150+
keys.sort.each { |key|
151+
str << "#{key}=#{self[key]}" + ((str.length) ? delim : '')
152+
}
153+
154+
return str
155+
end
156+
157+
def to_h
158+
datastore_hash = {}
159+
self.keys.each do |k|
160+
datastore_hash[k.to_s] = self[k].to_s
157161
end
162+
datastore_hash
158163
end
159164

160165
#
@@ -194,10 +199,9 @@ def from_file(path, name = 'global')
194199
# not include default option values.
195200
#
196201
def user_defined
197-
@original_keys.reduce({}) do |acc, k|
198-
acc[k] = self[k] unless @imported[k.downcase]
199-
acc
200-
end
202+
reject { |k, v|
203+
@imported[k] == true
204+
}
201205
end
202206

203207
#
@@ -218,26 +222,40 @@ def clear_non_user_defined
218222
# Completely clear all values in the hash
219223
#
220224
def clear
221-
@options.clear
222-
@imported.clear
223-
@imported_by.clear
224-
@original_keys.clear
225-
super
225+
self.keys.each {|k| self.delete(k) }
226+
self
226227
end
227228

228-
# Yield the original-cased key
229+
#
230+
# Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+
231+
# "can't add a new key into hash during iteration"
232+
#
229233
def each(&block)
230-
@original_keys.each do |key|
231-
block.call(key, self[key])
234+
list = []
235+
self.keys.sort.each do |sidx|
236+
list << [sidx, self[sidx]]
232237
end
238+
list.each(&block)
233239
end
234240

235-
protected
241+
protected
242+
243+
#
244+
# Case-insensitive key lookup
245+
#
246+
def find_key_case(k)
236247

237-
# Keep track of the original, case-sensitive key
238-
def add_key(k)
239-
@original_keys.add(k) unless include? k.downcase
248+
# Scan each key looking for a match
249+
self.each_key do |rk|
250+
if (rk.downcase == k.downcase)
251+
return rk
252+
end
253+
end
254+
255+
# Fall through to the non-existent value
256+
return k
240257
end
258+
241259
end
242260

243261
###
@@ -260,7 +278,7 @@ def initialize(m)
260278
# if we can't directly find it
261279
#
262280
def fetch(key)
263-
key = key.downcase
281+
key = find_key_case(key)
264282
val = nil
265283
val = super if(@imported_by[key] != 'self')
266284
if (val.nil? and @_module and @_module.framework)
@@ -274,7 +292,7 @@ def fetch(key)
274292
# Same as fetch
275293
#
276294
def [](key)
277-
key = key.downcase
295+
key = find_key_case(key)
278296
val = nil
279297
val = super if(@imported_by[key] != 'self')
280298
if (val.nil? and @_module and @_module.framework)
@@ -297,10 +315,11 @@ def default?(key)
297315
def copy
298316
clone = self.class.new(@_module)
299317
self.keys.each do |k|
300-
clone.import_option(k, self[k].kind_of?(String) ? self[k].dup : self[k], @imported[k.downcase], @imported_by[k.downcase])
318+
clone.import_option(k, self[k].kind_of?(String) ? self[k].dup : self[k], @imported[k], @imported_by[k])
301319
end
302320
clone
303321
end
304322
end
305323

306324
end
325+

lib/msf/core/exploit/powershell.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def make_subs(script, subs)
5858
# @return [String] Encoded script
5959
def encode_script(script_in, eof = nil)
6060
opts = {}
61-
datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/i && v }.keys.map do |k|
61+
datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/ && v }.keys.map do |k|
6262
mod_method = k.split('::').last.intern
6363
opts[mod_method.to_sym] = true
6464
end
@@ -76,7 +76,7 @@ def encode_script(script_in, eof = nil)
7676
# @return [String] Compressed script with decompression stub
7777
def compress_script(script_in, eof=nil)
7878
opts = {}
79-
datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/i && v }.keys.map do |k|
79+
datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/ && v }.keys.map do |k|
8080
mod_method = k.split('::').last.intern
8181
opts[mod_method.to_sym] = true
8282
end

modules/post/multi/recon/local_exploit_suggester.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def is_session_type_compat?(mod)
8888

8989

9090
def set_module_options(mod)
91-
self.datastore.each do |k,v|
91+
self.datastore.each_pair do |k,v|
9292
mod.datastore[k] = v
9393
end
9494
if !mod.datastore['SESSION'] && session.present?

0 commit comments

Comments
 (0)