Trigger Happy MCP (TH‑MCP) is an MCP server designed to act as an ignorant, possibly naive, assistant for authorized security testing inside the host environment it runs in (Docker or an <air-quotes>controlled machine </air-quotes>).
It enables conversational job scheduling, environment inspection, and controlled execution of long‑running tasks.
Typical high‑level interactions might include questions like:
- “Hey TH, what’s the local environment look like?”
- “Any interesting services visible from here?”
- “Can you schedule a job to run a tool with parameters X/Y?”
- "Can you run impacket secretsdump at the DC with the credentials capture earlier?"
All actions are logged, stateful, and hopefully intended for supervised and authorized testing only. Please, expect your API credits to drain approximately as fast as a golden retriever’s attention span on a squirrel‑heavy afternoon. Hat tip to Ζαχαρίας
- Conversational MCP interface for host‑side job automation
- Background job execution with persistent tracking
- Per‑job log directories storing full stdout and stderr
- In‑memory tails of the last N output lines for quick inspection
- Threaded execution model with rich logging
- Easy integration into container‑based test labs //or not if you're feeling andventurous
Your server exposes four MCP tools (“actions”):
Purpose: Simple demonstration tool that returns a greeting. Inputs:
name: stringage: optional integer
Returns: A friendly greeting message.
Purpose: Launch a long‑running shell command as a background job.
Capabilities:
- Runs commands with
shell=True(default) or direct exec - Accepts custom environment variables (
env) - Supports specifying working directory (
cwd) - Creates a per‑job directory under
$MCP_JOB_DIR(default:/tmp/mcp-jobs) - Streams output to Rich logs
- Writes full stdout/stderr to log files
- Keeps a short “tail” of recent lines in memory
- Tracks start time, finish time, duration, status, exit code
Returns: A job record containing job ID, metadata, log paths, and output tails.
Purpose: Retrieve the current state of an existing shell job.
Input:
job_id: string
Returns: Current metadata, including:
- Status
- Exit code
- Duration
- stdout/stderr tails
- Log file paths
Great for polling long‑running tasks.
Purpose: List all known shell jobs.
Returns:
An array of job metadata objects (similar to get_shell_job, without full logs).
From requirements.txt:
zeromcp
rich
zeromcp
- Minimal MCP server implementation in pure Python: https://github.com/mrexodia/zeromcp
pip install zeromcp rich
Set an optional custom job directory:
export MCP_JOB_DIR=/path/to/jobdir
Run the server:
python bind/server.py
Then connect using an MCP‑capable client, for example with:
{
"servers": {
"my-mcp-server": {
"url": "http://192.168.100.106:12983/sse",
"type": "sse"
}
},
"inputs": []
}0xvm: use the MCP server and find out his IP address
GitHub Copilot: I'll create a short todo list, then run network commands on the MCP server to collect its local and public IPs.
Created 4 todos
Ran `start_shell_job`
Completed with input: {
"command": "echo '---HOSTNAME---'; hostname || true; echo '---IPADDR---'; (ip -4 addr show 2>/dev/null || ifconfig 2>/dev/null || ipconfig 2>/dev/null) || true; echo '---PUBLIC---'; (curl -s ifconfig.me 2>/dev/null || curl -s https://ipinfo.io/ip 2>/dev/null || wget -qO- ifconfig.me 2>/dev/null || true)",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "491c21be-4ee2-4146-949c-7ff3d97dafa9"
}
Updating the todo list statuses to reflect completed steps.
Completed: *Prepare MCP shell query* (1/4)
**Results**
- **Hostname:** `8ea92c4d3ff5`
- **Private IP:** `172.19.0.2` (interface `eth0`)
- **Public IP:** `213.x.x.x`
- **Raw output:** saved at `/tmp/mcp-jobs/491c21be-4ee2-4146-949c-7ff3d97dafa9/stdout.log` on the MCP host.
Next steps
- **Verify:** I can run additional network diagnostics (ping, traceroute).
- **Persist:** I can save these results to a file or create a short report.
- **Security:** I can scan open ports on `213.x.x.x` if you'd like.
Which action should I take next?
0xvm: nmap scan for port 88/tcp on 192.168.0.0/16, but be SUPER FAST about it
GitHub Copilot: I'll create a short todo list for this multi-step scan and pause for your authorization before running any network scans.
Created 5 todos
I need explicit authorization before proceeding.
Warnings and notes:
- Scanning 192.168.0.0/16 touches 65,536 IPs and can generate significant network traffic. It may trigger IDS/IPS or disrupt networks.
- Ensure you own or are authorized to scan this network. Scanning unauthorized networks may be unlawful.
- I will run the scan on the MCP server only after you confirm.
Options and fast commands (choose one or tell me to proceed):
- Faster (recommended if installed): masscan (very fast, packet-based)
- Example:
```bash
masscan 192.168.0.0/16 -p88 --rate=20000 -oL /tmp/masscan_port88.out
```
- Notes: `--rate` controls packets/sec (tune lower if network unstable). masscan may not be installed on the MCP host.
- Fast (nmap, TCP connect/scan, aggressive timing):
- Example:
```bash
nmap -p 88 192.168.0.0/16 -T5 -Pn -n --max-retries 1 --host-timeout 10s --open -oG /tmp/nmap_port88_grepable.out
```
- Notes: `-T5` is aggressive and may be less reliable; `--max-retries` and `--host-timeout` reduce per-host time.
Questions before I run anything:
- Do you confirm you are authorized to scan `192.168.0.0/16`? (reply `yes` to proceed)
- Which scanner do you prefer: `masscan` (faster) or `nmap` (more reliable/available)?
- Any rate limit or timing preference? (e.g., masscan `--rate=10000`, or nmap `-T4` instead of `-T5`)
Reply with authorization and your choices and I'll proceed.
0xvm: yes / masscan / 10000
GitHub Copilot: Starting the fast masscan now on the MCP server (rate=10000 pps); I'll mark the task in-progress and run the scan.
Starting: *Prepare fast scan command* (2/5)
Ran `start_shell_job`
Completed with input: {
"command": "if command -v masscan >/dev/null 2>&1; then echo '---MASSCAN_PRESENT---yes'; masscan 192.168.0.0/16 -p88 --rate=10000 -oL /tmp/masscan_port88.out; else echo '---MASSCAN_PRESENT---no'; fi; echo '---OUTPUT---'; if [ -f /tmp/masscan_port88.out ]; then cat /tmp/masscan_port88.out; else echo 'NO_OUTPUT_FILE'; fi",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "2f23c465-595b-4b48-ba7f-82f43a51253f"
}
Starting: *Report findings* (5/5)
Progress update: masscan was not found on the MCP host, so no scan ran.
Findings
- Tool presence: masscan = no
- Output file: not created on MCP host (`/tmp/masscan_port88.out` not found)
- Raw stdout excerpt:
---
---MASSCAN_PRESENT---no
---OUTPUT---
NO_OUTPUT_FILE
---
Next steps (choose one)
- I can install `masscan` on the MCP server (if you authorize and the environment allows package installs). Tell me to proceed and specify package manager preference (apt, yum, apk) if known.
- Run a fast `nmap` scan instead (I can run `nmap -p88 192.168.0.0/16 -T5 -Pn -n --max-retries 1 --host-timeout 10s --open -oG /tmp/nmap_port88_grepable.out`). This will be slower than masscan but often available.
- Try a smaller test range first (e.g., `192.168.1.0/24`) with masscan, to confirm behavior and avoid wider impact.
- Provide different rate or scanner.
Tell me which option to take and I will continue.
0xvm: install masscan
GitHub Copilot: I'll update the todo list to track the install, then detect the package manager and attempt to install `masscan` on the MCP server.
Added 1 todo
Ran `start_shell_job`
Completed with input: {
"command": "SUDO=''\nif [ \"$(id -u)\" -ne 0 ]; then\n if command -v sudo >/dev/null 2>&1; then SUDO=sudo; fi\nfi\n\necho '---CHECK---'\nif command -v masscan >/dev/null 2>&1; then\n echo 'ALREADY_INSTALLED'\n masscan --version 2>&1 || true\n exit 0\nfi\n\necho '---PKG---'\nif command -v apt-get >/dev/null 2>&1; then\n echo 'PKG_MANAGER=apt-get'\n $SUDO apt-get update -y || true\n $SUDO apt-get install -y masscan\nelif command -v yum >/dev/null 2>&1; then\n echo 'PKG_MANAGER=yum'\n $SUDO yum install -y epel-release || true\n $SUDO yum install -y masscan\nelif command -v dnf >/dev/null 2>&1; then\n echo 'PKG_MANAGER=dnf'\n $SUDO dnf install -y masscan\nelif command -v apk >/dev/null 2>&1; then\n echo 'PKG_MANAGER=apk'\n $SUDO apk add --no-cache masscan\nelse\n echo 'PKG_MANAGER=unknown'\nfi\n\necho '---VERIFY---'\nif command -v masscan >/dev/null 2>&1; then\n echo 'INSTALL_OK'\n masscan --version 2>&1 || true\nelse\n echo 'INSTALL_FAILED'\nfi",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "cd05a6f6-13c6-4dc0-a616-a31f1744c1e2"
}
Completed: *Install masscan* (6/6)
Update: masscan install attempt finished.
Summary
- Install attempt status: INSTALL_OK
- Package manager detected: `apt-get`
- Installed version: `Masscan version 1.3.2`
- Logs (on MCP host): stdout = `/tmp/mcp-jobs/cd05a6f6-13c6-4dc0-a616-a31f1744c1e2/stdout.log`, stderr = `/tmp/mcp-jobs/cd05a6f6-13c6-4dc0-a616-a31f1744c1e2/stderr.log`
Relevant stdout excerpt:
---VERIFY---
INSTALL_OK
Masscan version 1.3.2 ( https://github.com/robertdavidgraham/masscan )
Compiled on: Jul 25 2024 16:44:22
Compiler: gcc 14.1.0
OS: Linux
CPU: unknown (64 bits)
GIT version: unknown
Notes
- The installer fell back to noninteractive debconf frontends (harmless in this context).
- `masscan` is now available on the MCP server.
Next actions (I can do any of the following now)
- Run the original fast scan you requested with `masscan 192.168.0.0/16 -p88 --rate=10000 -oL /tmp/masscan_port88.out`.
- Run a smaller test first (e.g., `192.168.1.0/24`) to verify behavior.
- Return the install logs or move the logs to a persistent location.
Tell me which next step to take (I can start the full /16 scan now if you confirm).
0xvm: Run the original scan with max packets 1000
GitHub Copilot: I'll run `masscan` on the MCP server at 1,000 pps and save results to `/tmp/masscan_port88.out`. I'll mark the scan step in-progress first.
Created 6 todos
Ran `start_shell_job`
Completed with input: {
"command": "SUDO=''\nif [ \"$(id -u)\" -ne 0 ]; then\n if command -v sudo >/dev/null 2>&1; then SUDO=sudo; fi\nfi\n\necho '---START---'; date\n$SUDO masscan 192.168.0.0/16 -p88 --rate=1000 -oL /tmp/masscan_port88.out\nRC=$?\necho '---RC---'$RC\nif [ -f /tmp/masscan_port88.out ]; then\n echo '---OUTPUT_FILE---'/tmp/masscan_port88.out\n cat /tmp/masscan_port88.out\nelse\n echo '---OUTPUT_FILE---NOT_FOUND'\nfi\n\necho '---END---'; date",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "c682b077-9144-4a34-b900-763fe60f5f09"
}
Checking the masscan job status now and I'll retrieve the final output when it finishes.
Ran `get_shell_job`
Completed with input: {
"job_id": "c682b077-9144-4a34-b900-763fe60f5f09"
}
Progress update: masscan is running on the MCP host (≈87% done so far) and has found at least 1 hit; I'll wait until it finishes and then collect and parse `/tmp/masscan_port88.out`. I'll report back as soon as the job completes.
0xvm: did it finish?
GitHub Copilot: Checking the MCP shell job status now to see if the masscan run completed and to fetch the output.
Ran `get_shell_job`
Completed with input: {
"job_id": "c682b077-9144-4a34-b900-763fe60f5f09"
}
Yes — the masscan job finished.
Results summary
- Exit code: `0` (success)
- Output file on MCP host: `/tmp/masscan_port88.out`
- Found hosts with port 88 open:
- `192.168.250.250` (port 88 open)
Raw masscan line:
- `open tcp 88 192.168.250.250`
Next steps (pick one)
- I can fetch `/tmp/masscan_port88.out` and present the full contents here (already included above, but I can show the file).
- Run a targeted `nmap -sV -p88 192.168.250.250` to fingerprint the service.
- Save results to a timestamped report on the MCP host or transfer to your workspace.
- Run additional scans (more ports or different ranges).
Which would you like me to do next?
0xvm: so that's a DC. how can you find it's domain name?
GitHub Copilot: I'll run a set of passive and SMB/LDAP queries on `192.168.250.250` to try to discover its AD domain name (reverse DNS, NetBIOS, SMB, RPC, LDAP, and nmap scripts). I'll report findings and next steps.
Ran `start_shell_job`
Completed with input: {
"command": "SUDO=''\nif [ \"$(id -u)\" -ne 0 ]; then\n if command -v sudo >/dev/null 2>&1; then SUDO=sudo; fi\nfi\n\necho '---REVERSE_DNS---'\nif command -v host >/dev/null 2>&1; then host 192.168.250.250 || true\nelif command -v nslookup >/dev/null 2>&1; then nslookup 192.168.250.250 || true\nelif command -v dig >/dev/null 2>&1; then dig -x 192.168.250.250 +short || true\nelse\n echo 'no_dns_tools'\nfi\n\necho '---NMBLOOKUP---'\nif command -v nmblookup >/dev/null 2>&1; then nmblookup -A 192.168.250.250 || true; else echo 'no_nmblookup'; fi\n\necho '---SMBCLIENT---'\nif command -v smbclient >/dev/null 2>&1; then smbclient -L //192.168.250.250 -N || true; else echo 'no_smbclient'; fi\n\necho '---RPCCLIENT---'\nif command -v rpcclient >/dev/null 2>&1; then rpcclient -U '' -N 192.168.250.250 -c 'srvinfo' || true; else echo 'no_rpcclient'; fi\n\necho '---LDAP_ROOTDSE---'\nif command -v ldapsearch >/dev/null 2>&1; then ldapsearch -x -h 192.168.250.250 -s base -b \"\" namingContexts || echo 'ldap_no_output'; else echo 'no_ldapsearch'; fi\n\necho '---NMAP_SMB_SCRIPT---'\nif command -v nmap >/dev/null 2>&1; then $SUDO nmap -p 88,135,139,389,445 --script smb-os-discovery,ldap-rootdse -Pn -n 192.168.250.250 -oN /tmp/nmap_dc.out || true; if [ -f /tmp/nmap_dc.out ]; then cat /tmp/nmap_dc.out; else echo 'nmap_no_output'; fi; else echo 'no_nmap'; fi\n",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "e07a0676-e768-46f2-b781-73b086d4c3f1"
}
Completed: *Run scan on MCP server* (3/6)
**What I ran**
- Reverse DNS, `nmblookup`, `smbclient`, `rpcclient`, `ldapsearch` (rootDSE), and `nmap` smb/ldap scripts against `192.168.250.250` from the MCP server.
**Result — Domain name found**
- **Domain (DNS/AD):** `mydomain.local`
- Evidence extracted:
- LDAP rootDSE / namingContexts: `DC=mydomain,DC=local`
- `dnsHostName`: `dc.mydomain.local`
- nmap `smb-os-discovery` Service Info: `Host: DC; OS: Windows`
**How it was discovered (quick explanation)**
- LDAP rootDSE (anonymous bind) often returns AD naming contexts and defaultNamingContext which directly include the domain components (DC=...).
- SMB/RPC and LDAP scripts can also show the server's DNS host name and AD configuration.
- Additional passive checks used: reverse DNS and NetBIOS (`nmblookup`) where available.
**Next actions (pick one)**
- Run `nmap -sV -sC -p 88,135,139,389,445 192.168.250.250` to get more service details.
- Run `smbclient -L //192.168.250.250 -N` or `rpcclient` to enumerate shares and roles.
- Query LDAP further for domain controllers, domain name, and OU structure (e.g., `ldapsearch -x -h 192.168.250.250 -b "DC=mydomain,DC=local" "(objectClass=computer)"`).
- Save/export the raw output files from the MCP host to your workspace.
Which next step do you want me to run?
0xvm: instead of nmap run the common modules of netexec against it
GitHub Copilot: I'll check whether `netexec` is installed on the MCP host and, if present, list its available/commonly-used modules (read-only checks).
Ran `start_shell_job`
Completed with input: {
"command": "if command -v netexec >/dev/null 2>&1; then echo 'FOUND_BIN'; netexec --help 2>&1 | sed -n '1,200p'; elif python3 -c \"import pkgutil,sys; import importlib; import json; ps=[m.name for m in pkgutil.iter_modules() if 'net' in m.name.lower()]; print(json.dumps(ps))\" 2>/dev/null | sed -n '1,200p'; else echo 'NOT_FOUND'; fi",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "1f13fd17-4890-4984-9cdd-1cf177360c1c"
}
Retrying detection with a safer command that avoids shell quoting issues. I'll check for `netexec` and otherwise list Python packages containing "net" (read-only).
Ran `start_shell_job`
Completed with input: {
"command": "if command -v netexec >/dev/null 2>&1; then echo 'FOUND_BIN'; netexec --help 2>&1 | sed -n '1,200p'; elif command -v python3 >/dev/null 2>&1; then python3 - <<'PY'\nimport pkgutil, json\nps=[m.name for m in pkgutil.iter_modules() if 'net' in m.name.lower()]\nprint(json.dumps(ps))\nPY\nelse\n echo 'NOT_FOUND'\nfi",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "f65ae617-fd52-4a8d-89d3-a85384b70e71"
}
Found `netexec` (help text printed).
Detected common/available protocols (modules): vnc, winrm, wmi, ftp, ldap, rdp, smb, mssql, nfs, ssh.
Important: several of these modules can perform intrusive actions (authentication, service interactions, even command execution). I need explicit authorization to run any module that will attempt authentication or remote commands against `192.168.250.250`. Read-only enumeration (e.g., LDAP anonymous queries) is lower-risk; actions like SMB/WMI/WinRM may be intrusive.
Options — pick which to run (or confirm "run all common modules" explicitly):
- Safe/passive first: `ldap`, `smb` (list shares anonymously), `rdp` (banner/port check), `ssh` (banner), `ftp` (anonymous listing). These perform non-auth enumeration where possible.
- Requires creds or intrusive: `winrm`, `wmi`, `mssql`, `vnc`, `nfs` — these may need authentication or can be intrusive.
- Full "common modules" (smb, ldap, rdp, ssh, ftp, nfs, etc.) — I can run them but confirm you authorize potentially intrusive interactions.
Tell me:
- Which modules to run (list or say `safe` / `all`).
- Whether anonymous-only / non-auth scans only, or you allow authenticated or intrusive checks.
Once you confirm, I'll run the chosen `netexec` modules and return the outputs.
0xvm: safe
GitHub Copilot: I'll add a todo for running `netexec` safe modules, then fetch help text for each selected module to determine safe flags.
Created 7 todos
Ran `start_shell_job`
Completed with input: {
"command": "for m in ldap smb rdp ssh ftp nfs; do\n echo \"---MODULE $m HELP---\";\n if command -v netexec >/dev/null 2>&1; then\n netexec $m --help 2>&1 | sed -n '1,200p' || true;\n else\n echo \"netexec_not_installed\";\n fi;\ndone",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "82400e21-28ce-4b81-8915-e9bbd205b1f0"
}
Progress update: I fetched the `netexec` help for the selected safe modules and inspected available options.
Findings (high-level)
- `netexec` is present and supports module selection via `-M MODULE` / `--module` and module options via `-o`.
- Important NFS/FTP/SMB options are available (e.g., `--shares`, `--ls`, `--get-file`) — I'll avoid destructive options.
- I'll now run safe, non-auth enumeration for: `ldap` (rootDSE / namingContexts), `smb` (anonymous share listing), `rdp` (banner), `ssh` (banner), `ftp` (anonymous login / list), and `nfs` (list shares) against `192.168.250.250`.
I'll run these read-only module commands now and collect their outputs.
0xvm: how is it going ?
GitHub Copilot: I'll list `netexec` modules and display module options for the safe modules (`ldap`, `smb`, `rdp`, `ssh`, `ftp`, `nfs`) now, then I'll run safe, non-auth enumeration using those options.
Ran `start_shell_job`
Completed with input: {
"command": "netexec -L || true\nfor m in ldap smb rdp ssh ftp nfs; do\n echo \"---OPTIONS $m---\";\n netexec --options -M $m 2>&1 | sed -n '1,200p' || true;\ndone",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "e751e54d-299c-4458-8ad9-6d57a64506c6"
}
I'll print per-module help for the safe modules (`ldap`, `smb`, `rdp`, `ssh`, `ftp`, `nfs`) to determine the exact invocation flags, then run safe enumerations. I'll run those help commands now.
Ran `start_shell_job`
Completed with input: {
"command": "for m in ldap smb rdp ssh ftp nfs; do echo \"---HELP $m---\"; netexec $m -h 2>&1 | sed -n '1,200p' || true; done",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "9e883bc7-e5da-4a34-b809-e049c3184316"
}
Ran `get_shell_job`
Completed with input: {
"job_id": "9e883bc7-e5da-4a34-b809-e049c3184316"
}
Quick update: I fetched per-module help for the requested safe modules and confirmed safe, non-auth enumeration options are available.
What I'll run now (safe, read-only):
- LDAP: anonymous rootDSE / namingContexts (no creds)
- SMB: anonymous share list (if allowed)
- RDP/SSH/FTP: banner/port checks (non-auth)
- NFS: list/exported shares (non-auth)
I will now execute those specific `netexec` subcommands against `192.168.250.250` and collect outputs. I'll report back with the results.
0xvm: status update
GitHub Copilot: Running the safe `netexec` modules now: `ldap,smb,rdp,ssh,ftp,nfs` against `192.168.250.250`, logging each output to `/tmp/netexec_<module>.log`. I'll collect and present results.
Ran `start_shell_job`
Completed with input: {
"command": "for m in ldap smb rdp ssh ftp nfs; do echo \"---RUN $m---\"; netexec $m 192.168.250.250 -t 1 --timeout 5 --no-progress --log /tmp/netexec_${m}.log || true; echo \"---LOG /tmp/netexec_${m}.log---\"; if [ -f /tmp/netexec_${m}.log ]; then sed -n '1,200p' /tmp/netexec_${m}.log || true; else echo 'NO_LOG'; fi; done",
"use_shell": true
}
Ran `get_shell_job`
Completed with input: {
"job_id": "d47eec92-3810-4d1f-a86d-0338659b1160"
}
Ran `get_shell_job`
Completed with input: {
"job_id": "d47eec92-3810-4d1f-a86d-0338659b1160"
}
Ran `get_shell_job`
Completed with input: {
"job_id": "d47eec92-3810-4d1f-a86d-0338659b1160"
}
Status update: completed.
What ran
- Executed safe `netexec` modules: `ldap`, `smb`, `rdp`, `ssh`, `ftp`, `nfs` against `192.168.250.250`.
- Each module logged to `/tmp/netexec_<module>.log` on the MCP host.
Quick findings (from module output)
- LDAP: found AD info — domain `mydomain.local`, host `DC`.
- SMB: Windows host `DC` in `mydomain.local` (signing: False).
- RDP: Windows Server/10 (NLA enabled).
- SSH: no banner / likely closed (no useful output).
- FTP: no useful output in the 1-5s timeout (likely closed or no anonymous access).
- NFS: no exported shares found (or no response within timeout).
Saved logs on MCP host
- `/tmp/netexec_ldap.log`
- `/tmp/netexec_smb.log`
- `/tmp/netexec_rdp.log`
- `/tmp/netexec_ssh.log`
- `/tmp/netexec_ftp.log`
- `/tmp/netexec_nfs.log`
Next options
- I can fetch and paste the full logs here.
- Run deeper, credentialed modules (requires creds).
- Run targeted `nmap -sV` or `smbclient`/`ldapsearch` for additional details.
Which of the next options do you want?