from __future__ import print_function
from builtins import str
import argparse
import json
import os.path
import re
from time import strftime, gmtime
class PrettyOuput(object):
def d2b(self, a):
tbin = []
while a:
tbin.append(a % 2)
a //= 2
t2bin = tbin[::-1]
if len(t2bin) != 8:
for x in range(6 - len(t2bin)):
t2bin.insert(0, 0)
return ''.join([str(g) for g in t2bin])
def convert(self, time):
if isinstance(time, str):
return time
if time == 0:
return "None"
if time == -9223372036854775808:
return "Not Set"
sec = abs(time) // 10000000
days = sec // 86400
sec -= 86400*days
hrs = sec // 3600
sec -= 3600*hrs
mins = sec // 60
sec -= 60*mins
result = ""
if days > 1:
result += "{0} days ".format(days)
elif days == 1:
result += "{0} day ".format(days)
if hrs > 1:
result += "{0} hours ".format(hrs)
elif hrs == 1:
result += "{0} hour ".format(hrs)
if mins > 1:
result += "{0} minutes ".format(mins)
elif mins == 1:
result += "{0} minute ".format(mins)
return result
def password_complexity(self, data):
print('''
+-----------------------------------------+
| Password Policy Information |
+-----------------------------------------+
''')
print("[+] Password Info for Domain:", data[0]['attributes']['dc'][0].upper())
print("\t[+] Minimum password length: ", data[0]['attributes']['instanceType'][0])
print("\t[+] Password history length:", data[0]['attributes']['pwdHistoryLength'][0])
password_properties = self.d2b(data[0]['attributes']['pwdProperties'][0])
print("\t[+] Password Complexity Flags:", password_properties)
print("")
print("\t\t[+] Domain Refuse Password Change:", password_properties[0])
print("\t\t[+] Domain Password Store Cleartext:", password_properties[1])
print("\t\t[+] Domain Password Lockout Admins:", password_properties[2])
print("\t\t[+] Domain Password No Clear Change:", password_properties[3])
print("\t\t[+] Domain Password No Anon Change:", password_properties[4])
print("\t\t[+] Domain Password Complex:", password_properties[5])
print("")
print("\t[+] Maximum password age:", self.convert(data[0]['attributes']['maxPwdAge'][0]))
print("\t[+] Minimum password age:", self.convert(data[0]['attributes']['minPwdAge'][0]))
print("\t[+] Reset Account Lockout Counter:", self.convert(data[0]['attributes']['lockoutDuration'][0]))
print("\t[+] Account Lockout Threshold:", data[0]['attributes']['lockoutThreshold'][0])
print("\t[+] Forced Log off Time:", self.convert(data[0]['attributes']['forceLogoff'][0]))
def domain_info(self, data):
print('''
+--------------------------------------+
| Getting Domain Sid For |
+--------------------------------------+
''')
print('[+] Domain Name:', data[0]['attributes']['dc'][0])
print('Domain Sid:', data[0]['attributes']['objectSid'][0])
print('')
return data[0]['attributes']['dc'][0]
def user_info(self, users, dc):
print('''
+------------------------+
| Users Infos |
+------------------------+
''')
for user in users:
desc = user['attributes'].get('description')[0] if user['attributes'].get('description') else "(null)"
print("Account: " + dc + "\\" + user['attributes']['sAMAccountName'][0] + "\tName: " + user['attributes']['name'][0] + "\tDesc: " + desc)
print("")
for user in users:
print("user:[" + user['attributes']['sAMAccountName'][0] + "]")
print("")
def groups_info(self, groups, dc):
print('''
+------------------------+import os.path
| Groups Infos |
+------------------------+
''')
for group in groups:
print("group:[" + group['attributes']['name'][0] + "]")
for group in groups:
if group['attributes'].get('member'):
users = re.findall(r"^CN=([\w\s\-\_\{\}\.\$\#]+)", '\n'.join(group['attributes']['member']), re.M)
if users:
print("\n[+] Getting domain group memberships:")
for user in users:
if user == "S-1-5-11":
user = "NT AUTHORITY\\Authenticated Users"
elif user == "S-1-5-4":
user = "NT AUTHORITY\\INTERACTIVE"
elif user == "S-1-5-17":
user = "NT AUTHORITY\\IUSR"
print("Group '" + group['attributes']['name'][0] + "' has member: " + dc + "\\" + user)
def main():
parser = argparse.ArgumentParser(description='LDAPDomainDump to pretty output like enum4linux.')
#Main parameters
parser.add_argument("-d", "--directory", help="The ldapdomaindump directory where the json files are saved. Required files: domain_users.json, domain_groups.json and domain_policy.json")
args = parser.parse_args()
if args.directory:
with open(args.directory + '/domain_policy.json') as f:
domain = json.load(f)
with open(args.directory + '/domain_users.json') as f:
users = json.load(f)
with open(args.directory + '/domain_groups.json') as f:
groups = json.load(f)
pretty = PrettyOuput()
dc = pretty.domain_info(domain)
pretty.password_complexity(domain)
pretty.user_info(users, dc.upper())
pretty.groups_info(groups, dc.upper())
else:
print("Missing parameter --directory /output/")
if __name__ == "__main__":
main()