Skip to content

Commit 7091022

Browse files
committed
Move bloodhound package info function to the helpers
1 parent 09cb12d commit 7091022

2 files changed

Lines changed: 60 additions & 59 deletions

File tree

nxc/helpers/misc.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def called_from_cmd_args():
4040
# Stolen from https://github.com/pydanny/whichcraft/
4141
def which(cmd, mode=os.F_OK | os.X_OK, path=None):
4242
"""Find the path which conforms to the given mode on the PATH for a command.
43-
43+
4444
Given a command, mode, and a PATH string, return the path which conforms to the given mode on the PATH, or None if there is no such file.
4545
`mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result of os.environ.get("PATH"), or can be overridden with a custom search path.
4646
Note: This function was backported from the Python 3 source code.
@@ -77,3 +77,61 @@ def _access_check(fn, mode):
7777
name = os.path.join(p, thefile)
7878
if _access_check(name, mode):
7979
return name
80+
81+
82+
def get_bloodhound_info():
83+
"""
84+
Detect which BloodHound package is installed (regular or CE) and its version.
85+
86+
Returns
87+
-------
88+
tuple: (package_name, version, is_ce)
89+
- package_name: Name of the installed package ('bloodhound', 'bloodhound-ce', or None)
90+
- version: Version string of the installed package (or None if not installed)
91+
- is_ce: Boolean indicating if it's the Community Edition
92+
"""
93+
import importlib.metadata
94+
import importlib.util
95+
96+
# First check if any BloodHound package is available to import
97+
if importlib.util.find_spec("bloodhound") is None:
98+
return None, None, False
99+
100+
# Try to get version info from both possible packages
101+
version = None
102+
package_name = None
103+
is_ce = False
104+
105+
# Check for bloodhound-ce first
106+
try:
107+
version = importlib.metadata.version("bloodhound-ce")
108+
package_name = "bloodhound-ce"
109+
is_ce = True
110+
except importlib.metadata.PackageNotFoundError:
111+
# Check for regular bloodhound
112+
try:
113+
version = importlib.metadata.version("bloodhound")
114+
package_name = "bloodhound"
115+
116+
# Even when installed as 'bloodhound', check if it's actually the CE version
117+
if version and ("ce" in version.lower() or "community" in version.lower()):
118+
is_ce = True
119+
except importlib.metadata.PackageNotFoundError:
120+
# No bloodhound package found via metadata
121+
pass
122+
123+
# In case we can import it but metadata is not working, check the module itself
124+
if not version:
125+
try:
126+
import bloodhound
127+
version = getattr(bloodhound, "__version__", "unknown")
128+
package_name = "bloodhound"
129+
130+
# Check if it's CE based on version string
131+
if "ce" in version.lower() or "community" in version.lower():
132+
is_ce = True
133+
package_name = "bloodhound-ce"
134+
except ImportError:
135+
pass
136+
137+
return package_name, version, is_ce

nxc/protocols/ldap.py

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from nxc.protocols.ldap.kerberos import KerberosAttacks
4444
from nxc.parsers.ldap_results import parse_result_attributes
4545
from nxc.helpers.ntlm_parser import parse_challenge
46+
from nxc.helpers.misc import get_bloodhound_info
4647

4748
ldap_error_status = {
4849
"1": "STATUS_NOT_SUPPORTED",
@@ -1219,64 +1220,6 @@ def gmsa_decrypt_lsa(self):
12191220
self.logger.fail("No string provided :'(")
12201221

12211222
def bloodhound(self):
1222-
1223-
def get_bloodhound_info():
1224-
"""
1225-
Detect which BloodHound package is installed (regular or CE) and its version.
1226-
1227-
Returns
1228-
-------
1229-
tuple: (package_name, version, is_ce)
1230-
- package_name: Name of the installed package ('bloodhound', 'bloodhound-ce', or None)
1231-
- version: Version string of the installed package (or None if not installed)
1232-
- is_ce: Boolean indicating if it's the Community Edition
1233-
"""
1234-
import importlib.metadata
1235-
import importlib.util
1236-
1237-
# First check if any BloodHound package is available to import
1238-
if importlib.util.find_spec("bloodhound") is None:
1239-
return None, None, False
1240-
1241-
# Try to get version info from both possible packages
1242-
version = None
1243-
package_name = None
1244-
is_ce = False
1245-
1246-
# Check for bloodhound-ce first
1247-
try:
1248-
version = importlib.metadata.version("bloodhound-ce")
1249-
package_name = "bloodhound-ce"
1250-
is_ce = True
1251-
except importlib.metadata.PackageNotFoundError:
1252-
# Check for regular bloodhound
1253-
try:
1254-
version = importlib.metadata.version("bloodhound")
1255-
package_name = "bloodhound"
1256-
1257-
# Even when installed as 'bloodhound', check if it's actually the CE version
1258-
if version and ("ce" in version.lower() or "community" in version.lower()):
1259-
is_ce = True
1260-
except importlib.metadata.PackageNotFoundError:
1261-
# No bloodhound package found via metadata
1262-
pass
1263-
1264-
# In case we can import it but metadata is not working, check the module itself
1265-
if not version:
1266-
try:
1267-
import bloodhound
1268-
version = getattr(bloodhound, "__version__", "unknown")
1269-
package_name = "bloodhound"
1270-
1271-
# Check if it's CE based on version string
1272-
if "ce" in version.lower() or "community" in version.lower():
1273-
is_ce = True
1274-
package_name = "bloodhound-ce"
1275-
except ImportError:
1276-
pass
1277-
1278-
return package_name, version, is_ce
1279-
12801223
# Check which version is desired
12811224
use_bhce = self.config.getboolean("BloodHound-CE", "bhce_enabled", fallback=False)
12821225
package_name, version, is_ce = get_bloodhound_info()

0 commit comments

Comments
 (0)