Thanks to visit codestin.com
Credit goes to github.com

Skip to content

cognis-digital/modlure

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MODLURE

MODLURE

Spin up a high-interaction Modbus/DNP3 ICS honeypot that logs attacker register reads/writes as structured JSON.

PyPI CI License: COCL 1.0 Suite

IoT / OT / Embedded — firmware, buses, and device security.

pip install modlure
modlure analyze capture.hexlog        # → classified Modbus threat events

🔎 Example output

Real, reproducible output from the tool — runs offline:

$ modlure-emit --version
modlure 1.0.0
$ modlure-emit --help
usage: modlure [-h] [--version] [--format {table,json,sarif}]
              {analyze,serve,probe,feeds} ...

MODLURE - a standard-library Modbus TCP honeypot that logs attacker register reads/writes as JSON.

positional arguments:
  {analyze,serve,probe,feeds}
    analyze             decode + classify Modbus frames from a hex capture log
    serve               run a live Modbus TCP honeypot listener
    probe               ACTIVE: read-only probe of an AUTHORIZED, in-scope
                        device (OFF by default; requires --authorized + a
                        target scope)
    feeds               manage the bundled threat-intel feeds (feodo-c2,
                        threatfox)

options:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --format {table,json,sarif}
                        output format (default: table). Accepted before OR
                        after the subcommand.

Command-line interface for MODLURE.

Subcommands
-----------
  analyze   Decode + classify Modbus TCP frames from a hex capture log
            and emit threat events (table or JSON).
  serve     Run a live Modbus TCP honeypot listener that logs every
            request as a JSON threat event.

Examples
--------
  # Analyze a captured hex log and pretty-print a table
  modlure analyze demos/01-basic/capture.hexlog

  # Emit JSON for piping into a SIEM / CI gate
  modlure analyze demos/01-basic/capture.hexlog --format json

  # Read frames from stdin
  cat capture.hexlog | modlure analyze -

  # Run a real honeypot on port 5020 (no root needed)
  modlure serve --host 0.0.0.0 --port 5020

Exit codes
----------
  0  no high-severity findings
  1  at least one high-severity event (write/control/recon) -- use as a
     

Blocks above are real modlure output — reproduce them from a clone.

Sample result format (illustrative values — run on your own data for real findings):

{
    "title": "Example Finding",
    "id": "1234567890",
    "created_by": "John Doe",
    "created_at": 1643723400,
    "modified_at": 1643723400,
    "labels": ["Vulnerability", "Exploit"],
    "observables": [
        {
            "type": "IPv4-Address",
            "value": "192.168.1.100"
        },
        {
            "type": "Domain-Name",
            "value": "example.com"
        }
    ],
    "indicators": [
        {
            "type": "Hash-MD5",
            "value": "1234567890abcdef"
        }
    ]
}

Usage — step by step

modlure is a standard-library Modbus TCP honeypot that decodes and classifies attacker register reads/writes as JSON threat events. Console script: modlure.

  1. Install:
    pipx install modlure     # or: pip install modlure
  2. Analyze a captured hex log of Modbus frames and print a classified threat table (the --format flag is global, before the subcommand):
    modlure analyze capture.hexlog
    cat capture.hexlog | modlure analyze -        # read frames from stdin
    Exit 1 = at least one high-severity event (write/control/recon), 0 = none.
  3. Filter to serious events and emit JSON for a SIEM:
    modlure --format json analyze capture.hexlog --min-severity high | jq '.[].reasons'
  4. Run a live honeypot listener (no root needed on a high port); every request is logged as a JSON event on stdout:
    modlure serve --host 0.0.0.0 --port 5020
  5. Use it as a CI / alerting gate over a capture — fail when control-plane writes appear:
    modlure analyze capture.hexlog --min-severity high || echo "high-severity Modbus activity — alerting"

Threat-intel enrichment (real C2/IOC feeds, edge / air-gap)

MODLURE can score every attacker source IP against two authoritative, keyless abuse.ch feeds and escalate any match to high severity:

Feed id Source URL
feodo-c2 abuse.ch Feodo Tracker active botnet C2 IP blocklist (Emotet/Dridex/QakBot/...) https://feodotracker.abuse.ch/downloads/ipblocklist.json
threatfox abuse.ch ThreatFox recent IOCs (ip:port IOCs are extracted, with malware family + confidence) https://threatfox.abuse.ch/export/json/recent/
modlure feeds list                          # show consumed feeds + cache freshness
modlure feeds update                         # fetch + cache feodo-c2 and threatfox
modlure feeds get feodo-c2 --offline         # print the cached feed (no network)

# enrich a capture: a known-C2 source IP becomes a high-severity event
modlure analyze capture.hexlog --enrich --format json

A match adds a threat_intel block to the event and forces severity: high — a host that is a known botnet C2 touching an ICS device is critical by definition:

{
  "src": "203.0.113.66:50000",
  "severity": "high",
  "reasons": ["THREAT-INTEL: source IP flagged by feodo-c2 (Emotet)", "..."],
  "threat_intel": { "ti_source": ["feodo-c2"], "ti_malware": ["Emotet"], "ti_confidence": 100 }
}

Edge / air-gap deployment

The feed layer (modlure/datafeeds.py, stdlib-only) fetches once over HTTPS, caches to disk (COGNIS_FEEDS_CACHE, default ~/.cache/cognis-feeds), and re-serves from cache with --offline — so enrichment keeps working on a disconnected OT / ICS network. To move intel across an air gap (sneakernet):

# on a connected box
modlure feeds update
python -m modlure.datafeeds snapshot-export feeds.tar.gz

# carry feeds.tar.gz to the air-gapped enclave, then
python -m modlure.datafeeds snapshot-import feeds.tar.gz
modlure analyze capture.hexlog --enrich --offline      # never touches the network

The committed tests run fully offline against a trimmed fixture cache (tests/fixtures/feeds_cache); see demo 06.

Passive (default) vs. Active (authorization-gated)

modlure is a defensive, authorized-use-only tool. It has two clearly separated modes.

Passive mode — the safe default (no network)

Everything default is offline: it decodes captures and runs a honeypot you own. No outbound connections to third parties are ever made.

modlure analyze capture.hexlog              # decode + classify a captured hex log
modlure analyze capture.hexlog --summary    # aggregated scan summary (JSON):
                                           #   counts by severity/category/function,
                                           #   distinct sources, recon-sweep heuristic
modlure serve --host 0.0.0.0 --port 5020    # honeypot listener — YOU own the socket
modlure analyze capture.hexlog --enrich --offline   # score source IPs vs cached C2/IOC feeds

Active mode — modlure probe (OFF by default)

⚠️ AUTHORIZED USE ONLY. Active mode opens outbound Modbus/TCP connections to real devices. Scanning equipment you are not explicitly authorized to test can be illegal and can disrupt live OT/ICS processes. Only probe devices you own or are contracted to assess.

Active probing confirms reachability and fingerprints a device using read-only requests (holding-register read, report-server-id, read device identification). It is gated four ways:

  • Off by default — refuses (exit 2) unless you pass --authorized.
  • Scope-enforced — every target must be in an allowlist (--target HOST[:PORT] repeatable, and/or --scope-file FILE); out-of-scope targets are skipped, never contacted.
  • Read-only — only read/identity function codes are ever transmitted; write and control codes (0x05/0x06/0x0F/0x10/0x16/0x08) are refused before a byte leaves the host.
  • Rate-limited--rate (default 1.0s) enforces a minimum inter-request delay so a fragile PLC is not overwhelmed.
# Refused — active mode is off by default:
modlure probe --target 10.0.0.5:502
#   error: active probing is OFF by default ...

