modbus

package
v0.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 10, 2023 License: Apache-2.0, ISC Imports: 10 Imported by: 0

Documentation

Overview

Package modbus provides a zgrab2 module that scans for modbus. Default Port: 502 (TCP)

The --unit-id flag allows overriding the default value of 0 (the simulator for example does not respond at all to UnitID == 0; other servers may interpret it as a broadcast).

The --object-id flag allows reading a different object ID's information. The default of 0x00 is the VendorName, which is required.

The --request-id flag allows setting a custom request identifier (which the server will use in its response).

The --strict flag allows turning on new validity checks beyond those done in the original zgrab, to help rule out false matches.

The output is the same as the original ZGrab: a "modbus event" object, with either the parsed MEI response or the parsed exception info. The only addition is a "raw" field containing the raw response data.

Index

Constants

View Source
const (
	// FunctionCodeMEI identifies the MEI read function.
	FunctionCodeMEI = FunctionCode(0x2B)
)

Variables

View Source
var ModbusFunctionEncapsulatedInterface = FunctionCode(0x2B)

ModbusFunctionEncapsulatedInterface identifies the MEI read function.

Functions

func RegisterModule

func RegisterModule()

RegisterModule registers the zgrab2 module.

Types

type Conn

type Conn struct {
	Conn net.Conn
	// contains filtered or unexported fields
}

Conn wraps the connection state (more importantly, it provides the interface used by the old zgrab code, so that it could be taken over as-is).

func (*Conn) GetModbusResponse

func (c *Conn) GetModbusResponse() (*ModbusResponse, error)

GetModbusResponse reads the response from the server and does some minimal parsing.

func (*Conn) MarshalRequest

func (c *Conn) MarshalRequest(r *ModbusRequest) (data []byte, err error)

MarshalRequest marshals the request for transport to the server.

type ExceptionCode

type ExceptionCode byte

ExceptionCode represents the exception description codes.

type ExceptionFunctionCode

type ExceptionFunctionCode byte

ExceptionFunctionCode represents the function code corresponding to an exception -- that is, with the high bit set.

func (ExceptionFunctionCode) FunctionCode

func (e ExceptionFunctionCode) FunctionCode() FunctionCode

FunctionCode strips the high bit off of the exception function code, to get the function for which the server is responding.

type ExceptionResponse

type ExceptionResponse struct {
	// ExceptionFunction is the function to which the server is responding -- namely, the value of the FunctionCode in
	// the response with the high bit masked off.
	ExceptionFunction FunctionCode `json:"exception_function"`

	// ExceptionType is the type code representing the exception.
	// For details see e.g. section 7 of http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf
	ExceptionType byte `json:"exception_type"`
}

ExceptionResponse wraps the exception returned by the server.

type Flags

type Flags struct {
	zgrab2.BaseFlags
	// Protocols that support TLS should include zgrab2.TLSFlags
	UnitID    uint8  `long:"unit-id" description:"The UnitID / Station ID to probe"`
	ObjectID  uint8  `long:"object-id" description:"The ObjectID of the object to be read." default:"0x00"`
	Strict    bool   `long:"strict" description:"If set, perform stricter checks on the response data to get fewer false positives"`
	RequestID uint16 `long:"request-id" description:"Override the default request ID." default:"0x5A47"`
	Verbose   bool   `long:"verbose" description:"More verbose logging, include debug fields in the scan results"`
}

Flags holds the command-line configuration for the modbus scan module. Populated by the framework.

func (*Flags) Help

func (flags *Flags) Help() string

Help returns the module's help string.

func (*Flags) Validate

func (flags *Flags) Validate(args []string) error

Validate checks that the flags are valid. On success, returns nil. On failure, returns an error instance describing the error.

type FunctionCode

type FunctionCode byte

FunctionCode identifies the Modbus function being queried.

func (FunctionCode) ExceptionFunctionCode

func (c FunctionCode) ExceptionFunctionCode() ExceptionFunctionCode

ExceptionFunctionCode gets the code that the server would return in an exception to the given function code.

func (FunctionCode) IsException

func (c FunctionCode) IsException() bool

IsException checks if the given function code is an exception (i.e. its high bit is set).

type MEIObject

type MEIObject struct {
	// OID is the object identifier.
	OID MEIObjectID
	// Value is the value for that object identifier.
	Value string
}

MEIObject wraps the ID/value pair in the 0x2B/0x0E response.

func (*MEIObject) MarshalJSON

func (m *MEIObject) MarshalJSON() ([]byte, error)

MarshalJSON encodes the identifier as its friendly name.

type MEIObjectID

type MEIObjectID int

MEIObjectID is the numeric identifier used by the server to identify different data.

const (
	// OIDVendor identifies the vendor name. Mandatory ASCII String, category = basic.
	OIDVendor MEIObjectID = 0

	// OIDProductCode identifies the product code. Mandatory ASCII String, category = basic.
	OIDProductCode MEIObjectID = 1

	// OIDRevision identifies the MajorMinorRevision. Mandatory ASCII String, category = basic.
	OIDRevision MEIObjectID = 2

	// OIDVendorURL identifies the vendor URL. Optional ASCII String, category = regular.
	OIDVendorURL MEIObjectID = 3

	// OIDProductName identifies the product name. Optional ASCII String, category = regular.
	OIDProductName MEIObjectID = 4

	// OIDModelName identifies the model name. Optional ASCII String, category = regular.
	OIDModelName MEIObjectID = 5

	// OIDUserApplicationName identifies the user application name. Optional ASCII String, category = regular.
	OIDUserApplicationName MEIObjectID = 6
)

func (*MEIObjectID) Name

