Skip to content

Add local database hash dump for mssql#1257

Open
Dfte wants to merge 8 commits into
Pennyw0rth:mainfrom
Dfte:add_hash_dump_mssql
Open

Add local database hash dump for mssql#1257
Dfte wants to merge 8 commits into
Pennyw0rth:mainfrom
Dfte:add_hash_dump_mssql

Conversation

@Dfte

@Dfte Dfte commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds the --db-hash core option that can be used to dump database users' hashes:

image

Type of change

Insert an "x" inside the brackets for relevant items (do not delete options)

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Deprecation of feature or functionality
  • This change requires a documentation update
  • This requires a third party update (such as Impacket, Dploot, lsassy, etc)
  • This PR was created with the assistance of AI (list what type of assistance, tool(s)/model(s) in the description)

Setup guide for the review

Run the following command:

poetry run nxc mssql TARGET -u USER -p PASS --db-hash

Screenshots (if appropriate):

Checklist:

Insert an "x" inside the brackets for completed and relevant items (do not delete options)

  • [ x I have ran Ruff against my changes (poetry: poetry run ruff check ., use --fix to automatically fix what it can)
  • I have added or updated the tests/e2e_commands.txt file if necessary (new modules or features are required to be added to the e2e tests)
  • If reliant on changes of third party dependencies, such as Impacket, dploot, lsassy, etc, I have linked the relevant PRs in those projects
  • I have linked relevant sources that describes the added technique (blog posts, documentation, etc)
  • I have performed a self-review of my own code (not an AI review)
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (PR here: https://github.com/Pennyw0rth/NetExec-Wiki)

@NeffIsBack NeffIsBack added the enhancement New feature or request label Jun 1, 2026
@NeffIsBack

Copy link
Copy Markdown
Member

Sweeet, what's the hash type? Can you also add a wiki page that documents how you can crack it (preferebly even with the hashcat command so you can just copy&paste)?

@Dfte

Dfte commented Jun 1, 2026

Copy link
Copy Markdown
Contributor Author

There are three type of hashes which are 0000 0100 0200 (the 4 first characters of the hash dump).
And yeah I will update the wiki once I'm over with MSSQL PR's (there are a few incoming).

Comment thread nxc/protocols/mssql.py Outdated

@requires_admin
def db_hash(self):
self.logger.info("Dumping local database users' hashes")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use display instead of info, just like in list_databases()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread nxc/protocols/mssql.py
@requires_admin
def db_hash(self):
self.logger.info("Dumping local database users' hashes")
query = """

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sql_query should be inside a try/except block, just as list_databases() is (here)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary but i'll add the lastError block.

Comment thread nxc/protocols/mssql.py Outdated
AND sp.name NOT LIKE '##%'
ORDER BY login_type, sp.name;
"""
rows = self.conn.sql_query(query) or []

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check self.conn.lastError after the query

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread nxc/protocols/mssql.py Outdated
"""
rows = self.conn.sql_query(query) or []
if not rows:
self.logger.display("No databases returned")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be No logins returned instead of No databases returned?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imo this should also be a .fail() message (applies to all recent PR) to immediately make visible that we failed to retrieve any hashes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't mean we failed retrieving them, it means that there are no hashes to diaply. If there is any error, it should be notified in self.conn.lastError

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I know. I mean not in the sense of an error, but imo we should use .fail() cause it correctly displays the negative event that we did not retrieve any hashes. E.g.:

context.log.fail("No ADCS infrastructure found.")

context.log.fail("No domain controller with operating system Windows Server 2025 found, attack not possible. Enumerate dMSA objects anyway.")

etc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah got it

Comment thread nxc/protocols/mssql.py Outdated
CASE sp.type_desc
WHEN 'SQL_LOGIN' THEN 'SQL User'
ELSE sp.type_desc
END as login_type,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

login_type is selected but never displayed, imo it should either be removed if it's not needed or displayed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@Dfte

Dfte commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Latest commit adds the hash algorithm for easier post exploit:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants