Skip to content

Instantly share code, notes, and snippets.

@faisalfs10x
Forked from 3xocyte/adidns_records.py
Last active October 6, 2022 09:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save faisalfs10x/63440041d22615c8322790176c5b3c53 to your computer and use it in GitHub Desktop.
Save faisalfs10x/63440041d22615c8322790176c5b3c53 to your computer and use it in GitHub Desktop.
get /etc/hosts entries from ADIDNS - port to py3
#!/usr/bin/env python
import argparse
import sys
import binascii
import socket
import re
from ldap3 import Server, Connection, NTLM, ALL, SUBTREE, ALL_ATTRIBUTES
# get /etc/hosts entries for domain-joined computers from A and AAAA records (via LDAP/ADIDNS) (@3xocyte)
def get_domain_dn(domain):
base_dn = ''
domain_parts = domain.split('.')
for i in domain_parts:
base_dn += 'DC=%s,' % i
base_dn = base_dn[:-1]
return base_dn
def ldap_login(dc_ip, username, password, ssl, domain):
if ssl == True:
s = Server(dc_ip, port = 636, use_ssl = True, get_info=ALL)
else:
s = Server(dc_ip, get_info=ALL)
domain_user = "%s\\%s" % (domain, username)
try:
c = Connection(s, user = domain_user, password = password, authentication=NTLM)
if c.bind() != True:
print ("[!] unable to bind")
sys.exit()
except (Exception, e):
print ("[!] unable to connect: %s") % str(e)
sys.exit()
return c
def get_entries(ldap_connection, domain, zone, dc_ip, forest, system):
if forest == True:
dn = "DC=%s,CN=MicrosoftDNS,DC=ForestDnsZones,%s" % (zone, get_domain_dn(domain))
elif system == True:
dn = "DC=%s,CN=MicrosoftDNS,CN=System,%s" % (zone, get_domain_dn(domain))
else:
dn = "DC=%s,CN=MicrosoftDNS,DC=DomainDNSZones,%s" % (zone, get_domain_dn(domain))
try:
ldap_connection.search(search_base=dn, search_scope=SUBTREE, attributes=ALL_ATTRIBUTES, search_filter='(!(name=_*))')
for entry in ldap_connection.entries:
try:
name = entry['name']
distinguished_name = entry['distinguishedName']
record = binascii.unhexlify(str(entry['dnsRecord']))
if record[2] == '\x01':
record_data = record[-ord(record[0]):]
address = socket.inet_ntop(socket.AF_INET, record_data)
dns_name = re.findall(r'DC=(.*?),', str(distinguished_name))[0] + '.' + re.findall(r'DC=(.*?),',str(distinguished_name))[1]
print ('%s\t%s') % (address, dns_name)
if record[2] == '\x1c':
record_data = record[-ord(record[0]):]
address = socket.inet_ntop(socket.AF_INET6, record_data)
dns_name = re.findall(r'DC=(.*?),', str(distinguished_name))[0] + '.' + re.findall(r'DC=(.*?),',str(distinguished_name))[1]
print ('%s\t%s') % (address, dns_name)
except:
pass
except (Exception, e):
print ("[!] exception raised: %s") % str(e)
if __name__ == '__main__':
parser = argparse.ArgumentParser(add_help = True, description = "get /etc/hosts entries for domain-joined computers from A and AAAA records (via LDAP/ADIDNS) (@3xocyte)")
parser.add_argument('-d', '--domain', action="store", default='', help='valid fully-qualified domain name', required=True)
parser.add_argument('-u', '--username', action="store", default='', help='valid username', required=True)
parser.add_argument('--ssl', action="store_true", default=False, help="connect to ldap over SSL")
password_or_ntlm = parser.add_mutually_exclusive_group(required=True)
password_or_ntlm.add_argument('-p', '--password', action="store", default='', help='valid password')
password_or_ntlm.add_argument('-n', '--nthash', action="store", default='', help='valid nt hash (32 hex chars)')
parser.add_argument('-z', '--zone', action="store", default='', help='DNS Zone (default will be domain)')
system_or_forest = parser.add_mutually_exclusive_group(required=False)
system_or_forest.add_argument('--forest', action="store_true", default=False, help='query ForestDnsZones (default is DomainDnsZones)')
system_or_forest.add_argument('--system', action="store_true", default=False, help='query System partition (legacy, default is DomainDnsZones)')
parser.add_argument('target_dc', help='ip address or hostname of dc')
options = parser.parse_args()
domain = options.domain
username = options.username
password = options.password
nthash = options.nthash
dc_ip = options.target_dc
ssl = options.ssl
zone = options.zone
forest = options.forest
system = options.system
if not options.zone:
zone = domain
if nthash:
password = '00000000000000000000000000000000:%s' % nthash
ldap_connection = ldap_login(dc_ip, username, password, ssl, domain)
get_entries(ldap_connection, zone, domain, dc_ip, forest, system)
ldap_connection.unbind()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment