Repository navigation
Fix tool errors from agent session + combined relay attack tool - #87
Conversation
The runtime's sys.executable didn't have impacket importable because it was installed under a different Python version. Declaring it as a capability dependency ensures the runtime venv has it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… combined relay+coerce tool Fixes three issues observed in agent session c0dd9138: 1. nmap_service_scan: strip wrapping quotes from ports parameter — agent sent '"80,1433"' which nmap rejected as illegal port spec. 2. certipy_find: add structured auth params (target, username, domain, password, nt_hash) instead of raw args passthrough. Prevents agent from inventing nonexistent flags like -domain. Also fix base certipy() to handle username="user@domain" without double-appending. 3. impacket_ntlmrelay_attack: new combined tool that starts ntlmrelayx as a background subprocess, waits for listeners to bind, fires coercion (petitpotam/dfscoerce/shadowcoerce), monitors for success indicators, and returns combined output. Solves the sequencing problem where ntlmrelayx must be running before coercion fires. Includes: _build_ntlmrelayx_args (extracted from existing method), _build_coercion_command, _wait_for_relay_ready, _wait_for_relay_result, _kill_relay helpers. 24 unit tests covering all changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses a set of tool failures observed in a prior agent session by hardening several network-ops tools and adding a combined NTLM relay + coercion workflow so agents can run relay and coercion in the correct sequence within a single tool call.
Changes:
- Hardened
nmap_service_scanport handling and improved Certipy authentication argument construction (including a breakingcertipy_findsignature update). - Refactored ntlmrelayx argument construction and added a new combined
impacket_ntlmrelay_attacktool with relay lifecycle orchestration helpers. - Added unit tests covering the above fixes and updated skill guidance + capability dependency/version metadata.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| capabilities/network-ops/tools/nmap.py | Strips wrapping quotes from ports before passing to nmap -p. |
| capabilities/network-ops/tools/impacket.py | Adds relay orchestration helpers, refactors ntlmrelayx arg building, and introduces combined impacket_ntlmrelay_attack. |
| capabilities/network-ops/tools/certipy.py | Updates base certipy() username/domain handling and changes certipy_find to structured auth params routed through certipy(). |
| capabilities/network-ops/tests/test_tool_fixes.py | New unit tests for the nmap/certipy/impacket fixes and relay helper behavior. |
| capabilities/network-ops/skills/ad-attack-patterns/SKILL.md | Updates guidance to prefer the new combined relay+coerce tool for NTLM relay workflows. |
| capabilities/network-ops/capability.yaml | Bumps capability version and adds an impacket>=0.12.0 dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Strip whitespace before quotes in nmap ports parameter - Use asyncio.get_running_loop() instead of deprecated get_event_loop() - Prefer hashes over password in coercion command (mutually exclusive) - Derive relay readiness/coercion/monitoring timeouts from relay_timeout so total runtime respects the documented contract - Guard test stubs to avoid clobbering real dreadnode package if present Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Don't append @Domain when username contains backslash (NTLM-style DOMAIN\user format). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… loop - nmap: compute cleaned ports before the truthy check to avoid passing empty string to -p - relay drain loop: use a 5s total deadline instead of per-line timeout to prevent indefinite reads when ntlmrelayx is noisy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ecks Add install_coercion_tools.sh to clone PetitPotam, DFSCoerce, and ShadowCoerce repos at sandbox provision time. Add checks entries so the capability warns if they're missing at runtime. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| try: | ||
| # Readiness gets at most half the total budget, capped at 30s | ||
| ready_timeout = min(relay_timeout // 2, 30) |
There was a problem hiding this comment.
Refuted. The parameter defaults to 120 and @tool_method(catch=True) wraps the call. No agent would pass zero/negative — adding validation is defending against an impossible scenario.
| coerce_result = await execute( | ||
| coerce_cmd, timeout=coerce_timeout, env=env | ||
| ) |
There was a problem hiding this comment.
Refuted. execute() does its own os.environ.copy() + env.update() internally (execute.py:78-80). Passing raw env is correct and consistent with every other tool call in the codebase.
Fixes tool errors observed in agent session
c0dd9138and adds provisioning for coercion scripts.Added
impacket_ntlmrelay_attack— combined NTLM relay + coercion tool that starts ntlmrelayx as a background subprocess, waits for listeners to bind, fires coercion (PetitPotam/DFSCoerce/ShadowCoerce), monitors for success indicators, and returns combined output in a single tool call_build_ntlmrelayx_argsextracted fromimpacket_ntlmrelayxfor reuse by the combined tool_build_coercion_command,_wait_for_relay_ready,_wait_for_relay_result,_kill_relayhelpers for relay orchestrationscripts/install_coercion_tools.sh— auto-clones PetitPotam, DFSCoerce, and ShadowCoerce repos to/opt/at sandbox provision time viadependencies.scriptschecksfornmap,petitpotam,dfscoerce,shadowcoerceincapability.yamlimpacket>=0.12.0as a Python dependency — ensures the runtime venv has impacket importable bysys.executableChanged
certipy_findnow accepts structuredtarget,username,domain,password,nt_hashparams and routes throughself.certipy()instead of rawargspassthrough — prevents the agent from inventing nonexistent flags like-domaincertipy()method handlesusername="user@domain"andDOMAIN\userformats without double-appending domainad-attack-patternsskill referencesimpacket_ntlmrelay_attackas the preferred tool for NTLM relay workflowsBreaking
certipy_findsignature changed:targetis now a required first positional arg,argsis optional. Agents calling the oldcertipy_find(args=[...])form must update tocertipy_find(target="...", args=[...]). The genericcertipy()method is unchanged as a fallback.Fixed
nmap_service_scanno longer fails when the agent passes quoted or whitespace-padded port specs — cleaned before passing to nmapGetNPUsers,secretsdump,ntlmrelayx,lookupsid) no longer fail withModuleNotFoundErrorwhen the runtime Python differs from the system Python where impacket is installedntlmrelayxno longer times out after 30s before coercion can fire — the combined tool handles the full relay lifecycle-pand-hasheswhen both are provided — hashes take priorityNotes
2.1.0dependencies.scriptsand validated viachecks