I could not resist
@client = client
@@exec_opts = Rex::Parser::Arguments.new(
"-h" => [ false,"Help menu." ]
)
@@exec_opts.parse(args) { |opt, idx, val|
case opt
when "-h"
print_line("check_ad -- Checks if host is part of a domain if it is it check if it is a DC")
print_line("and enumerates info of the DC.")
print_line("USAGE: run check_ad")
print_line(@@exec_opts.usage)
raise Rex::Script::Completed
end
}
#Enumerates the subkeys of a given registry key returns array of subkeys
def reg_enumkeys(key)
subkeys = []
begin
root_key, base_key = @client.sys.registry.splitkey(key)
open_key = @client.sys.registry.open_key(root_key, base_key, KEY_READ)
keys = open_key.enum_key
keys.each { |subkey|
subkeys << subkey
}
open_key.close
end
return subkeys
end
#Returns the data of a given registry key and value
def reg_getvaldata(key,valname)
value = nil
begin
root_key, base_key = @client.sys.registry.splitkey(key)
open_key = @client.sys.registry.open_key(root_key, base_key, KEY_READ)
v = open_key.query_value(valname)
value = v.data
open_key.close
end
return value
end
#Returns logon server value
def get_dc
user = @client.sys.config.getuid
if user != "NT AUTHORITY\\SYSTEM"
logonsrv = @client.fs.file.expand_path("%logonserver%")
print_status("Domain Controller: #{logonsrv}")
else
user_sid = []
key = "HKU\\"
root_key, base_key = @client.sys.registry.splitkey(key)
open_key = @client.sys.registry.open_key(root_key, base_key)
keys = open_key.enum_key
keys.each do |k|
user_sid << k if k =~ /S-1-5-21-\d*-\d*-\d*-\d{4}$/
end
user_sid.each do |us|
logonsrv = reg_getvaldata("HKU\\#{us}\\Volatile Environment","reg_getvaldata")
end
print_status("Domain Controller: #{logonsrv}")
end
end
#check if host is a Domain Controller
def check_dc
srvs = reg_enumkeys("HKLM\\SYSTEM\\CurrentControlSet\\Services")
if srvs.include?("NTDS")
print_status("This server appears to be a Domain Controller")
rootdomian = reg_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Services\\NTDS\\Parameters","Root Domain")
machinedn = reg_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Services\\NTDS\\Parameters","Machine DN Name")
database_file = reg_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Services\\NTDS\\Parameters","DSA Database file")
gc = reg_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Services\\NTDS\\Parameters","Global Catalog Promotion Complete")
print_status("Root Domain: #{rootdomian}")
print_status("Machine DN: #{machinedn}")
print_status("Database File: #{database_file}")
if gc.to_i == 1
print_status("Global Catalog: True")
else
print_status("Global Catalog: False")
end
end
end
def srv_dc_enum(domain)
print_status("SRV Records:")
srout = []
garbage = []
srv_list = "_ldap._tcp.","_gc._tcp.","_kerberos._tcp.", "_kerberos._udp."
srv_list.each do |srv|
r = session.sys.process.execute("nslookup -query=srv #{srv}#{domain}", nil, {'Hidden' => true, 'Channelized' => true})
while(d = r.channel.read)
srout << d
end
r.channel.close
r.close
results = srout.join.split(/\n/)
results.each do |rec|
if rec.match(/\s*internet\saddress\s\=\s/)
garbage << rec.split(/\s*internet\saddress\s\=/)
print_status("\tfor #{srv}#{domain} #{garbage[0].join.sub(" "," ")}")
garbage.clear
end
garbage.clear
srout.clear
end
end
end
#Get domain and hostname information
domain = reg_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters","Domain")
hostname = reg_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters","Hostname")
#check if domain name is empty
if domain == ""
print_status("This host appears to not be part of a domain")
else
print_status("Hostname: #{hostname}")
print_status("Domain: #{domain}")
srv_dc_enum(domain)
get_dc
os = @client.sys.config.sysinfo['OS']
if os =~ /2000|NET|2003|2008/
check_dc
end
end
meterpreter > run check_ad
[*] Hostname: awin2k301
[*] Domain: acmeprodinc.com
[*] SRV Records:
[*] for _ldap._tcp.acmeprodinc.com awin2k301.acmeprodinc.com 10.10.10.3
[*] for _gc._tcp.acmeprodinc.com awin2k301.acmeprodinc.com 10.10.10.3
[*] for _kerberos._tcp.acmeprodinc.com awin2k301.acmeprodinc.com
10.10.10.3
[*] for _kerberos._udp.acmeprodinc.com awin2k301.acmeprodinc.com
10.10.10.3
[*] Domain Controller: \\AWIN2K301
[*] This server appears to be a Domain Controller
[*] Root Domain: DC=acmeprodinc,DC=com
[*] Machine DN: CN=NTDS
Settings,CN=AWIN2K301,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=acmeprodinc,DC=com
[*] Database File: C:\WINDOWS\NTDS\ntds.dit
[*] Global Catalog: True
meterpreter >
Let me know if you like it and any bugs or improvements.
Cheers,
Carlos
On Mar 25, 2010, at 8:12 PM, Butturini, Russell wrote:
> These solutuons are useful, but you're assuming a machine joined to the
> domain, running in the context of an authenticated user session, with
> knowledge of the internal domain name.
>
> ----- Original Message -----
> From: [email protected]
> <[email protected]>
> To: PaulDotCom Security Weekly Mailing List <[email protected]>
> Sent: Thu Mar 25 16:36:13 2010
> Subject: Re: [Pauldotcom] detecting PDCs
>
> Indeed.
> Similar to ethe cho %logonserver% method is:
>
> Systeminfo | findstr /I /C:"logon server"
> But a nice way is to get it from dns:
> Nslookup -type=srv _ldap._tcp.pdc._msdcs.<domainname>
> Will give you the same answer as logonserver, to see all DC's change
> pdc to just dc. I got 8 DCs doing this at work all of which I know are
> dcs
> -Josh
>
> On Mar 25, 2010, at 5:07 PM, k41zen <[email protected]> wrote:
>
>> depends on how auth'd you are to the domain I guess, but dsquery is
>> very useful too
>>
>> http://www.computerperformance.co.uk/Logon/DSquery.htm
>>
>> http://tactech.net/2009/09/28/how-to-search-for-a-domain-controller/
>>
>> http://technet.microsoft.com/en-us/library/cc732885%28WS.10%29.aspx
>>
>>
>> On 25 Mar 2010, at 10:54, Robin Wood wrote:
>>
>>> Hi
>>> I'm wondering what techniques people are using to detect domain
>>> controllers when they get on networks. I've asked a few people and
>>> the
>>> standard answer seems to be to look for the DNS server as the PDC is
>>> usually also acting as the DNS server. Has anyone else got any better
>>> or alternative techniques they use?
>>>
>>> Robin
>>> _______________________________________________
>>> Pauldotcom mailing list
>>> [email protected]
>>> http://mail.pauldotcom.com/cgi-bin/mailman/listinfo/pauldotcom
>>> Main Web Site: http://pauldotcom.com
>>>
>>
>> _______________________________________________
>> Pauldotcom mailing list
>> [email protected]
>> http://mail.pauldotcom.com/cgi-bin/mailman/listinfo/pauldotcom
>> Main Web Site: http://pauldotcom.com
> _______________________________________________
> Pauldotcom mailing list
> [email protected]
> http://mail.pauldotcom.com/cgi-bin/mailman/listinfo/pauldotcom
> Main Web Site: http://pauldotcom.com
>
>
> ******************************************************************************
> This email contains confidential and proprietary information and is not to be
> used or disclosed to anyone other than the named recipient of this email,
> and is to be used only for the intended purpose of this communication.
> ******************************************************************************
> _______________________________________________
> Pauldotcom mailing list
> [email protected]
> http://mail.pauldotcom.com/cgi-bin/mailman/listinfo/pauldotcom
> Main Web Site: http://pauldotcom.com
_______________________________________________
Pauldotcom mailing list
[email protected]
http://mail.pauldotcom.com/cgi-bin/mailman/listinfo/pauldotcom
Main Web Site: http://pauldotcom.com