Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Realtime mode cc link in #90

Merged
merged 4 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion osect_sensor/Infrastructure/edge_cron/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ RUN spicyz -o nbns.hlto nbns.spicy nbns.evt
WORKDIR /home/work/ot_tools/broscript/SSDP/
RUN spicyz -o ssdp.hlto ssdp.spicy ssdp.evt

WORKDIR /home/work/ot_tools/broscript/CC_LINK_BASIC/
RUN spicyz -o cc_link_basic.hlto cc_link_basic.spicy cc_link_basic.evt

WORKDIR /home/work/ot_tools/broscript/CC_LINK_NOIP/
RUN spicyz -o cc_link_noip.hlto cc_link_noip.spicy cc_link_noip.evt

WORKDIR /home/work
RUN cp -p ot_tools/broscript/CIFS_B/CIFS_B.hlto /opt/zeek/lib/zeek-spicy/modules/ \
&& cp -p ot_tools/broscript/CIFS_B/CIFS_B.zeek /opt/zeek/share/zeek/site/ \
Expand All @@ -132,7 +138,11 @@ RUN cp -p ot_tools/broscript/CIFS_B/CIFS_B.hlto /opt/zeek/lib/zeek-spicy/modules
&& cp -p ot_tools/broscript/NBNS/nbns.hlto /opt/zeek/lib/zeek-spicy/modules/ \
&& cp -p ot_tools/broscript/NBNS/nbns.zeek /opt/zeek/share/zeek/site/ \
&& cp -p ot_tools/broscript/SSDP/ssdp.hlto /opt/zeek/lib/zeek-spicy/modules/ \
&& cp -p ot_tools/broscript/SSDP/ssdp.zeek /opt/zeek/share/zeek/site/
&& cp -p ot_tools/broscript/SSDP/ssdp.zeek /opt/zeek/share/zeek/site/ \
&& cp -p ot_tools/broscript/CC_LINK_BASIC/cc_link_basic.hlto /opt/zeek/lib/zeek-spicy/modules/ \
&& cp -p ot_tools/broscript/CC_LINK_BASIC/cc_link_basic.zeek /opt/zeek/share/zeek/site/ \
&& cp -p ot_tools/broscript/CC_LINK_NOIP/cc_link_noip.hlto /opt/zeek/lib/zeek-spicy/modules/ \
&& cp -p ot_tools/broscript/CC_LINK_NOIP/cc_link_noip.zeek /opt/zeek/share/zeek/site/

# 本番イメージ
FROM ubuntu:20.04
Expand Down
2 changes: 2 additions & 0 deletions osect_sensor/Infrastructure/edge_cron/work/ot_tools/bro.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ merge_log "/opt/zeek/logs/${DATE}/nbns.*.log" "netbios-ns.log"
reformat_log "netbios-ns.log"
merge_log "/opt/zeek/logs/${DATE}/ssdp.*.log" "ssdp.log"
reformat_log "ssdp.log"
merge_log "/opt/zeek/logs/${DATE}/cclink_ie_field_basic.*.log" "cclink-ief-basic.log"
merge_log "/opt/zeek/logs/${DATE}/field_control.*.log" "cclink-ie.log"
rm /opt/zeek/logs/${DATE}/*.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
protocol analyzer spicy::cclink_ie_field_basic over UDP:
parse originator with cclink_ie_field_basic::Packet,
parse responder with cclink_ie_field_basic::Packet,
ports { 61450/udp };

import cclink_ie_field_basic;

on cclink_ie_field_basic::CyclicDataReq -> event cclink_ie_field_basic::cyclicDataReq($conn, self.dl, self.command, self.subCommand,
self.reqData.protocolVer,
self.reqData.offsetAddrInfo.cyclicInfoOffsetAddr,
self.reqData.masterNoticeInfo.protocolVer1,
self.reqData.cyclicInfo.masterID, self.reqData.cyclicInfo.groupNo, self.reqData.cyclicInfo.parameterNo, self.reqData.cyclicInfo.slaveTotalOccupiedStationCount, self.reqData.cyclicInfo.cyclicTransmissionState, self.reqData.cyclicInfo.slaveNo_slaveID
);
on cclink_ie_field_basic::CyclicDataRes -> event cclink_ie_field_basic::cyclicDataRes($conn, self.dl,
self.resData.protocolVer,
self.resData.endCode,
self.resData.offsetAddrInfo.cyclicInfoOffsetAddr,
self.resData.slaveNoticeInfo.protocolVer1,
self.resData.cyclicInfo.slaveID, self.resData.cyclicInfo.groupNo
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
module cclink_ie_field_basic;

import zeek;
import spicy;

public type Packet = unit {
reserved1: uint16 &convert=Reserved1($$);
switch ( self.reserved1 ) {
Reserved1::CyclicDataReq -> rq: CyclicDataReq;
Reserved1::CyclicDataRes -> rs: CyclicDataRes;
* -> unk: Unknown;
};

on %done { print self; }
};

type Reserved1 = enum {
CyclicDataReq = 0x5000,
CyclicDataRes = 0xd000,
};
# --------------------------------
# cc_link_ief_basicの基本リクエスト
type CyclicDataReq = unit {
reserved2: bytes &size=1;
reserved3: bytes &size=1;
reserved4: bytes &size=2;
reserved5: bytes &size=1;
dl: uint16 &byte-order=spicy::ByteOrder::Little;
reserved6: bytes &size=2;
command: bytes &size=2;
subCommand: bytes &size=2;
reqData: ReqCyclicData;

on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};

# cc_link_ief_basicの基本リクエストのデータ部
type ReqCyclicData = unit {
protocolVer: bytes &size=2;
reserved1: bytes &size=2;
offsetAddrInfo: OffsetAddrInfoRQ;
masterNoticeInfo: MasterNoticeInfoRQ;
cyclicInfo: CyclicInfoRQ;

# on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};

# cc_link_ief_basicの基本リクエストのデータ部の中身
type OffsetAddrInfoRQ = unit {
cyclicInfoOffsetAddr: bytes &size=2;
reserved2: bytes &size=14;

# on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};

# cc_link_ief_basicの基本リクエストのデータ部の中身
type MasterNoticeInfoRQ = unit {
protocolVer1: bytes &size=12;

# on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};

# cc_link_ief_basicのの基本リクエストのデータ部の中身
type CyclicInfoRQ = unit {
masterID: bytes &size=4;
groupNo: bytes &size=1;
reserved3: bytes &size=1;
frameSequenceNo: bytes &size=2;
timeoutValue: bytes &size=2;
parallelOffTimeoutCount: bytes &size=2;
parameterNo: bytes &size=2;
slaveTotalOccupiedStationCount: uint16 &byte-order=spicy::ByteOrder::Little;
cyclicTransmissionState: bytes &size=2;
reserved: bytes &size=2;
slaveNo_slaveID: bytes &size=self.slaveTotalOccupiedStationCount * 4;
cyclicDataRWw: bytes &size=self.slaveTotalOccupiedStationCount * 64;
cyclicDataRY: bytes &size=self.slaveTotalOccupiedStationCount * 8;
demo: bytes &eod;

# on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};
# --------------------------------

# --------------------------------
# cc_link_ief_basicの基本レスポンス
type CyclicDataRes = unit {
reserved2: bytes &size=1;
reserved3: bytes &size=1;
reserved4: bytes &size=2;
reserved5: bytes &size=1;
dl: uint16 &byte-order=spicy::ByteOrder::Little;
reserved6: bytes &size=2;
resData: ResCyclicData(self.dl);

on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};

# cc_link_ief_basicの基本レスポンスのデータ部
type ResCyclicData = unit(dl: uint16) {
protocolVer: bytes &size=2;
endCode: bytes &size=2;
offsetAddrInfo: OffsetAddrInfoRS;
slaveNoticeInfo: SlaveNoticeInfo;
cyclicInfo: CyclicInfoRS(dl);

# on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};

# cc_link_ief_basicのデータ部の中身
type OffsetAddrInfoRS = unit {
cyclicInfoOffsetAddr: bytes &size=2;
reserved1: bytes &size=14;

# on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};

# cc_link_ief_basicのデータ部の中身
type SlaveNoticeInfo = unit {
protocolVer1: bytes &size=20;

# on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};

# cc_link_ief_basicのデータ部の中身
type CyclicInfoRS = unit(dl: uint16) {
slaveID: bytes &size=4;
groupNo: bytes &size=1;
reserved2: bytes &size=1;
frameSequenceNo: bytes &size=2;
cyclicDataRWr: bytes &size=((dl - 50) / 72) * 64;
cyclicDataRX: bytes &size=((dl - 50) / 72) * 8;

# on %done { print self; zeek::confirm_protocol();}
# on %done { print self;}
};
# --------------------------------

type Unknown = unit {
data: bytes &eod;

# on %done { print self; }
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
module cclink_ie_field_basic;

export {
redef enum Log::ID += { LOG };

type Info: record {
## Timestamp for when the request 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;
pdu: string &log;
cmd: string &log;
# ## cclink_ie_field_basic data.
# dl: int &log;
# ## cclink_ie_field_basic REQ data.
# command: string &log;
# ## cclink_ie_field_basic REQ data.
# subCommand: string &log;
# ## cclink_ie_field_basic REQ data.
# reqData_protocolVer: string &log;
# ## cclink_ie_field_basic REQ data.
# reqData_masterNoticeInfo_protocolVer1: string &log;
# ## cclink_ie_field_basic REQ data.
# reqData_cyclicInfoRQ_masterID: string &log;
# ## cclink_ie_field_basic REQ data.
# reqData_cyclicInfoRQ_groupNo: string &log;
# ## cclink_ie_field_basic REQ data.
# reqData_cyclicInfoRQ_parameterNo: string &log;
# ## cclink_ie_field_basic REQ data.
# reqData_cyclicInfoRQ_slaveTotalOccupiedStationCount: int &log;
# ## cclink_ie_field_basic REQ data.
# reqData_cyclicInfoRQ_cyclicTransmissionState: string &log;
# ## cclink_ie_field_basic REQ data.
# reqData_cyclicInfoRQ_slaveNo_slaveID: string &log;
# ## cclink_ie_field_basic RES data.
# resData_protocolVer: string &log;
# ## cclink_ie_field_basic RES data.
# resData_endCode: string &log;
# ## cclink_ie_field_basic RES data.
# resData_offsetAddrInfo_cyclicInfoOffsetAddr: string &log;
# ## cclink_ie_field_basic RES data.
# resData_slaveNoticeInfo_protocolVer1: string &log;
# ## cclink_ie_field_basic RES data.
# resData_cyclicInfo_slaveID: string &log;
# ## cclink_ie_field_basic RES data.
# resData_cyclicInfo_groupNo: string &log;

# Set to block number of final piece of data once received.
final_block: count &optional;

# Set to true once logged.
done: bool &default=F;
};

## Event that can be handled to access the cclink_ie_field_basic logging record.
global log_cclink_ie_field_basic: event(rec: Info);

global res_endCode: table[string] of string = { ["\x00\x00"] = "nomal",
["\xCF\x80"] = "stop",};

global res_cmd: table[string] of string = { ["p\x0e"] = "cyclic",};
}

# Maps a partial data connection ID to the request's Info record.
global expected_data_conns: table[addr, port, addr] of Info;

redef record connection += {
cclink_ie_field_basic: Info &optional;
};

event zeek_init() &priority=5
{
Log::create_stream(cclink_ie_field_basic::LOG, [$columns = Info, $ev = log_cclink_ie_field_basic, $path="cclink_ie_field_basic"]);
}

function log_pending(c: connection)
{
if ( ! c?$cclink_ie_field_basic || c$cclink_ie_field_basic$done )
return;

Log::write(cclink_ie_field_basic::LOG, c$cclink_ie_field_basic);
c$cclink_ie_field_basic$done = T;
}

# function schedule_tftp_analyzer(id: conn_id)
# {
# Analyzer::schedule_analyzer(0.0.0.0, id$orig_h, id$orig_p, Analyzer::get_tag("spicy_cclink_ie_field_basic"), 20min);
# Analyzer::schedule_analyzer(0.0.0.0, id$resp_h, id$orig_p, Analyzer::get_tag("spicy_cclink_ie_field_basic"), 20min);
# }

event cclink_ie_field_basic::cyclicDataReq(c: connection, dl: int, command: string, subCommand: string,
reqData_protocolVer: string,
reqData_offsetAddrInfo_cyclicInfoOffsetAddr: string,
reqData_masterNoticeInfo_protocolVer1: string,
reqData_cyclicInfoRQ_masterID: string , reqData_cyclicInfoRQ_groupNo: string , reqData_cyclicInfoRQ_parameterNo: string , reqData_cyclicInfoRQ_slaveTotalOccupiedStationCount: int , reqData_cyclicInfoRQ_cyclicTransmissionState: string, reqData_cyclicInfoRQ_slaveNo_slaveID: string
)
{
log_pending(c);

local info: Info;
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
info$pdu = "cyclicDataReq";
if (command in res_cmd){
info$cmd = res_cmd[command];
} else {
info$cmd = "unknown_ct_" + command;
}
# info$dl = dl;
# info$command = command;
# info$subCommand = subCommand;
# info$reqData_protocolVer = reqData_protocolVer;
# info$reqData_masterNoticeInfo_protocolVer1 = reqData_masterNoticeInfo_protocolVer1;
# info$reqData_cyclicInfoRQ_masterID = reqData_cyclicInfoRQ_masterID;
# info$reqData_cyclicInfoRQ_groupNo = reqData_cyclicInfoRQ_groupNo;
# info$reqData_cyclicInfoRQ_parameterNo = reqData_cyclicInfoRQ_parameterNo;
# info$reqData_cyclicInfoRQ_slaveTotalOccupiedStationCount = reqData_cyclicInfoRQ_slaveTotalOccupiedStationCount;
# info$reqData_cyclicInfoRQ_cyclicTransmissionState = reqData_cyclicInfoRQ_cyclicTransmissionState;
# info$reqData_cyclicInfoRQ_slaveNo_slaveID = reqData_cyclicInfoRQ_slaveNo_slaveID;
c$cclink_ie_field_basic = info;
# print fmt("Zeek saw from %s %s to %s: dl:%s command:%s subCommanda:%s %s", c$start_time, c$id$orig_h, c$id$resp_h, dl, command, subCommand, reqData_protocolVer);
# schedule_tftp_analyzer(c$id);
}

event cclink_ie_field_basic::cyclicDataRes(c: connection, dl: int,
resData_protocolVer: string,
resData_endCode: string,
resData_offsetAddrInfo_cyclicInfoOffsetAddr: string,
resData_slaveNoticeInfo_protocolVer1: string,
resData_cyclicInfo_slaveID: string, resData_cyclicInfo_groupNo: string
)
{
log_pending(c);

local info: Info;
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
info$pdu = "cyclicDataRes";
# info$dl = dl;
# info$resData_protocolVer = resData_protocolVer;
# info$resData_endCode = res_endCode[resData_endCode];
# info$resData_offsetAddrInfo_cyclicInfoOffsetAddr = resData_offsetAddrInfo_cyclicInfoOffsetAddr;
# info$resData_slaveNoticeInfo_protocolVer1 = resData_slaveNoticeInfo_protocolVer1;
# info$resData_cyclicInfo_slaveID = resData_cyclicInfo_slaveID;
# info$resData_cyclicInfo_groupNo = resData_cyclicInfo_groupNo;
c$cclink_ie_field_basic = info;
# print fmt("Zeek saw from %s %s to %s: dl:%s", c$start_time, c$id$orig_h, c$id$resp_h, dl);
# schedule_tftp_analyzer(c$id);
}
Loading