Skip to content

Commit

Permalink
FindUncommonShares.py version 1.3
Browse files Browse the repository at this point in the history
Fixes #1
Fixes #2
Fixes #3
  • Loading branch information
p0dalirius committed Oct 7, 2021
1 parent 1a35791 commit 148542d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 21 deletions.
Binary file modified .github/example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 51 additions & 19 deletions FindUncommonShares.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,26 @@
# Remi GASCOU (@podalirius_)
#


import argparse
import sys
import traceback
import logging
import threading
from concurrent.futures import ThreadPoolExecutor
from impacket import version
from impacket.examples import logger, utils
from impacket.smbconnection import SMBConnection, SMB2_DIALECT_002, SMB2_DIALECT_21, SMB_DIALECT, SessionError
import ldap3
import nslookup
import json
import time


COMMON_SHARES = [
"ADMIN$", "IPC$", "C$", "NETLOGON", "SYSVOL"
]


def get_domain_computers(target_dn, ldap_server, ldap_session):
results = {}
ldap_session.search(target_dn, "(objectCategory=computer)", attributes=["dNSHostName", "sAMAccountName"])
Expand All @@ -40,15 +46,19 @@ def get_domain_computers(target_dn, ldap_server, ldap_session):
}
return results


def parse_args():
parser = argparse.ArgumentParser(add_help=True, description='Find uncommon SMB shares on remote machines.')
parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output')
parser.add_argument('--use-ldaps', action='store_true', help='Use LDAPS instead of LDAP')
parser.add_argument("-q", "--quiet", dest="quiet", action="store_true", default=False, help="show no information at all")
parser.add_argument("-debug", dest="debug", action="store_true", default=False, help="Debug mode")
parser.add_argument("-t", "--threads", dest="threads", action="store", type=int, default=5, required=False, help="Number of threads (default: 5)")
parser.add_argument("-o", "--output-file", dest="output_file", type=str, default="shares.json", required=False, help="Output file to store the results in. (default: shares.json)")


authconn = parser.add_argument_group('authentication & connection')
authconn.add_argument('--dc-ip', action='store', metavar="ip address", help='IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted it will use the domain part (FQDN) specified in the identity parameter')
authconn.add_argument('--dc-ip', required=True, action='store', metavar="ip address", help='IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted it will use the domain part (FQDN) specified in the identity parameter')
authconn.add_argument("-d", "--domain", dest="auth_domain", metavar="DOMAIN", action="store", help="(FQDN) domain to authenticate to")
authconn.add_argument("-u", "--user", dest="auth_username", metavar="USER", action="store", help="user to authenticate with")