# Authorized probe of two in-scope devices, 1 request/sec, JSON out:
modlure probe --authorized \
  --target 10.0.0.5:502 --target 10.0.0.6:502 \
  --rate 1.0 --format json

# Scope from a file (one HOST[:PORT] per line, # comments allowed):
modlure probe --authorized --scope-file authorized_devices.txt

The bundled tests for active mode hit only a localhost fixture server (tests/modbus_fixture.py) and mocks — never a real external host.

Contents

Why modlure?

OT threat-intel content engine — drop it on a VPS, share the 'someone tried to open my fake water-treatment valve' logs. ICS honeypot captures get major infosec-Twitter traction.

modlure is single-purpose, scriptable, and self-hostable: point it at a target, get prioritized results in the format your workflow already speaks (table · JSON · SARIF), gate CI on it, and let agents drive it over MCP.

Features

  • Passive (default, offline): parse frame · classify event · analyze capture · scan summary
  • ✅ Build honeypot response · live serve listener
  • ✅ Threat-intel enrichment (abuse.ch C2/IOC, edge / air-gap, offline cache)
  • Active (authorization-gated, OFF by default): read-only probe of an in-scope device — scope-enforced + rate-limited
  • ✅ JSON · SARIF · table output; CI-gate exit codes
  • ✅ Runs on Linux/macOS/Windows · Docker · devcontainer
  • ✅ Core check ported to Python, JavaScript, TypeScript, Go, and Rust (ports/, CI-tested)

Quick start

pip install modlure
modlure --version
modlure analyze capture.hexlog                       # decode + classify a capture
modlure --format json analyze capture.hexlog         # machine-readable (SIEM)
modlure --format sarif analyze capture.hexlog        # SARIF for code-scanning
modlure analyze capture.hexlog --min-severity high   # CI gate (non-zero exit)

Example

$ modlure analyze demos/04-water-treatment-tamper/capture.hexlog
SEV     SRC              FUNCTION                     ADDR   QTY  REASONS
-------------------------------------------------------------------------
low     10.0.4.10        read_holding_registers        100     4  benign register read
high    185.220.101.7    report_server_id                         suspicious function report_server_id (recon/tamper); undecodable PDU (malformed/fuzz traffic)
high    185.220.101.7    write_single_coil              16        register/coil write attempt against control device
high    185.220.101.7    write_single_register         101        register/coil write attempt against control device
high    185.220.101.7    write_multiple_coils           16     5  register/coil write attempt against control device
-------------------------------------------------------------------------
total=5  high=4, low=1

--format is accepted before or after the subcommand, and supports table (default), json, and sarif.

Demos

Every demo under demos/ is a real Modbus TCP capture in the tool's actual input format (<src> | <hex> per line) plus a SCENARIO.md explaining where the traffic came from, the exact run command, what to expect, and how to act. Each one is verified by the test suite to produce the finding it describes.

Demo Scenario Outcome
01-basic Small mixed capture (reads, writes, recon, malformed) high + medium + low
02-clean Trusted HMI reads only — negative control exit 0
03-mixed Mostly benign polling with one hostile source high
04-water-treatment-tamper Chlorine-dosing valve/setpoint writes 4× high
05-port-scan-recon Internet-wide scanner fingerprinting :502 3× high (recon)
06-plc-restart-diagnostics Restart / clear-counters / listen-only via FC 0x08 3× high
07-fuzzing-campaign Malformed/truncated frames — all recorded high + medium
08-benign-scada-poll Normal cyclic SCADA polling exit 0
09-setpoint-override Turbine overspeed-trip setpoint tamper (mask-write) 3× high
10-multi-unit-sweep One peer walking unit ids behind a gateway reads-only, exit 0
11-coil-flood Mass coil writes flipping actuators 3× high
python -m modlure analyze demos/09-setpoint-override/capture.hexlog
python -m modlure --format sarif analyze demos/05-port-scan-recon/capture.hexlog > recon.sarif

Architecture

