
Scanner de detecção Modbus/TCP multithread escrito em C usando libmodbus.
Um scanner em C multithread para detetar serviços Modbus/TCP usando libmodbus.
O scanner não depende apenas de a porta TCP 502 estar aberta. Em vez disso, estabelece uma ligação Modbus/TCP e envia um pedido Modbus ao nível da aplicação. Uma resposta Modbus válida é usada como indicador principal de que um serviço Modbus está presente.
Modbus é um protocolo de comunicação industrial comummente usado por PLCs, RTUs, HMIs, sistemas SCADA, sensores, medidores e outros dispositivos industriais.
O Modbus/TCP transporta o protocolo de aplicação Modbus sobre TCP.
A porta padrão Modbus/TCP é:
TCP/502
Um fluxo de comunicação típico é:
Scanner
|
| Ligação TCP → 502
|
| Pedido Modbus/TCP
v
Dispositivo Modbus
|
| Resposta Modbus/TCP
v
Scanner
Ao contrário de protocolos que fornecem um banner imediatamente após a ligação, o Modbus/TCP geralmente exige que o cliente envie um pedido Modbus válido antes de o dispositivo produzir uma resposta ao nível da aplicação.
O scanner realiza a deteção em duas fases.
O scanner tenta estabelecer uma ligação TCP para:
<alvo>:502
Se a ligação não puder ser estabelecida, o alvo é tratado como não respondendo a Modbus/TCP.
No entanto, uma porta TCP/502 aberta por si só não é considerada evidência suficiente de Modbus.
Após ligar, o scanner envia um pedido Modbus usando libmodbus.
A sonda principal é:
modbus_read_input_registers(ctx, 0, 1, ®);
Isto gera um Código de Função Modbus:
0x04 - Ler Registos de Entrada
O pedido solicita ao alvo um registo de entrada começando no endereço 0.
Se o alvo devolver uma resposta Modbus válida, o scanner considera o serviço detetado.
Um pacote Modbus/TCP consiste em:
+----------------------+----------------------+
| Cabeçalho MBAP | PDU |
+----------------------+----------------------+
Cabeçalho MBAP:
+------------------+
| ID de Transação | 2 bytes
| ID de Protocolo | 2 bytes
| Comprimento | 2 bytes
| Identificador de Unidade | 1 byte
+------------------+
PDU:
+------------------+
| Código de Função | 1 byte
| Dados | N bytes
+------------------+
O cabeçalho MBAP é específico do Modbus/TCP.
A primeira sonda do scanner usa o Código de Função 0x04.
Um pedido representativo é:
00 01 00 00 00 06 01 04 00 00 00 01
Decompondo isto:
00 01 Identificador de Transação
00 00 Identificador de Protocolo
00 06 Comprimento
01 Identificador de Unidade
04 Código de Função
00 00 Endereço Inicial
00 01 Quantidade
00 01
Identifica a transação.
O valor pode variar porque o identificador de transação é normalmente gerido pela biblioteca cliente Modbus.
00 00
Um valor de 0 identifica Modbus.
00 06
Especifica o número de bytes que se seguem ao campo de comprimento.
01
Identifica a unidade Modbus alvo.
04
O Código de Função 0x04 significa:
Ler Registos de Entrada
00 00
O scanner começa no endereço de registo 0.
00 01
O scanner solicita um registo.
Uma resposta bem-sucedida ao pedido contém o Código de Função 0x04 e os dados do registo solicitado.
Uma resposta representativa poderia ser:
00 01 00 00 00 05 01 04 02 00 00
Decompondo:
00 01 Identificador de Transação
00 00 Identificador de Protocolo
00 05 Comprimento
01 Identificador de Unidade
04 Código de Função
02 Contagem de Bytes
00 00 Valor do Registo
A parte importante para a deteção é que o alvo processa com sucesso o pedido Modbus e devolve uma resposta Modbus válida ao nível da aplicação.
O valor real do registo depende do dispositivo.
Simplesmente verificar:
TCP/502 = ABERTA
não prova necessariamente que o serviço é Modbus.
Os números de porta são convenções. Uma aplicação diferente pode estar à escuta em TCP/502, e um dispositivo Modbus também pode comportar-se de forma diferente dependendo da sua configuração.
O scanner usa portanto:
Conectividade TCP
+
Resposta do protocolo Modbus
=
Deteção Modbus
Isto torna a deteção ao nível da aplicação mais significativa do que uma simples verificação de portas.
Alguns dispositivos podem não responder ao pedido inicial 0x04 devido à sua configuração de registos ou códigos de função suportados.
O scanner tenta portanto um segundo pedido se o primeiro falhar:
modbus_read_bits(ctx, 0, 1, bits);
Isto usa o Código de Função:
0x01 - Ler Bobinas
Um pedido representativo é:
00 02 00 00 00 06 01 01 00 00 00 01
Decomposição:
00 02 Identificador de Transação
00 00 Identificador de Protocolo
00 06 Comprimento
01 Identificador de Unidade
01 Código de Função
00 00 Endereço Inicial
00 01 Quantidade
O scanner considera o alvo detetado quando qualquer uma das operações Modbus recebe uma resposta bem-sucedida.
IP Alvo
|
v
Ligação TCP
porta 502
|
+------+------+
| |
Falhou Ligado
| |
v v
Ignorar Função 0x04
|
+------+------+
| |
Válida Falhou
| |
v v
MODBUS ENCONTRADO Função 0x01
|
+------+------+
| |
Válida Falhou
| |
v v
MODBUS ENCONTRADO Sem deteção
O scanner usa libmodbus para construir e analisar pacotes Modbus/TCP em vez de construir manualmente tramas de protocolo.
A operação principal é:
modbus_read_input_registers(ctx, 0, 1, ®);
Se isto falhar:
modbus_read_bits(ctx, 0, 1, bits);
A ligação é então fechada e o contexto libmodbus é libertado.
Isto mantém o tratamento do protocolo dentro da biblioteca Modbus enquanto o scanner trata de:
O scanner usa timeouts curtos de ligação e resposta:
#define TIMEOUT_SEC 2
Isto evita que um único anfitrião inacessível ou sem resposta bloqueie um worker durante um período excessivo de tempo.
As redes industriais podem conter dispositivos com respostas relativamente lentas, pelo que os valores de timeout podem precisar de ser ajustados dependendo do ambiente.
Os alvos são divididos entre múltiplos threads de trabalho.
Por exemplo:
Thread 1 → alvos 1–64
Thread 2 → alvos 65–128
Thread 3 → alvos 129–192
Thread 4 → alvos 193–254
Cada worker tenta independentemente a deteção Modbus/TCP.
Isto permite que vários anfitriões sejam testados em simultâneo em vez de esperar por cada alvo sequencialmente.
Um resultado positivo significa que o alvo respondeu com sucesso a um pedido Modbus compreendido pelo scanner.
Não identifica necessariamente:
Essas são tarefas separadas de fingerprinting ou avaliação.
O scanner é principalmente uma ferramenta de deteção de serviços Modbus/TCP.
O método de deteção é intencionalmente conservador.
Um dispositivo pode ser capaz de Modbus mas falhar a deteção se:
Portanto:
Sem resposta ≠ Definitivamente não é Modbus
Significa que o scanner não conseguiu obter uma resposta bem-sucedida usando as sondas que tentou.
Instale as dependências necessárias e compile com:
make
Ou diretamente:
gcc -Wall -Wextra -O2 -o modbus modbus.c -lmodbus -lpthread
Execute:
./modbus -i 192.168.1.0 -s /24 -t 10 -o results.txt
Exemplo:
[+] Modbus detetado: 192.168.1.20:502
[+] Modbus detetado: 192.168.1.42:502
[+] Verificados: 254 | Encontrados: 2 Modbus
[+] Resultados guardados em: results.txt
O scanner deteta serviços Modbus/TCP realizando interação real com o protocolo em vez de depender exclusivamente da deteção da porta TCP.
O processo de deteção é:
Ligar a TCP/502
↓
Enviar Código de Função Modbus 0x04
↓
Receber resposta Modbus válida?
↓
SIM → Modbus detetado
|
NÃO
↓
Enviar Código de Função Modbus 0x01
↓
Receber resposta Modbus válida?
↓
SIM → Modbus detetado
|
NÃO
↓
Sem deteção
O princípio-chave é simples:
Detetar o protocolo, não apenas a porta.