Repository: p0dalirius/DumpSMBShare
Branch: master
Commit: 1e5ceb1690d0
Files: 4
Total size: 14.0 KB
Directory structure:
gitextract_hi7mzzpz/
├── .github/
│ └── FUNDING.yml
├── DumpSMBShare.py
├── README.md
└── requirements.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: p0dalirius
patreon: Podalirius
================================================
FILE: DumpSMBShare.py
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File name : DumpSMBShare.py
# Author : Podalirius (@podalirius_)
# Date created : 6 Jul 2022
import argparse
import os
import sys
import traceback
from impacket import version
from impacket.examples import logger, utils
from impacket.smbconnection import SMBConnection, SMB2_DIALECT_002, SMB2_DIALECT_21, SMB_DIALECT, SessionError
class BFSDumpShare(object):
"""docstring for BFSDumpShare."""
def __init__(self, smb, share, base_dir="", dump_dir=".", quiet=False, debug=False, only_list_files=False):
super(BFSDumpShare, self).__init__()
self.quiet = quiet
self.debug = debug
self.smb = smb
self.share = share
self.dump_dir = dump_dir
self.base_dir = base_dir
self.only_list_files = only_list_files
if not os.path.exists(self.dump_dir):
os.makedirs(self.dump_dir, exist_ok=True)
def list_shares(self):
print("[>] Listing shares ...")
resp = self.smb.listShares()
shares = []
for k in range(len(resp)):
shares.append(resp[k]["shi1_netname"][:-1])
return shares
def dump_share(self, targetfile="", extensions=[], base_dir=None):
if base_dir is not None:
self.base_dir = base_dir
print("[>] Dumping files with extensions %s ... " % extensions)
# Breadth-first search algorithm to recursively find .extension files
files = []
searchdirs = [self.base_dir + "/"]
while len(searchdirs) != 0:
next_dirs = []
for sdir in searchdirs:
if self.debug:
print("[>] Searching in %s " % sdir)
try:
for sharedfile in self.smb.listPath(self.share, sdir + "*", password=None):
if sharedfile.get_longname() not in [".", ".."]:
if sharedfile.is_directory():
if self.debug:
print("[>] Found directory %s/" % sharedfile.get_longname())
next_dirs.append(sdir + sharedfile.get_longname() + "/")
else:
if len(extensions) == 0 or any([sharedfile.get_longname().endswith("." + e) for e in extensions]) or sharedfile.get_longname() == targetfile:
if self.debug or not self.quiet or self.only_list_files:
print("[>] Found matching file %s" % (sdir + sharedfile.get_longname()))
full_path = sdir + sharedfile.get_longname()
files.append(full_path)
if not self.only_list_files:
self.dump_file(full_path)
else:
if self.debug:
print("[>] Found file %s" % sharedfile.get_longname())
except SessionError as e:
if self.debug:
print("[error] %s " % e)
searchdirs = next_dirs
if self.debug:
print("[>] Next iteration with %d folders." % len(next_dirs))
return files
def dump_file(self, filepath, only_file=False):
# Sanitize dir
filepath = filepath.replace("\\", "/")
_dir, _file = os.path.dirname(filepath), os.path.basename(filepath)
if _dir.startswith("//"):
_dir = _dir[2:]
try:
if only_file:
if not os.path.exists(self.dump_dir):
os.makedirs(self.dump_dir, exist_ok=True)
path = self.dump_dir + "/" + _file
else:
# Create directory
if _dir.startswith(self.base_dir.rstrip('/')):
_dir = _dir[len(self.base_dir.rstrip('/')):].lstrip('/')
if not os.path.exists(self.dump_dir + "/" + _dir + "/"):
os.makedirs(self.dump_dir + "/" + _dir + "/", exist_ok=True)
path = self.dump_dir + "/" + _dir + "/" + _file
# Write file
f = open(path, "wb")
self.smb.getFile(self.share, filepath, f.write)
f.close()
return True
except SessionError as e:
if self.debug:
print("[error] %s" % e)
return False
except Exception as e:
raise
def parse_args():
print("DumpSMBShare v1.3 - by Remi GASCOU (Podalirius)\n")
parser = argparse.ArgumentParser(add_help=True, description="A script to dump files and folders remotely from a Windows SMB share.")
parser.add_argument("target", action="store", help="[[domain/]username[:password]@]<targetName or address>")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-s", "--share", type=str, default=None, help="SMB Share to dump")
group.add_argument("-l", "--list-shares", default=False, action="store_true", help="Lists SMB shares on the remote machine.")
parser.add_argument("-L", "--list-files", default=False, action="store_true", help="Lists all the files present in the SMB share.")
parser.add_argument("-e", "--extensions", type=str, required=False, default="", help="Extensions")
parser.add_argument("-D", "--dump-dir", type=str, required=False, default=None, help="Dump directory")
parser.add_argument("-f", "--file", type=str, default=None, help="SMB file to dump")
parser.add_argument("-B", "--base-dir", type=str, required=False, default="", help="Directory to search in (Default: /)")
parser.add_argument("--debug", action="store_true", help="Turn on debug output. (Default: False)")
parser.add_argument("-q", "--quiet", action="store_true", default=False, help="Turn DEBUG output ON")
group = parser.add_argument_group("authentication")
group.add_argument("-H", "--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", "--kerberos", 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("-A", "--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("-I", "--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("-P", "--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_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:
if args.debug:
print("[>] SMBv1 dialect used")
elif dialect == SMB2_DIALECT_002:
if args.debug:
print("[>] SMBv2.0 dialect used")
elif dialect == SMB2_DIALECT_21:
if args.debug:
print("[>] SMBv2.1 dialect used")
else:
if args.debug:
print("[>] SMBv3.0 dialect used")
if args.kerberos 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:
if args.debug:
print("[>] GUEST Session Granted")
else:
if args.debug:
print("[>] USER Session Granted")
return smbClient
if __name__ == "__main__":
args = parse_args()
args.extensions = [e.strip() for e in args.extensions.strip().split(",") if len(e.strip()) != 0]
domain, username, password, address, lmhash, nthash = parse_target(args)
try:
smbClient = init_smb_session(args, domain, username, password, address, lmhash, nthash)
if args.list_shares:
if args.dump_dir is None:
g = BFSDumpShare(smbClient, args.share)
else:
g = BFSDumpShare(smbClient, args.share, dump_dir=args.dump_dir)
shares = g.list_shares()
for s in shares:
print(" - %s" % s)
print()
else:
if args.dump_dir is None:
args.dump_dir = "./%s/%s/" % (address, args.share)
g = BFSDumpShare(smbClient, args.share, base_dir=args.base_dir, dump_dir=args.dump_dir, quiet=args.quiet, debug=args.debug, only_list_files=args.list_files)
if args.share in g.list_shares():
if args.file is not None:
print("[+] Dumping file '%s' from share '%s'" % (args.file, args.share))
g.base_dir = os.path.basename(args.base_dir)
g.dump_file(args.file, only_file=True)
else:
dumped_files = g.dump_share(extensions=args.extensions)
if not args.list_files:
print("[+] Dumped %d files from share '%s'" % (len(dumped_files), args.share))
else:
print("[>] Cannot find share '%s'" % args.share)
except Exception as e:
raise e
================================================
FILE: README.md
================================================

<p align="center">
A python script to dump files and folders remotely from a Windows SMB share.
<br>
<img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/p0dalirius/DumpSMBShare">
<a href="https://twitter.com/intent/follow?screen_name=podalirius_" title="Follow"><img src="https://img.shields.io/twitter/follow/podalirius_?label=Podalirius&style=social"></a>
<a href="https://www.youtube.com/c/Podalirius_?sub_confirmation=1" title="Subscribe"><img alt="YouTube Channel Subscribers" src="https://img.shields.io/youtube/channel/subscribers/UCF_x5O7CSfr82AfNVTKOv_A?style=social"></a>
<br>
</p>
## Features
- [x] Only list shares with `--list-shares`.
- [x] Select only files with given extensions (with `--extensions`) or all files.
- [x] Choose the local folder to dump to with `--dump-dir`.
- [x] Select base folder to search from in the share with `--base-dir`.
## Usage
```
$ ./DumpSMBShare.py -h
DumpSMBShare v1.3 - by Remi GASCOU (Podalirius)
usage: Dump.py [-h] (-s SHARE | -l) [-e EXTENSIONS] [-D DUMP_DIR] [-f FILE] [-B BASE_DIR] [--debug] [-q] [-H LMHASH:NTHASH] [--no-pass] [-k] [-A hex key]
[--dc-ip ip address] [-I ip address] [-P [destination port]]
target
positional arguments:
target [[domain/]username[:password]@]<targetName or address>
optional arguments:
-h, --help show this help message and exit
-s SHARE, --share SHARE
SMB Share to dump
-l, --list-shares Lists SMB shares on the remote machine.
-L, --list-files Lists all the files present in the SMB share.
-e EXTENSIONS, --extensions EXTENSIONS
Extensions
-D DUMP_DIR, --dump-dir DUMP_DIR
Dump directory
-f FILE, --file FILE SMB file to dump
-B BASE_DIR, --base-dir BASE_DIR
Directory to search in (Default: /)
--debug Turn on debug output. (Default: False)
-q, --quiet Turn DEBUG output ON
authentication:
-H LMHASH:NTHASH, --hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
--no-pass Don't ask for password (useful for -k)
-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
-A hex key, --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
-I ip address, --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
-P [destination port], --port [destination port]
Destination port to connect to SMB Server
```
## Example
+ Dump all files from the `SYSVOL` share:
```
./DumpSMBShare.py 'LAB.local/user2:Admin123@192.168.2.1' --debug
```


## Contributing
Pull requests are welcome. Feel free to open an issue if you want to add other features.
================================================
FILE: requirements.txt
================================================
impacket
gitextract_hi7mzzpz/ ├── .github/ │ └── FUNDING.yml ├── DumpSMBShare.py ├── README.md └── requirements.txt
SYMBOL INDEX (8 symbols across 1 files)
FILE: DumpSMBShare.py
class BFSDumpShare (line 16) | class BFSDumpShare(object):
method __init__ (line 19) | def __init__(self, smb, share, base_dir="", dump_dir=".", quiet=False,...
method list_shares (line 32) | def list_shares(self):
method dump_share (line 40) | def dump_share(self, targetfile="", extensions=[], base_dir=None):
method dump_file (line 78) | def dump_file(self, filepath, only_file=False):
function parse_args (line 110) | def parse_args():
function parse_target (line 150) | def parse_target(args):
function init_smb_session (line 169) | def init_smb_session(args, domain, username, password, address, lmhash, ...
Condensed preview — 4 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (15K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 85,
"preview": "# These are supported funding model platforms\n\ngithub: p0dalirius\npatreon: Podalirius"
},
{
"path": "DumpSMBShare.py",
"chars": 10758,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# File name : DumpSMBShare.py\n# Author : Podalirius "
},
{
"path": "README.md",
"chars": 3439,
"preview": "\n\n<p align=\"center\">\n A python script to dump files and folders remotely from a Windows SMB sh"
},
{
"path": "requirements.txt",
"chars": 8,
"preview": "impacket"
}
]
About this extraction
This page contains the full source code of the p0dalirius/DumpSMBShare GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 4 files (14.0 KB), approximately 3.5k tokens, and a symbol index with 8 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.