Expand Down Expand Up @@ -109,6 +119,7 @@ def init_ldap_connection(target, tls_version, args, domain, username, password,

return ldap_server, ldap_session


def init_ldap_session(args, domain, username, password, lmhash, nthash):
if args.use_kerberos:
target = get_machine_name(args, domain)
Expand Down Expand Up @@ -319,20 +330,33 @@ def init_smb_session(args, target_ip, domain, username, password, address, lmhas
return smbClient


def worker(args, target_ip, domain, username, password, address, lmhash, nthash):
try:
smbClient = init_smb_session(args, target_ip, domain, username, password, address, lmhash, nthash)
resp = smbClient.listShares()

for share in resp:
sharename = share['shi1_netname'][:-1]
if sharename not in COMMON_SHARES:
print("[>] Found uncommon share '%s' on '%s'" % (sharename, address))
except Exception as e:
pass
# if logging.getLogger().level == logging.DEBUG:
# traceback.print_exc()
# logging.error(str(e))
def worker(args, target_name, domain, username, password, address, lmhash, nthash, lock):
target_ip = nslookup.Nslookup(dns_servers=[args.dc_ip]).dns_lookup(target_name).answer
if len(target_ip) != 0:
target_ip = target_ip[0]
try:
smbClient = init_smb_session(args, target_ip, domain, username, password, address, lmhash, nthash)
resp = smbClient.listShares()

for share in resp:
sharename = share['shi1_netname'][:-1]
if sharename not in COMMON_SHARES:
lock.acquire()
print("[>] Found uncommon share '\x1b[93m%s\x1b[0m' on '\x1b[96m%s\x1b[0m'" % (sharename, address))
d = {
"sharename": sharename,
"uncpath": "\\".join(['', '', target_ip, sharename, '']),
"computer": target_name
}
f = open(args.output_file, "a")
f.write(json.dumps(d)+"\n")
f.close()
lock.release()
except Exception as e:
pass
# if logging.getLogger().level == logging.DEBUG:
# traceback.print_exc()
# logging.error(str(e))

if __name__ == '__main__':
print(version.BANNER)
Expand All @@ -356,12 +380,20 @@ def worker(args, target_ip, domain, username, password, address, lmhash, nthash)
lmhash=auth_lm_hash,
nthash=auth_nt_hash
)

print("[>] Extracting all computers ...")
dn = ','.join(["DC=%s" % part for part in args.auth_domain.split('.')])
computers = get_domain_computers(dn, ldap_server, ldap_session)
print("[+] Found %d computers." % len(computers.keys()))
print()

print("[>] Enumerating shares ...")
for ck in computers.keys():
computer = computers[ck]
worker(args, computer['dNSHostName'], args.auth_domain, args.auth_username, args.auth_password, computer['dNSHostName'], auth_lm_hash, auth_nt_hash)
# Overwrite output file
open(args.output_file, "w").close()
# Setup thread lock to properly write in the file
lock = threading.Lock()
# Waits for all the threads to be completed
with ThreadPoolExecutor(max_workers=min(args.threads, len(computers.keys()))) as tp:
for ck in computers.keys():
computer = computers[ck]
tp.submit(worker, args, computer['dNSHostName'], args.auth_domain, args.auth_username, args.auth_password, computer['dNSHostName'], auth_lm_hash, auth_nt_hash, lock)
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The script [FindUncommonShares.py](https://github.com/p0dalirius/FindUncommonSha
$ ./FindUncommonShares.py -h
Impacket v0.9.24.dev1+20210906.175840.50c76958 - Copyright 2021 SecureAuth Corporation
usage: FindUncommonShares.py [-h] [-ts] [--use-ldaps] [-q] [-debug] [--dc-ip ip address] [-d DOMAIN] [-u USER]
usage: FindUncommonShares.py [-h] [-ts] [--use-ldaps] [-q] [-debug] [-t THREADS] [-o OUTPUT_FILE] --dc-ip ip address [-d DOMAIN] [-u USER]
[--no-pass | -p PASSWORD | -H [LMHASH:]NTHASH | --aes-key hex key] [-k]
Find uncommon SMB shares on remote machines.
Expand All @@ -21,6 +21,10 @@ optional arguments:
--use-ldaps Use LDAPS instead of LDAP
-q, --quiet show no information at all
-debug Debug mode
-t THREADS, --threads THREADS
Number of threads (default: 5)
-o OUTPUT_FILE, --output-file OUTPUT_FILE
Output file to store the results in. (default: shares.json)
authentication & connection:
--dc-ip ip address IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted it will use the domain part (FQDN)
Expand All @@ -36,7 +40,7 @@ authentication & connection:
NT/LM hashes, format is LMhash:NThash
--aes-key hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-k, --kerberos Use Kerberos authentication. Grabs credentials from .ccache file (KRB5CCNAME) based on target parameters. If valid credentials
cannot be found, it will use the ones specified in the command line
cannot be found, it will use the ones specified in the command line
```

## Examples :
Expand All @@ -55,6 +59,15 @@ Impacket v0.9.24.dev1+20210906.175840.50c76958 - Copyright 2021 SecureAuth Corpo
[]$
```

Results are exported in JSON:

```json
{"sharename": "AnotherShare", "uncpath": "\\\\192.168.2.11\\AnotherShare\\", "computer": "PC01.LAB.local"}
{"sharename": "Users", "uncpath": "\\\\192.168.2.11\\Users\\", "computer": "PC01.LAB.local"}
{"sharename": "Users", "uncpath": "\\\\192.168.2.1\\Users\\", "computer": "DC01.LAB.local"}
{"sharename": "WeirdShare", "uncpath": "\\\\192.168.2.1\\WeirdShare\\", "computer": "DC01.LAB.local"}
```

## Credits

- Feature suggested in [impacket issue #1176](https://github.com/SecureAuthCorp/impacket/issues/1176) by [@CaledoniaProject](https://github.com/CaledoniaProject)

0 comments on commit 148542d

Please sign in to comment.