Skip to content

Commit

Permalink
FindUncommonShares.py version 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
p0dalirius committed Oct 6, 2021
1 parent 6c941e2 commit e4dfc53
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# These are supported funding model platforms

github: p0dalirius
patreon: Podalirius
Binary file added .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.
148 changes: 148 additions & 0 deletions FindUncommonShares.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/usr/bin/env python
# Impacket - Collection of Python classes for working with network protocols.
#
# SECUREAUTH LABS. Copyright (C) 2021 SecureAuth Corporation. All rights reserved.
#
# This software is provided under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Description:
# Find uncommon SMB shares on remote machines
#
# Author:
# Remi GASCOU (@podalirius_)
#


import argparse
import sys
import traceback
import logging
from impacket import version
from impacket.examples import logger, utils
from impacket.smbconnection import SMBConnection, SMB2_DIALECT_002, SMB2_DIALECT_21, SMB_DIALECT, SessionError

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

def parse_args():
parser = argparse.ArgumentParser(add_help=True, description='Find uncommon SMB shares on remote machines')
parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>')
parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output')
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')

group = parser.add_argument_group('authentication')
group.add_argument('-hashes', action="store", metavar="LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)')
group.add_argument('-k', action="store_true",
help='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')
group.add_argument('-aesKey', action="store", metavar="hex key", help='AES key to use for Kerberos Authentication '
'(128 or 256 bits)')

group = parser.add_argument_group('connection')

group.add_argument('-dc-ip', action='store', metavar="ip address",
help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in '
'the target parameter')
group.add_argument('-target-ip', action='store', metavar="ip address",
help='IP Address of the target machine. If omitted it will use whatever was specified as target. '
'This is useful when target is the NetBIOS name and you cannot resolve it')
group.add_argument('-port', choices=['139', '445'], nargs='?', default='445', metavar="destination port",
help='Destination port to connect to SMB Server')
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)

return parser.parse_args()


def parse_target(args):
domain, username, password, address = utils.parse_target(args.target)

if args.target_ip is None:
args.target_ip = address

if domain is None:
domain = ''

if password == '' and username != '' and args.hashes is None and args.no_pass is False and args.aesKey is None:
from getpass import getpass

password = getpass("Password:")

if args.aesKey is not None:
args.k = True

if args.hashes is not None:
lmhash, nthash = args.hashes.split(':')
else:
lmhash = ''
nthash = ''

return domain, username, password, address, lmhash, nthash


def init_logger(args):
# Init the example's logger theme and debug level
logger.init(args.ts)
if args.debug is True:
logging.getLogger().setLevel(logging.DEBUG)
# Print the Library's installation path
logging.debug(version.getInstallationPath())
else:
logging.getLogger().setLevel(logging.INFO)
logging.getLogger('impacket.smbserver').setLevel(logging.ERROR)


def init_smb_session(args, domain, username, password, address, lmhash, nthash):
smbClient = SMBConnection(address, args.target_ip, sess_port=int(args.port))
dialect = smbClient.getDialect()
if dialect == SMB_DIALECT:
logging.debug("SMBv1 dialect used")
elif dialect == SMB2_DIALECT_002:
logging.debug("SMBv2.0 dialect used")
elif dialect == SMB2_DIALECT_21:
logging.debug("SMBv2.1 dialect used")
else:
logging.debug("SMBv3.0 dialect used")
if args.k is True:
smbClient.kerberosLogin(username, password, domain, lmhash, nthash, args.aesKey, args.dc_ip)
else:
smbClient.login(username, password, domain, lmhash, nthash)
if smbClient.isGuestSession() > 0:
logging.debug("GUEST Session Granted")
else:
logging.debug("USER Session Granted")
return smbClient


if __name__ == '__main__':
print(version.BANNER)
args = parse_args()
init_logger(args)

domain, username, password, address, lmhash, nthash = parse_target(args)
try:
smbClient = init_smb_session(args, domain, username, password, address, lmhash, nthash)

resp = smbClient.listShares()
found_uncommon_shares = False
for share in resp:
sharename = share['shi1_netname'][:-1]
if sharename not in COMMON_SHARES:
if not found_uncommon_shares:
print("[>] Found uncommon shares!")
found_uncommon_shares = True
print(" - '%s'" % sharename)
if found_uncommon_shares == False:
logging.error("No uncommon shares found.")

except Exception as e:
if logging.getLogger().level == logging.DEBUG:
traceback.print_exc()
logging.error(str(e))
70 changes: 69 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,69 @@
# FindUncommonShares
# FindUncommonShares

![](.github/example.png)

The script [FindUncommonShares.py](https://github.com/p0dalirius/FindUncommonShares/FindUncommonShares.py) is a Python equivalent of [PowerView](https://github.com/darkoperator/Veil-PowerView/)'s [Invoke-ShareFinder.ps1](https://github.com/darkoperator/Veil-PowerView/blob/master/PowerView/functions/Invoke-ShareFinder.ps1)

## Usage

```
$ ./FindUncommonShares.py
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
usage: FindUncommonShares.py [-h] [-xmlfile XMLFILE] [-share SHARE]
[-base-dir BASE_DIR] [-ts] [-debug]
[-hashes LMHASH:NTHASH] [-no-pass] [-k]
[-aesKey hex key] [-dc-ip ip address]
[-target-ip ip address]
[-port [destination port]]
target
Find uncommon SMB shares on remote machines
positional arguments:
target [[domain/]username[:password]@]<targetName or address>
optional arguments:
-h, --help show this help message and exit
-ts Adds timestamp to every logging output
-debug Turn DEBUG output ON
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k 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
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256
bits)
connection:
-dc-ip ip address IP Address of the domain controller. If omitted it
will use the domain part (FQDN) specified in the
target parameter
-target-ip ip address
IP Address of the target machine. If omitted it will
use whatever was specified as target. This is useful
when target is the NetBIOS name and you cannot resolve
it
-port [destination port]
Destination port to connect to SMB Server
```

## Examples :

```
[]$ ./FindUncommonShares.py 'LAB.local/user1:[email protected]'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[>] Found uncommon shares!
- 'Users'
- 'WeirdShare'
[]$
```

## Credits

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

0 comments on commit e4dfc53

Please sign in to comment.