flowchart LR
  IN[attacker traffic] --> P[modlure<br/>capture]
  P --> OUT[alerts + indicators]
Loading

Use it from any AI stack

modlure is interoperable with every popular way of using AI:

  • MCP servermodlure mcp (Claude Desktop, Cursor, Cognis.Studio, uncensored-fleet)
  • OpenAI-compatible / JSON — pipe modlure scan . --format json into any agent or LLM
  • LangChain · CrewAI · AutoGen · LlamaIndex — wrap the CLI/JSON as a tool in one line
  • CI / scripts — exit codes + SARIF for non-AI pipelines

How it compares

Cognis modlure conpot
Self-hostable, no account varies
Single command, zero config ⚠️
JSON + SARIF for CI varies
MCP-native (AI agents)
Polyglot ports (JS/TS/Go/Rust)
Open license ✅ COCL varies

Built in the spirit of conpot, re-framed the Cognis way. Missing a credit? Open a PR.

Integrations

Pipes into your stack: SARIF for code-scanning, JSON for anything, an MCP server (modlure mcp) for AI agents, and a webhook forwarder for SIEM/Slack/Jira. See docs/INTEGRATIONS.md.

Install — every way, every platform

pip install "git+https://github.com/cognis-digital/modlure.git"    # pip (works today)
pipx install "git+https://github.com/cognis-digital/modlure.git"   # isolated CLI
uv tool install "git+https://github.com/cognis-digital/modlure.git" # uv
pip install modlure                                          # PyPI (when published)
docker run --rm ghcr.io/cognis-digital/modlure:latest --help        # Docker
brew install cognis-digital/tap/modlure                             # Homebrew tap
curl -fsSL https://raw.githubusercontent.com/cognis-digital/modlure/main/install.sh | sh
Linux macOS Windows Docker Cloud
scripts/setup-linux.sh scripts/setup-macos.sh scripts/setup-windows.ps1 docker run ghcr.io/cognis-digital/modlure DEPLOY.md (AWS/Azure/GCP/k8s)

Related Cognis tools

  • fwxray — Diff two firmware images and surface exactly what changed: new binaries, flipped config flags, added certs, and shifted entropy regions.
  • canzap — Replay, fuzz, and assert on CAN bus traffic from a .pcap or SocketCAN interface with a tiny YAML DSL.
  • sbomb — Generate a CycloneDX SBOM directly from an unpacked firmware root filesystem and flag components with known CVEs and EOL kernels.
  • mqttspy — Passively map an MQTT broker: enumerate topics, detect unauthenticated writes, spot PII/secrets in payloads, and emit a risk report.
  • uefiscan — Audit UEFI firmware dumps for missing Secure Boot keys, unsigned modules, S3 boot-script vulns, and known SMM threats.
  • keyhunt — Scan firmware blobs and filesystem dumps for hardcoded private keys, API tokens, default creds, and weak RSA/ECC material.

Explore the suite → 🗂️ all 170+ tools · ⭐ awesome-cognis · 🔗 cognis-sources · 🤖 uncensored-fleet · 🧠 engram

Contributing

PRs, new rules, and demo scenarios are welcome under the collaboration-pull model — see CONTRIBUTING.md and SECURITY.md.

⭐ If modlure saved you time, star it — it genuinely helps others find it.

Interoperability

{} composes with the 300+ tool Cognis suite — JSON in/out and a shared OpenAI-compatible /v1 backbone. See INTEROP.md for the suite map, composition patterns, and reference stacks.

License

Source-available under the Cognis Open Collaboration License (COCL) v1.0 — free for personal, internal-evaluation, research, and educational use; commercial / production use requires a license ([email protected]). See LICENSE.


Cognis Digital · one of 170+ tools in the Cognis Neural Suite · Making Tomorrow Better Today

About

Spin up a high-interaction Modbus/DNP3 ICS honeypot that logs attacker register reads/writes as structured JSON.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors