Metadata-Version: 2.4
Name: oida-ics
Version: 1.0.3
Summary: OIDA - OT/ICS Dynamic Assessment Framework
Author: f0rw4rd
Maintainer: f0rw4rd
License: AGPL-3.0-or-later
Project-URL: Homepage, https://github.com/f0rw4rd/oida
Project-URL: Bug Reports, https://github.com/f0rw4rd/oida/issues
Project-URL: Source, https://github.com/f0rw4rd/oida
Project-URL: Documentation, https://getoida.dev
Project-URL: Contact, https://getoida.dev/contact
Project-URL: Changelog, https://github.com/f0rw4rd/oida/blob/main/CHANGELOG.md
Project-URL: Security, https://github.com/f0rw4rd/oida/blob/main/SECURITY.md
Keywords: ics,scada,industrial,security,pentesting,modbus,opcua,ethercat
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: Topic :: Security
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Topic :: Software Development :: Testing
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: tqdm==4.70.1
Requires-Dist: manuf2==2.0.2
Requires-Dist: pyserial==3.5
Requires-Dist: termcolor==3.3.0
Provides-Extra: ads
Requires-Dist: pyads==3.6.0; extra == "ads"
Provides-Extra: bacnet
Requires-Dist: BAC0==2026.7.25; extra == "bacnet"
Requires-Dist: PyYAML==6.0.3; extra == "bacnet"
Provides-Extra: bacnetsc
Requires-Dist: BAC0==2026.7.25; extra == "bacnetsc"
Requires-Dist: PyYAML==6.0.3; extra == "bacnetsc"
Requires-Dist: websockets==16.0; extra == "bacnetsc"
Requires-Dist: cryptography>=43.0.0; extra == "bacnetsc"
Provides-Extra: can
Requires-Dist: python-can==4.6.1; extra == "can"
Provides-Extra: coap
Requires-Dist: aiocoap==0.4.17; extra == "coap"
Requires-Dist: cbor2==6.1.4; extra == "coap"
Requires-Dist: DTLSSocket==0.2.3; sys_platform != "win32" and extra == "coap"
Provides-Extra: dicom
Requires-Dist: pynetdicom==3.0.4; extra == "dicom"
Requires-Dist: pydicom==3.0.2; extra == "dicom"
Provides-Extra: discovery
Requires-Dist: zeroconf==0.151.3; extra == "discovery"
Requires-Dist: scapy==2.7.0; extra == "discovery"
Requires-Dist: psutil==7.2.2; extra == "discovery"
Requires-Dist: profinet-py==0.6.5; extra == "discovery"
Requires-Dist: defusedxml==0.7.1; extra == "discovery"
Provides-Extra: dnp3
Requires-Dist: yadnp3==3.2.1.2; extra == "dnp3"
Provides-Extra: ethercat
Requires-Dist: pysoem==1.1.13; sys_platform != "win32" and extra == "ethercat"
Provides-Extra: ethernetip
Requires-Dist: pycomm3==1.2.16; extra == "ethernetip"
Requires-Dist: cryptography>=43.0.0; extra == "ethernetip"
Provides-Extra: fhir
Requires-Dist: fhirclient==4.4.0; extra == "fhir"
Requires-Dist: requests==2.34.2; extra == "fhir"
Provides-Extra: goose
Requires-Dist: pyiec61850-ng==1.6.1.10; extra == "goose"
Provides-Extra: hart
Requires-Dist: hartip-py==0.3.0; extra == "hart"
Provides-Extra: hl7
Requires-Dist: hl7apy==1.3.5; extra == "hl7"
Provides-Extra: iec104
Requires-Dist: c104==2.2.1; extra == "iec104"
Provides-Extra: knx
Requires-Dist: xknx==3.20.0; extra == "knx"
Requires-Dist: xknxproject==3.10.0; extra == "knx"
Provides-Extra: mms
Requires-Dist: pyiec61850-ng==1.6.1.10; extra == "mms"
Provides-Extra: modbus
Requires-Dist: pymodbus==3.15.0; extra == "modbus"
Requires-Dist: PyYAML==6.0.3; extra == "modbus"
Provides-Extra: mqtt
Requires-Dist: paho-mqtt==2.1.0; extra == "mqtt"
Provides-Extra: opcua
Requires-Dist: asyncua==2.0.1; extra == "opcua"
Provides-Extra: pcap
Requires-Dist: oida-pyshark==0.6.1.post1; extra == "pcap"
Provides-Extra: profinet
Requires-Dist: profinet-py==0.6.5; extra == "profinet"
Provides-Extra: snap7
Requires-Dist: python-snap7==3.1.2; extra == "snap7"
Provides-Extra: snmp
Requires-Dist: pysnmp==7.1.29; extra == "snmp"
Provides-Extra: tase2
Requires-Dist: pyiec61850-ng==1.6.1.10; extra == "tase2"
Provides-Extra: astm
Provides-Extra: ocpp
Requires-Dist: websockets==16.0; extra == "ocpp"
Requires-Dist: cryptography>=43.0.0; extra == "ocpp"
Provides-Extra: serial
Requires-Dist: pyserial==3.5; extra == "serial"
Provides-Extra: fuzz
Requires-Dist: boofuzz==0.4.2; extra == "fuzz"
Requires-Dist: sqlalchemy==2.0.54; extra == "fuzz"
Requires-Dist: pyasn1==0.6.4; extra == "fuzz"
Requires-Dist: crc==7.1.0; extra == "fuzz"
Requires-Dist: h2==4.4.1; extra == "fuzz"
Requires-Dist: scapy==2.7.0; extra == "fuzz"
Requires-Dist: brotli==1.2.0; extra == "fuzz"
Requires-Dist: cryptography>=43.0.0; extra == "fuzz"
Provides-Extra: all
Requires-Dist: oida-ics[ads,astm,bacnet,bacnetsc,can,coap,dicom,discovery,dnp3,ethercat]; extra == "all"
Requires-Dist: oida-ics[ethernetip,fhir,goose,hart,hl7,iec104,knx,mms]; extra == "all"
Requires-Dist: oida-ics[fuzz,modbus,mqtt,ocpp,opcua,pcap,profinet,serial,snap7,snmp,tase2]; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=9.0.3; extra == "dev"
Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=1.4.0; extra == "dev"
Requires-Dist: pytest-docker>=3.2.5; extra == "dev"
Requires-Dist: pytest-xdist>=3.8.0; extra == "dev"
Requires-Dist: pytest-timeout>=2.4.0; extra == "dev"
Requires-Dist: pytest-rerunfailures>=15.0; extra == "dev"
Requires-Dist: flake8>=7.3.0; extra == "dev"
Requires-Dist: mypy>=1.19.1; extra == "dev"
Requires-Dist: pre-commit>=4.5.1; extra == "dev"
Requires-Dist: ruff>=0.15.1; extra == "dev"
Requires-Dist: vulture>=2.16; extra == "dev"
Requires-Dist: bandit>=1.9.3; extra == "dev"
Requires-Dist: Brotli>=1.2.0; extra == "dev"
Requires-Dist: docker>=7.1.0; extra == "dev"
Requires-Dist: defusedxml>=0.7.1; extra == "dev"
Requires-Dist: msgpack>=1.1.0; extra == "dev"
Requires-Dist: tomli>=2.0.0; python_version < "3.11" and extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx<9,>=8.0.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == "docs"
Requires-Dist: myst-parser<5,>=4.0.1; extra == "docs"
Dynamic: license-file

<div align="center">

<img src="assets/oida.png" alt="OIDA" width="140" />

**Scan. Fuzz. Assess. Responsibly in OT.**

One CLI to scan, fuzz, and assess OT protocols on industrial, energy,
building-automation, and healthcare networks. It runs from a single binary, so
it works air-gapped.

[![Python](https://img.shields.io/badge/python-3.10+-5cc8e8.svg)](https://www.python.org/downloads/)
[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-ffb000.svg)](https://www.gnu.org/licenses/agpl-3.0)
[![PyPI](https://img.shields.io/pypi/v/oida-ics.svg)](https://pypi.org/project/oida-ics/)
[![CLA](https://img.shields.io/badge/CLA-required-blue)](CONTRIBUTING.md)

**[Docs and live demo at getoida.dev](https://getoida.dev)**

</div>

---

Every protocol uses the same `oida <protocol> <target>` syntax. It is the
NetExec model for industrial control systems: if you know `nxc smb`, you already
know `oida modbus`.

## Install

```bash
pip install 'oida-ics[all]'
```

The PyPI package is `oida-ics` (the name `oida` was already taken); the command
it installs is still `oida`. Protocol stacks ship as extras, so you can install
only what you need, like `pip install 'oida-ics[modbus,opcua]'`. A bare
`pip install oida-ics` has no protocol stacks at all. The full install guide is at
[getoida.dev/getting-started/installation](https://getoida.dev/getting-started/installation/).

## Usage

```bash
oida modbus 10.0.0.5                  # scan a host
oida modbus 10.0.0.5:5020             # ...on a non-default port
oida modbus 10.0.0.0/24 -t 20         # scan a subnet
oida opcua opc.tcp://10.0.0.5:4840    # OPC UA
oida discovery eth0                   # find ICS devices on the wire
```

Any target may carry a port - `10.0.0.5:5020`, `10.0.0.0/24:5020`,
`[2001:db8::1]:5020`, or per line in a target file - which saves repeating
`-p` and is the only way to scan hosts on different ports in one run. A port in
the target wins over `-p/--port`.

Defaults are read-only. Writes and state changes need an explicit `--confirm`.
Run `oida <protocol> -h` for a protocol's full flag set.

## Protocols

OIDA ships scanners for Modbus, OPC UA, Siemens S7, DNP3, IEC 60870-5-104,
BACnet, EtherNet/IP, PROFINET, HL7, DICOM, MQTT, SNMP, and many more. The full
list and the per-protocol guides live at
[getoida.dev/protocols](https://getoida.dev/protocols/modbus/).

## Links

- **Docs and demo:** [getoida.dev](https://getoida.dev)
- **Discussion:** [GitHub Discussions](https://github.com/f0rw4rd/oida/discussions)
- **Contact:** [contact@getoida.dev](mailto:contact@getoida.dev)
- **Contributing:** [CONTRIBUTING.md](CONTRIBUTING.md), [Code of Conduct](CODE_OF_CONDUCT.md)
- **Security:** report it through [getoida.dev/contact](https://getoida.dev/contact); see [SECURITY.md](SECURITY.md) for what to include
- **Support:** [via QuellSec](https://quellsec.dev/#support) or [ko-fi.com/f0rw4rd](https://ko-fi.com/f0rw4rd)

## Legal

OIDA is built for authorized security research and defensive assessment of OT/ICS and healthcare networks. Use it only against systems you own or have explicit written authorization to test. Computer crime statutes in most jurisdictions apply regardless of intent.

The tool can crash devices, trigger physical actuator writes, and extract credentials. These are features, not bugs. Do not run it against systems you are not prepared to disrupt.

Full terms, capability disclosure, warranty disclaimer, and jurisdiction guidance: [getoida.dev/legal](https://getoida.dev/legal/).

All protocol and vendor names (EtherCAT, PROFINET, Modbus, BACnet, EtherNet/IP, OPC UA, DICOM, HL7, FHIR, KNX, and others) are the property of their respective owners. OIDA is unaffiliated with and unendorsed by any of those organizations.

## License

[AGPL-3.0](LICENSE)

## Trademarks

All marks belong to their owners; used nominatively to describe interoperability; no endorsement implied.
