-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
345 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Generated by binpac_quickstart | ||
@load ./main | ||
@load-sigs ./dpd.sig |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Generated by binpac_quickstart | ||
|
||
signature dpd_cip { | ||
|
||
ip-proto == tcp | ||
|
||
|
||
# ## TODO: Define the payload. When Bro sees this regex, on | ||
# ## any port, it will enable your analyzer on that | ||
# ## connection. | ||
# ## payload /^CIP/ | ||
|
||
enable "cip" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
##! Implements base functionality for cip analysis. | ||
##! Generates the Cip.log file. | ||
|
||
# Generated by binpac_quickstart | ||
|
||
module Cip; | ||
|
||
export { | ||
redef enum Log::ID += { LOG }; | ||
|
||
type Info: record { | ||
## Timestamp for when the event happened. | ||
ts: time &log; | ||
## Unique ID for the connection. | ||
uid: string &log; | ||
## The connection's 4-tuple of endpoint addresses/ports. | ||
id: conn_id &log; | ||
|
||
# ## TODO: Add other fields here that you'd like to log. | ||
}; | ||
|
||
## Event that can be handled to access the cip record as it is sent on | ||
## to the loggin framework. | ||
global log_cip: event(rec: Info); | ||
} | ||
|
||
# TODO: The recommended method to do dynamic protocol detection | ||
# (DPD) is with the signatures in dpd.sig. If you can't come up | ||
# with any signatures, then you can do port-based detection by | ||
# uncommenting the following and specifying the port(s): | ||
|
||
# const ports = { 1234/tcp, 5678/tcp }; | ||
|
||
|
||
# redef likely_server_ports += { ports }; | ||
|
||
event bro_init() &priority=5 | ||
{ | ||
Log::create_stream(Cip::LOG, [$columns=Info, $ev=log_cip, $path="cip"]); | ||
|
||
# TODO: If you're using port-based DPD, uncomment this. | ||
# Analyzer::register_for_ports(Analyzer::ANALYZER_CIP, ports); | ||
} | ||
|
||
event cip_event(c: connection) | ||
{ | ||
local info: Info; | ||
info$ts = network_time(); | ||
info$uid = c$uid; | ||
info$id = c$id; | ||
|
||
Log::write(Cip::LOG, info); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#include "CIP.h" | ||
#include "analyzer/protocol/tcp/TCP_Reassembler.h" | ||
#include "Reporter.h" | ||
#include "events.bif.h" | ||
|
||
using namespace analyzer::cip; | ||
|
||
CIP_Analyzer::CIP_Analyzer(Connection* c) | ||
|
||
: tcp::TCP_ApplicationAnalyzer("CIP", c) | ||
{ | ||
interp = new binpac::CIP::CIP_Conn(this); | ||
had_gap = false; | ||
} | ||
|
||
CIP_Analyzer::~CIP_Analyzer() | ||
{ | ||
delete interp; | ||
} | ||
|
||
void CIP_Analyzer::Done() | ||
{ | ||
tcp::TCP_ApplicationAnalyzer::Done(); | ||
|
||
interp->FlowEOF(true); | ||
interp->FlowEOF(false); | ||
} | ||
|
||
void CIP_Analyzer::EndpointEOF(bool is_orig) | ||
{ | ||
tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); | ||
interp->FlowEOF(is_orig); | ||
} | ||
|
||
void CIP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) | ||
{ | ||
tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); | ||
|
||
assert(TCP()); | ||
if ( TCP()->IsPartial() ) | ||
return; | ||
|
||
if ( had_gap ) | ||
// If only one side had a content gap, we could still try to | ||
// deliver data to the other side if the script layer can handle this. | ||
return; | ||
|
||
try | ||
{ | ||
interp->NewData(orig, data, data + len); | ||
} | ||
catch ( const binpac::Exception& e ) | ||
{ | ||
ProtocolViolation(fmt("Binpac exception: %s", e.c_msg())); | ||
} | ||
} | ||
|
||
void CIP_Analyzer::Undelivered(uint64 seq, int len, bool orig) | ||
{ | ||
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); | ||
had_gap = true; | ||
interp->NewGap(orig, len); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#ifndef ANALYZER_PROTOCOL_CIP_CIP_H | ||
#define ANALYZER_PROTOCOL_CIP_CIP_H | ||
|
||
#include "events.bif.h" | ||
#include "analyzer/protocol/tcp/TCP.h" | ||
#include "cip_pac.h" | ||
|
||
namespace analyzer { namespace cip { | ||
|
||
class CIP_Analyzer | ||
|
||
: public tcp::TCP_ApplicationAnalyzer { | ||
|
||
public: | ||
CIP_Analyzer(Connection* conn); | ||
virtual ~CIP_Analyzer(); | ||
|
||
// Overriden from Analyzer. | ||
virtual void Done(); | ||
virtual void DeliverStream(int len, const u_char* data, bool orig); | ||
virtual void Undelivered(uint64 seq, int len, bool orig); | ||
|
||
// Overriden from tcp::TCP_ApplicationAnalyzer. | ||
virtual void EndpointEOF(bool is_orig); | ||
|
||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) | ||
{ return new CIP_Analyzer(conn); } | ||
|
||
protected: | ||
binpac::CIP::CIP_Conn* interp; | ||
bool had_gap; | ||
}; | ||
|
||
} } // namespace analyzer::* | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
include(BroPlugin) | ||
|
||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) | ||
|
||
bro_plugin_begin(Bro CIP) | ||
bro_plugin_cc(CIP.cc Plugin.cc) | ||
bro_plugin_bif(events.bif) | ||
bro_plugin_pac(cip.pac cip-analyzer.pac cip-protocol.pac) | ||
bro_plugin_end() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include "plugin/Plugin.h" | ||
#include "CIP.h" | ||
|
||
namespace plugin { | ||
namespace Bro_CIP { | ||
|
||
class Plugin : public plugin::Plugin { | ||
public: | ||
plugin::Configuration Configure() | ||
{ | ||
AddComponent(new ::analyzer::Component("CIP", | ||
::analyzer::cip::CIP_Analyzer::InstantiateAnalyzer)); | ||
|
||
plugin::Configuration config; | ||
config.name = "Bro::CIP"; | ||
config.description = "Common Industrial Protocol analyzer"; | ||
return config; | ||
} | ||
} plugin; | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
refine flow CIP_Flow += { | ||
function proc_cip_message(msg: CIP_PDU): bool | ||
%{ | ||
BifEvent::generate_cip_event(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn()); | ||
return true; | ||
%} | ||
}; | ||
|
||
refine typeattr CIP_PDU += &let { | ||
proc: bool = $context.flow.proc_cip_message(this); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# | ||
# Useful reference for specs: http://odva.org/ | ||
# CIP NETWORKS LIBRARY Volume I: http://www.tud.ttu.ee/im/Kristjan.Sillmann/ISP0051%20Rakenduslik%20Andmeside/CIP%20docs/CIP%20Vol1_3.3.pdf | ||
# | ||
# Binpac for Common Industrial Protocol analyser. | ||
# | ||
|
||
############################## | ||
# CONSTANTS # | ||
############################## | ||
|
||
enum tag_types { | ||
BOOL = 0x00C1; # 1 byte | ||
SINT = 0x00C2; # 2 bytes | ||
INT = 0x00C3; # 4 bytes | ||
DINT = 0x00C4; # 4 bytes | ||
REAL = 0x00CA; # 4 bytes | ||
DWORD = 0x00D3; # 4 bytes | ||
LINT = 0x00C5; # 8 bytes | ||
}; | ||
|
||
# E8B means 8-bit element | ||
# C16B means 16-bit class | ||
enum segment_types { | ||
E8B = 0x28; | ||
E16B = 0x29; | ||
E32B = 0x2A; | ||
|
||
C8B = 0x20; | ||
C16B = 0x21; | ||
|
||
I8B = 0x24; | ||
I16B = 0x25; | ||
|
||
A8B = 0x30; | ||
A16B = 0x31; | ||
|
||
ANSI = 0x91; | ||
}; | ||
|
||
enum services { | ||
READ_TAG = 0x4C; | ||
READ_TAG_REPLY = 0xCC; | ||
READ_TAG_FRAGMENTED = 0x52; | ||
WRITE_TAG = 0x4D; | ||
WRITE_TAG_FRAGMENTED = 0x53; | ||
READ_MODIFY_WRITE_TAG = 0x4E; | ||
}; | ||
|
||
############################## | ||
# RECORD TYPES # | ||
############################## | ||
|
||
type Message_Request = record { | ||
srv: uint8; | ||
psize: uint8; | ||
path: uint8[psize * 2]; | ||
data: uint16; | ||
} &byteorder=bigendian; | ||
|
||
type Message_Reply = record { | ||
srv: uint8; | ||
rsrvd: uint8; | ||
st: uint8; | ||
ext: uint8; | ||
reply: Reply_Data; | ||
} &byteorder=bigendian; | ||
|
||
type Reply_Data = record { | ||
type: uint16; | ||
data: case(type) of { | ||
BOOL -> uint8[1]; | ||
SINT -> uint8[2]; | ||
INT -> uint8[4]; | ||
DINT -> uint8[4]; | ||
REAL -> uint8[4]; | ||
DWORD -> uint8[4]; | ||
LINT -> uint8[8]; | ||
}; | ||
} &byteorder=bigendian; | ||
|
||
type CIP_PDU(is_orig: bool) = record { | ||
data: bytestring &restofdata; | ||
} &byteorder=bigendian; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Analyzer for Common Industrial Protocol | ||
# - cip-protocol.pac: describes the cip protocol messages | ||
# - cip-analyzer.pac: describes the cip analyzer code | ||
|
||
%include binpac.pac | ||
%include bro.pac | ||
|
||
%extern{ | ||
#include "events.bif.h" | ||
%} | ||
|
||
analyzer CIP withcontext { | ||
connection: CIP_Conn; | ||
flow: CIP_Flow; | ||
}; | ||
|
||
# Our connection consists of two flows, one in each direction. | ||
connection CIP_Conn(bro_analyzer: BroAnalyzer) { | ||
upflow = CIP_Flow(true); | ||
downflow = CIP_Flow(false); | ||
}; | ||
|
||
%include cip-protocol.pac | ||
|
||
# Now we define the flow: | ||
flow CIP_Flow(is_orig: bool) { | ||
|
||
# ## TODO: Determine if you want flowunit or datagram parsing: | ||
|
||
# Using flowunit will cause the anlayzer to buffer incremental input. | ||
# This is needed for &oneline and &length. If you don't need this, you'll | ||
# get better performance with datagram. | ||
|
||
# flowunit = CIP_PDU(is_orig) withcontext(connection, this); | ||
datagram = CIP_PDU(is_orig) withcontext(connection, this); | ||
|
||
}; | ||
|
||
%include cip-analyzer.pac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
## Generated for cip connections | ||
## | ||
## See `Google <http://lmgtfy.com/?q=cip>`__ for more information about cip | ||
## | ||
## c: The connection | ||
## | ||
event cip_event%(c: connection%); |