<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: building-python-security-tools
description: >-
  Build custom Python security tools for network scanning, credential testing,
  packet crafting, and vulnerability detection using Scapy, Impacket, Paramiko,
  and the standard library. Covers argparse-driven CLI patterns, async I/O for
  concurrent scanning, and structured JSON output for pipeline integration.
domain: cybersecurity
subdomain: automation-scripting
tags:
  - python
  - scapy
  - impacket
  - paramiko
  - security-tools
  - network-scanning
  - credential-testing
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1059.006"]
---

# Building Python Security Tools

## Overview

Python is the dominant language for rapid security tool development. This skill
covers building production-quality CLI tools with structured output, proper error
handling, and async patterns for concurrent operations. Tools built here integrate
into larger automation pipelines via JSON output and standard exit codes.

Mode: `[MODE: RED]` — Offensive tooling with detection notes.

## Prerequisites

| Requirement | Details |
|---|---|
| Python 3.10+ with type hints | Required |
| `scapy` for packet crafting (`pip install scapy`) | Required |
| `impacket` for Windows protocol interaction (`pip install impacket`) | Required |
| `paramiko` for SSH automation (`pip install paramiko`) | Required |
| Root/sudo for raw socket operations (Scapy) | Required |

## Key Concepts

### TCP Port Scanner with Async I/O

```python
import asyncio
import socket

async def scan_port(host: str, port: int, timeout: float = 2.0) -> dict:
    """Probe a single TCP port and return result."""
    try:
        _, writer = await asyncio.wait_for(
            asyncio.open_connection(host, port), timeout=timeout
        )
        writer.close()
        await writer.wait_closed()
        return {"port": port, "state": "open", "service": socket.getservbyport(port, "tcp") if port < 1024 else "unknown"}
    except (asyncio.TimeoutError, ConnectionRefusedError, OSError):
        return {"port": port, "state": "closed"}

async def scan_range(host: str, ports: list[int]) -> list[dict]:
    """Scan multiple ports concurrently."""
    tasks = [scan_port(host, p) for p in ports]
    results = await asyncio.gather(*tasks)
    return [r for r in results if r["state"] == "open"]
```

### SSH Credential Tester with Paramiko

```python
import paramiko

def test_ssh_credential(host: str, port: int, username: str, password: str) -> dict:
    """Test a single SSH credential pair."""
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client.connect(host, port=port, username=username, password=password, timeout=5)
        return {"host": host, "username": username, "status": "success"}
    except paramiko.AuthenticationException:
        return {"host": host, "username": username, "status": "auth_failed"}
    except paramiko.SSHException as e:
        return {"host": host, "username": username, "status": "error", "detail": str(e)}
    finally:
        client.close()
```

### Scapy ARP Scanner

```python
from scapy.all import ARP, Ether, srp

def arp_scan(network: str, timeout: int = 3) -> list[dict]:
    """Discover hosts on a local network via ARP."""
    pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=network)
    answered, _ = srp(pkt, timeout=timeout, verbose=False)
    return [
        {"ip": rcv.psrc, "mac": rcv.hwsrc}
        for _, rcv in answered
    ]
```

## Workflow

### Step 1: Scan Target Ports

```bash
node scripts/agent.js --action port-scan --target 192.168.1.1 --ports 22,80,443,8080
```

### Step 2: ARP Discovery on Subnet

```bash
node scripts/agent.js --action arp-scan --target 192.168.1.0/24
```

### Step 3: SSH Credential Test

```bash
node scripts/agent.js --action ssh-test --target 192.168.1.10 --username admin --password admin
```

## Verification

- [ ] Port scanner returns JSON with open ports and service names
- [ ] ARP scanner discovers all live hosts on subnet
- [ ] SSH tester distinguishes auth failure from connection error
- [ ] All tools handle timeouts and unreachable hosts gracefully
- [ ] Exit code 0 on success, 1 on findings, 2 on error

## References

- [Scapy Documentation](https://scapy.readthedocs.io/)
- [Impacket GitHub](https://github.com/fortra/impacket)
- [Paramiko Documentation](https://www.paramiko.org/)
- [MITRE ATT&CK T1046 — Network Service Scanning](https://attack.mitre.org/techniques/T1046/)
