Skip to content

Commit 8edaf13

Browse files
authored
Merge pull request Pennyw0rth#847 from A3-N/feat/mssql-database-table-list
Add --database option to MSSQL protocol
2 parents cb0f125 + 30cf671 commit 8edaf13

2 files changed

Lines changed: 73 additions & 1 deletion

File tree

nxc/protocols/mssql.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,3 +435,74 @@ def rid_brute(self, max_rid=None):
435435

436436
so_far += simultaneous
437437
return entries
438+
439+
def _qname(self, ident: str) -> str:
440+
if ident is None:
441+
return "[]"
442+
return "[" + str(ident).replace("]", "]]") + "]"
443+
444+
def list_databases(self):
445+
try:
446+
q = (
447+
"SELECT d.name AS DatabaseName, "
448+
" suser_sname(d.owner_sid) AS Owner "
449+
"FROM sys.databases d "
450+
"ORDER BY d.name;"
451+
)
452+
rows = self.conn.sql_query(q) or []
453+
if not rows:
454+
self.logger.display("No databases returned")
455+
return
456+
457+
self.logger.display("Enumerated databases")
458+
self.logger.highlight(f"{'Database Name':<30} {'Owner':<25}")
459+
self.logger.highlight(f"{'-' * 30} {'-' * 25}")
460+
for r in rows:
461+
self.logger.highlight(f"{r.get('DatabaseName', ''):<30} {r.get('Owner', ''):<25}")
462+
self.logger.highlight(f"Total: {len(rows)} database(s)")
463+
except Exception as e:
464+
self.logger.fail(f"Failed to enumerate databases: {e}")
465+
self.logger.debug("list_databases error", exc_info=True)
466+
467+
def database(self):
468+
db_arg = self.args.database
469+
470+
# nxc --database (no value) -> list
471+
if db_arg is True or db_arg is None:
472+
self.list_databases()
473+
return
474+
475+
# nxc --database <name> -> tables
476+
if isinstance(db_arg, str):
477+
try:
478+
safe = db_arg.replace("'", "''")
479+
exists = self.conn.sql_query(f"SELECT 1 FROM sys.databases WHERE name = N'{safe}';")
480+
if not exists:
481+
self.logger.fail(f"Database [{db_arg}] does not exist on the server.")
482+
return
483+
484+
tq = (
485+
f"SELECT t.name AS TableName, t.modify_date "
486+
f"FROM {self._qname(db_arg)}.sys.tables t "
487+
f"ORDER BY t.name;"
488+
)
489+
rows = self.conn.sql_query(tq) or []
490+
except Exception as e:
491+
self.logger.fail(f"Insufficient permissions or query error in [{db_arg}]: {e}")
492+
self.logger.debug("database() error", exc_info=True)
493+
return
494+
495+
if not rows:
496+
self.logger.display(f"Database [{db_arg}] has no user tables.")
497+
return
498+
499+
self.logger.display(f"Tables in database: {db_arg}")
500+
self.logger.highlight(f"{'Table Name':<50} {'Last Modified':<25}")
501+
self.logger.highlight(f"{'-' * 50} {'-' * 25}")
502+
for r in rows:
503+
mod = r.get("modify_date", "")
504+
if mod and hasattr(mod, "strftime"):
505+
mod = mod.strftime("%Y-%m-%d %H:%M:%S")
506+
self.logger.highlight(f"{r.get('TableName', ''):<50} {mod!s:<25}")
507+
self.logger.highlight(f"Total: {len(rows)} table(s)")
508+
return

nxc/protocols/mssql/proto_args.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ def proto_args(parser, parents):
66
mssql_parser.add_argument("-H", "--hash", metavar="HASH", dest="hash", nargs="+", default=[], help="NTLM hash(es) or file(s) containing NTLM hashes")
77
mssql_parser.add_argument("--port", default=1433, type=int, metavar="PORT", help="MSSQL port")
88
mssql_parser.add_argument("--mssql-timeout", help="SQL server connection timeout", type=int, default=5)
9-
mssql_parser.add_argument("-q", "--query", dest="mssql_query", metavar="QUERY", type=str, help="execute the specified query against the MSSQL DB")
9+
mssql_parser.add_argument("-q", "--query", dest="mssql_query", metavar="QUERY", type=str, help="execute the specified query against the mssql db")
10+
mssql_parser.add_argument("--database", nargs="?", const=True, metavar="NAME", help="list databases or list tables for NAME")
1011

1112
dgroup = mssql_parser.add_mutually_exclusive_group()
1213
dgroup.add_argument("-d", metavar="DOMAIN", dest="domain", type=str, help="domain name")

0 commit comments

Comments
 (0)