func (m *MEIObjectID) Name() string

Name maps the object ID to its friendly name; if the ID is not on the list, it returns "oid_$(id)".

type MEIObjectSet

type MEIObjectSet []MEIObject

MEIObjectSet wraps the list of object ID/value pairs, encoding them as a dict of ID name -> value

func (*MEIObjectSet) MarshalJSON

func (ms *MEIObjectSet) MarshalJSON() ([]byte, error)

MarshalJSON encodes the object ID list as a map of { "obj.OID.Name()": obj.Value }

type MEIResponse

type MEIResponse struct {
	// ConformityLevel specifies the confirmity level of the device and the type of supported access.
	// Valid values include 0x01, 0x02, 0x03, for basic, regular, extended stream access, and
	// 8x81, 0x82, 0x83 for basic, regular, extended stream/individual access.
	ConformityLevel int `json:"conformity_level"`

	// MoreFollows specifies whether more data follows. Strictly should be 00 or FF, but we take any nonzero number
	// to mean that more data follows.
	MoreFollows bool `json:"more_follows"`

	// NextObjectID gives the next object ID if MoreFollows is set, otherwise it should be 0x00.
	NextObjectID int `json:"next_object_id"`

	// ObjectCount gives the number of items returned.
	ObjectCount int `json:"object_count"`

	// Objects is a set of object ID/value pairs returned by the server.
	Objects MEIObjectSet `json:"objects,omitempty"`
}

MEIResponse is the parsed data field from the 0x2B/0x0E response.

type ModbusEvent

type ModbusEvent struct {
	// Length is the data length the server claimed to return in the header. Should be len(Response) + 1 (the function
	// code is included)
	Length int `json:"length"`

	// UnitID is the unit ID for which the server is responding. If request unit ID was nonzero, should match that.
	UnitID int `json:"unit_id"`

	// Function is the response function code. The high bit indicates the presence of an exception (set -> exception).
	Function FunctionCode `json:"function_code"`

	// Response is the response data (not including the function code).
	Response []byte `json:"raw_response,omitempty"`

	// MEIResponse is the parsed response; it is present if the response was decoded successfully and there was no
	// exception.
	MEIResponse *MEIResponse `json:"mei_response,omitempty"`

	// ExceptionResponse is the parsed exception; it is present if the response was decoded successfully and there was
	// an exception (i.e. the high bit of Function is set).
	ExceptionResponse *ExceptionResponse `json:"exception_response,omitempty"`

	// Raw is the full raw response from the server, including the header.
	Raw []byte `json:"raw,omitempty"`
}

ModbusEvent is the response object. Either MEIResponse or ExceptionResponse will be set.

type ModbusRequest

type ModbusRequest struct {
	// UnitID is the target unit ID. 0 can get special treatment (ignored, invalid, or treated as broadcast).
	UnitID int

	// FunctionCode identifies the function for the server to execute.
	Function FunctionCode

	//  Deta is the payload for the request, its format depends on the FunctionCode.
	Data []byte
}

ModbusRequest wraps the Modbus ApplicationDataUnit (ADU).

type ModbusResponse

type ModbusResponse struct {
	// Length is the number of bytes the server says it will return.
	Length int

	// UnitID identifies the unit this response pertains to.
	UnitID int

	// Function is the function code returned by the server (which may have the high bit set to indicate an exception).
	Function FunctionCode

	// Data is payload, its format depends on the function code. Should be Length - 1 bytes.
	Data []byte

	// Raw is the actual data returned by the server, including the header.
	Raw []byte
}

ModbusResponse wraps the data returned by the server in response to the ModbusRequest.

func (*ModbusResponse) IsException

func (m *ModbusResponse) IsException() bool

IsException returns true if this response indicates an exception has occurred.

type Module

type Module struct {
}

Module implements the zgrab2.Module interface.

func (*Module) Description

func (module *Module) Description() string

Description returns an overview of this module.

func (*Module) NewFlags

func (module *Module) NewFlags() interface{}

NewFlags returns a default Flags object.

func (*Module) NewScanner

func (module *Module) NewScanner() zgrab2.Scanner

NewScanner returns a new Scanner instance.

type Scanner

type Scanner struct {
	// contains filtered or unexported fields
}

Scanner implements the zgrab2.Scanner interface.

func (*Scanner) GetName

func (scanner *Scanner) GetName() string

GetName returns the Scanner name defined in the Flags.

func (*Scanner) GetTrigger

func (scanner *Scanner) GetTrigger() string

GetTrigger returns the Trigger defined in the Flags.

func (*Scanner) Init

func (scanner *Scanner) Init(flags zgrab2.ScanFlags) error

Init initializes the Scanner.

func (*Scanner) InitPerSender

func (scanner *Scanner) InitPerSender(senderID int) error

InitPerSender initializes the scanner for a given sender.

func (*Scanner) Protocol

func (scanner *Scanner) Protocol() string

Protocol returns the protocol identifier of the scan.

func (*Scanner) Scan

func (scanner *Scanner) Scan(target zgrab2.ScanTarget) (zgrab2.ScanStatus, interface{}, error)

Scan probes for a modbus service. It connects to the configured TCP port (default 502) and sends a packet with:

	 UnitID = <flags.UnitID, default 0>
  FunctionCode = 0x2B: Encapsulated Interface Transport)
  MEI Type = 0x0E: Read Device Info
  Category = 0x01: Basic
	 ObjectID = <flags.ObjectID, default 0: VendorName>

If the response is not a valid modbus response to this packet, then fail with a SCAN_PROTOCOL_ERROR. Otherwise, return the parsed response and status (SCAN_SUCCESS or SCAN_APPLICATION_ERROR)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL