├── requirements.txt ├── README.md └── exchange_hunter2.py /requirements.txt: -------------------------------------------------------------------------------- 1 | argparse 2 | ldap3 3 | colorama 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # exchange_hunter2 2 | Hunting for Microsoft Exchange the LDAP Way. 3 | 4 | This script uses a valid credential, a DC IP and Hostname to log into the DC over LDAP and query the LDAP server for the wherabouts of the Microsoft Exchange servers in the environment. 5 | 6 | # Help Menu: 7 | ``` 8 | ./exchange_hunter2.py -h 9 | usage: exchange_hunter2.py [-h] -u USERNAME -p PASSWORD -d DOMAIN -t TARGET 10 | 11 | Exchange Hunter via LDAP 12 | 13 | optional arguments: 14 | -h, --help show this help message and exit 15 | -u USERNAME, --username USERNAME 16 | username 17 | -p PASSWORD, --password PASSWORD 18 | password 19 | -d DOMAIN, --domain DOMAIN 20 | domain.com 21 | -t TARGET, --target TARGET 22 | Target Domain Controller 23 | ``` 24 | # Example Usage: 25 | ``` 26 | ./exchange_hunter2.py -u testuser1 -p Summer2019 -d tgore.com -t 192.168.204.132 27 | [+] Exchange Servers Found: 28 | EXCHANGE.tgore.com 29 | ``` 30 | -------------------------------------------------------------------------------- /exchange_hunter2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import argparse 3 | from ldap3 import Server, Connection, ALL 4 | from colorama import Fore, Style 5 | 6 | def get_args(): 7 | p = argparse.ArgumentParser(description="Exchange Hunter via LDAP") 8 | p.add_argument('-u','--username',type=str,help='username',required=True) 9 | p.add_argument('-p','--password',type=str,help='password',required=True) 10 | p.add_argument('-d','--domain',type=str,help='domain.com',required=True) 11 | p.add_argument('-t','--target',type=str,help='Target Domain Controller',required=True) 12 | 13 | args = p.parse_args() 14 | 15 | return args 16 | 17 | def main(): 18 | args = get_args() 19 | 20 | # 0xZDH Magic Right here... 21 | dcstring = ','.join(['dc=%s' % i for i in args.domain.split('.')]) 22 | 23 | server = Server(args.target, get_info=ALL) 24 | conn = Connection(server, user="%s\\%s" % (args.domain, args.username), password="%s" % args.password, authentication="NTLM", auto_bind=True) 25 | 26 | 27 | conn.search('cn=Configuration,%s' % dcstring,'(objectCategory=msExchExchangeServer)', attributes = ['adminDisplayName']) 28 | 29 | print(Fore.GREEN+Style.BRIGHT+"[+] Exchange Servers Found:"+Style.RESET_ALL) 30 | 31 | for entry in conn.response: 32 | try: 33 | print(Fore.GREEN+"%s.%s" % (entry['attributes']['adminDisplayName'],args.domain) + Style.RESET_ALL) 34 | except Exception as e: 35 | continue 36 | 37 | if __name__ == "__main__": 38 | main() 39 | --------------------------------------------------------------------------------