aboutsummaryrefslogtreecommitdiff
path: root/broccoli/script
diff options
context:
space:
mode:
authorAndreas Lindhé <andreas@lindhe.io>2017-10-31 08:33:46 +0100
committerAndreas Lindhé <andreas@lindhe.io>2017-10-31 08:41:40 +0100
commitbc5ecd6da7f068a12b9ee5397178723481c7a3ea (patch)
tree6ac5bb33df7c3aacde8eb254c4aee1ce1df9dd29 /broccoli/script
parent2d5d5be5702867a7a719312a5a148489c3b68f31 (diff)
downloadmidbro-bc5ecd6da7f068a12b9ee5397178723481c7a3ea.tar.gz
midbro-bc5ecd6da7f068a12b9ee5397178723481c7a3ea.tar.bz2
Move all files one level down
Diffstat (limited to 'broccoli/script')
-rw-r--r--broccoli/script/README9
-rwxr-xr-xbroccoli/script/investigate.sh53
-rwxr-xr-xbroccoli/script/livegraph.sh38
-rw-r--r--broccoli/script/measure-packets.sh119
-rw-r--r--broccoli/script/modbus.bro150
-rw-r--r--broccoli/script/pasad-parsed.bro96
-rw-r--r--broccoli/script/pasad-simple.bro56
-rw-r--r--broccoli/script/run-midbro.sh40
8 files changed, 0 insertions, 561 deletions
diff --git a/broccoli/script/README b/broccoli/script/README
deleted file mode 100644
index 15f121e..0000000
--- a/broccoli/script/README
+++ /dev/null
@@ -1,9 +0,0 @@
-This directory contains a baseline implementation of the package parser
-implemented as a Bro script. A .bro file contains a script that can be
-executed on a Modbus pcap dump. A .log file contains an example for an
-output file generated by this script. By convention, the sample log file
-should contain the first 100 lines of a real log file obtained from running
-the script on packets_00014_20161128135616.cap.
-
-Currently, the scripts only handle the read_holding_registers event. Other
-events can handled by simply copying and adapting the existing handlers.
diff --git a/broccoli/script/investigate.sh b/broccoli/script/investigate.sh
deleted file mode 100755
index 9f67949..0000000
--- a/broccoli/script/investigate.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/bash
-
-if [ $# -ne 3 ]
-then
- echo "Extracts the data for one machine and one register from a Modbus dump"
- echo "and stores both the data and a plot in the current directory."
- echo
- echo "Usage: $0 DUMP IP ADDR"
- echo "Example: $0 packets_00014_20161128135616.cap 192.168.215.66 64"
- exit
-fi
-
-if [[ ! -f "$1" || ! -r "$1" ]]
-then
- echo "Dump file $1 does not exist or cannot be read."
- exit
-fi
-
-CAPTURE_FILE=$(realpath "$1")
-FILTER_MACHINE=$2
-FILTER_REGISTER=$3
-
-BRODIR=$(realpath "$(dirname "$0")/../..")
-BROSCRIPT_BASE=${BRODIR}/broccoli/script/modbus.bro
-
-TMPDIR=$(mktemp --tmpdir --directory pasad.XXXX)
-TMPDIR_BRO=${TMPDIR}/bro
-BROSCRIPT_MOD=${TMPDIR}/modbus.bro
-
-OUTDIR=$(pwd)
-OUTFILE_DAT=${OUTDIR}/${FILTER_MACHINE}-${FILTER_REGISTER}.dat
-OUTFILE_PNG=${OUTDIR}/${FILTER_MACHINE}-${FILTER_REGISTER}.png
-
-echo " * Preparing Bro script ..."
-cp "${BROSCRIPT_BASE}" "${BROSCRIPT_MOD}"
-sed -ie "s/\(const enable_filtering : bool = \).*;/\1T;/g" "${BROSCRIPT_MOD}"
-sed -ie "s/\(const filter_ip_addr : addr = \).*;/\1${FILTER_MACHINE};/g" "${BROSCRIPT_MOD}"
-sed -ie "s/\(const filter_mem_addr : count = \).*;/\1${FILTER_REGISTER};/g" "${BROSCRIPT_MOD}"
-
-echo " * Running Bro ..."
-mkdir "${TMPDIR_BRO}"
-cd "${TMPDIR_BRO}"
-bro -r "${CAPTURE_FILE}" "${BROSCRIPT_MOD}" > /dev/null
-
-echo " * Extracting data ..."
-tail -n +9 "${TMPDIR_BRO}/pasad-parsed.log" | cut -f 5 > "${OUTFILE_DAT}"
-echo "${OUTFILE_DAT}"
-
-echo " * Generating graph ..."
-echo "set terminal png; plot '${OUTFILE_DAT}' using 0:1 title '${FILTER_MACHINE} ${FILTER_REGISTER}'" | gnuplot > "${OUTFILE_PNG}"
-echo "${OUTFILE_PNG}"
-
-rm -r "${TMPDIR}"
diff --git a/broccoli/script/livegraph.sh b/broccoli/script/livegraph.sh
deleted file mode 100755
index 67111bc..0000000
--- a/broccoli/script/livegraph.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-
-if [[ $# -ne 1 ]]
-then
- echo "Reads the sensor.dat and distance.dat from a running Pasad"
- echo "instance and draws a graph from them."
- echo
- echo "Usage:"
- echo " $0 SOURCE"
- echo "Arguments:"
- echo " SOURCE an expression such that SOURCE/sensor.dat and"
- echo " SOURCE/distance.dat can be used as arguments for"
- echo " scp (e. g. user@host:/path/to/files)"
- echo
- echo "Note: Use ssh-add to avoid typing your SSH passphrase every second"
- exit 1
-fi
-
-function plot() {
- scp -i /home/andreas/.ssh/pasadpi_rsa -P 8022 "${SCP_EXPR}/sensor.dat" "${SCP_EXPR}/distance.dat" .
- tail -1000 sensor.dat > sensor-1000.dat
- tail -1000 distance.dat > distance-1000.dat
- echo "set terminal png; set yrange [17000:17300]; set y2range [0:300]; set ytics nomirror; set y2tics nomirror; set title 'Midbro/PASAD demo'; set ylabel 'sensor value'; set y2label 'distance'; plot 'sensor-1000.dat' using 0:1 with line title 'sensor value', 'distance-1000.dat' using 0:1 axis x1y2 with line title 'distance'" | gnuplot > live-tmp.png
- mv live-tmp.png live.png
-}
-
-SCP_EXPR=$1
-
-echo 0 > sensor.dat
-echo 0 > distance.dat
-plot
-feh -x --reload 0.1 live.png &
-
-while true
-do
- sleep 0.1
- plot
-done
diff --git a/broccoli/script/measure-packets.sh b/broccoli/script/measure-packets.sh
deleted file mode 100644
index b3df4be..0000000
--- a/broccoli/script/measure-packets.sh
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/bin/bash
-
-# This function has to execute the given arguments on the target machine.
-# For local execution, this could look like:
-# sudo bash -c "$@"
-# Or for remote execution:
-# ssh -i ~/.ssh/id_rsa root@remote "$@"
-# Make sure that the command is executed by root, and that root has
-# ~/.ssh/id_rsa.
-# Also note that the remote tests assumes no sudo password needed.
-
-function execute_command {
- # bash -c "$@"
- ssh -i ~/.ssh/pasadpi_rsa pi@pasadpi2 "sudo bash -c '$@'"
-}
-
-function measure_packets {
- TCPREPLAY_SPEED=$1
- TCPREPLAY_COUNT=$2
-
- BRO_PID=$(execute_command "bro -i \"${BRO_INTERFACE}\" -C -b Log::default_writer=Log::WRITER_NONE \"${BRO_SCRIPT}\" > ${BRO_DIR}/bro-out.txt 2> ${BRO_DIR}/bro-err.txt & echo \$!")
-
- PASAD_PID=""
- if [[ -n "${PASAD}" ]]
- then
- # We also want to execute a Pasad instance
- # Wait for Bro to be ready
- execute_command "tail -f ${BRO_DIR}/bro-err.txt | while read LOGLINE ; do [[ \"\${LOGLINE}\" == *\"listening on \"* ]] && pkill -P \$\$ tail ; done"
- # Start Pasad
- PASAD_PID=$(execute_command "${PASAD} > ${BRO_DIR}/pasad-out.txt 2> ${BRO_DIR}/pasad-err.txt & echo \$!")
- fi
-
- tcpreplay -i ${TCPREPLAY_INTERFACE} -M ${TCPREPLAY_SPEED} -L ${TCPREPLAY_COUNT} ${TCPREPLAY_DUMP} > /dev/null 2> /dev/null
-
- PCPU="100.0"
- while [[ $(echo "${PCPU}>${IDLE}" | bc) -eq 1 ]]
- do
- sleep 1
- PCPU=$(execute_command "ps -q ${BRO_PID} -o pcpu --no-headers")
- done
-
- if [[ -n "${PASAD_PID}" ]]
- then
- execute_command "kill -SIGINT \"${PASAD_PID}\""
- fi
- execute_command "kill -SIGINT \"${BRO_PID}\""
- execute_command "while kill -0 ${BRO_PID} 2>/dev/null ; do sleep 0.1 ; done"
-
- execute_command "tail -1 ${BRO_DIR}/bro-err.txt" | sed 's/.* \([0-9]\+\) packets received.*/\1/'
-}
-
-if [[ $# -lt 4 || $# -gt 5 ]]
-then
- echo "Executes Bro and tcpreplay and measures the number of packages"
- echo "received and handled by Bro."
- echo
- echo "Usage:"
- echo " $0 SCRIPT BIFACE DUMP TIFACE [PASAD]"
- echo "Arguments:"
- echo " SCRIPT the Bro script to execute"
- echo " BIFACE the interface for Bro to listen on"
- echo " DUMP the network dump to replay"
- echo " TIFACE the interface for tcpreplay to replay to"
- echo " PASAD the Pasad command to execute (optional)"
- exit 1
-fi
-
-BRO_SCRIPT=$1
-BRO_INTERFACE=$2
-TCPREPLAY_DUMP=$3
-TCPREPLAY_INTERFACE=$4
-PASAD=""
-if [[ $# -eq 5 ]]
-then
- PASAD=$5
-fi
-
-SPEEDS=(100 50 25)
-COUNTS=(1000000 2000000 4000000)
-
-if [[ ! -r "${TCPREPLAY_DUMP}" ]]
-then
- echo "The network dump '${TCPREPLAY_DUMP}' does not exist. Aborting."
- exit 1
-fi
-
-TCPREPLAY_DUMP=$(realpath "${TCPREPLAY_DUMP}")
-
-BRO_DIR=$(execute_command "mktemp --directory --tmpdir bro.XXX")
-
-# First run a test to measure what CPU base load to wait for
-BRO_PID=$(execute_command "bro -i \"${BRO_INTERFACE}\" -C -b Log::default_writer=Log::WRITER_NONE \"${BRO_SCRIPT}\" > ${BRO_DIR}/bro-out.txt 2> ${BRO_DIR}/bro-err.txt & echo \$!")
-sleep 10
-IDLECPU=$(execute_command "ps -q ${BRO_PID} -o pcpu --no-headers")
-IDLE=$(echo "${IDLECPU}+10" | bc);
-echo "Idle baseload is: $IDLE";
-execute_command "killall bro"
-
-echo "Starting time: $(date +'%F_%T')"
-
-echo -ne "sent\t"
-for SPEED in ${SPEEDS[@]}
-do
- echo -ne "${SPEED}\t"
-done
-echo "time"
-
-for COUNT in ${COUNTS[@]}
-do
- echo -ne "${COUNT}\t"
- for SPEED in ${SPEEDS[@]}
- do
- COUNT_RECEIVED=$(measure_packets ${SPEED} ${COUNT})
- echo -ne "${COUNT_RECEIVED}\t"
- done
- echo "$(date +'%F_%T')"
-done
-
-execute_command "rm -rf \"${BRO_DIR}\""
diff --git a/broccoli/script/modbus.bro b/broccoli/script/modbus.bro
deleted file mode 100644
index d258de3..0000000
--- a/broccoli/script/modbus.bro
+++ /dev/null
@@ -1,150 +0,0 @@
-# Example usage:
-# bro -b -C -i eth0 modbus.bro Log::default_writer=Log::WRITER_NONE
-@load frameworks/communication/listen
-@load base/protocols/modbus
-
-module Pasad;
-
-redef Pcap::bufsize = 256;
-
-redef Communication::listen_port = 47760/tcp;
-
-redef Communication::listen_ssl = F;
-
-## Global variables
-global verbose=F;
-
-## DATA STRUCTURES
-
-export {
- redef enum Log::ID += { LOG };
-
- type Transaction: record {
- start_address: count;
- quantity: count;
- };
-
- type TransactionTable: table[count] of Transaction;
-
- type Info: record {
- transactions: TransactionTable &default=TransactionTable();
- };
-
- type RegisterData: record {
- ip: addr &log;
- uid: count &log;
- regtype: string &log;
- address: count &log;
- register: count &log;
- };
-
- const enable_filtering : bool = T;
- const filter_ip_addr : addr = 192.168.215.66;
- const filter_mem_addr : count = 64;
-}
-
-redef record connection += {
- pasad: Info &default=Info();
-};
-
-redef Communication::nodes += {
- ["pasad"] = [$host = 127.0.0.1, $events = /pasad/, $connect=F, $ssl=F]
-};
-
-## CUSTOM EVENTS
-
-event pasad_register_received(data: RegisterData) {
- Log::write(Pasad::LOG, data);
- if(verbose)
- print fmt("Received address=%d, register=%d", data$address, data$register);
-}
-
-event pasad_unmatched_response(tid: count) {
- if(verbose)
- print fmt("Unmatched response: tid=%d", tid);
-}
-
-## CUSTOM FUNCTIONS
-
-function pasad_check_filter(ip: addr, start_address: count, quantity: count) : bool {
- if (!enable_filtering)
- return T;
- if (ip != filter_ip_addr)
- return F;
-
- if (start_address == 0 && quantity == 0)
- return T;
- if (start_address > filter_mem_addr)
- return F;
- return filter_mem_addr < start_address + quantity;
-}
-
-function pasad_generate_event(transaction: Transaction, c: connection,
- headers: ModbusHeaders, registers: ModbusRegisters, regtype: string,
- i: count) {
- local data = RegisterData(
- $ip=c$id$resp_h,
- $uid=headers$uid,
- $regtype=regtype,
- $address=transaction$start_address + i,
- $register=registers[i]
- );
- event pasad_register_received(data);
-}
-
-function pasad_generate_events(transaction: Transaction, c: connection,
- headers: ModbusHeaders, registers: ModbusRegisters, regtype: string) {
- # TODO: check registers size
- if (enable_filtering) {
- if(verbose)
- print fmt("%d %d %d", filter_mem_addr, transaction$start_address, transaction$quantity);
- pasad_generate_event(transaction, c, headers, registers, regtype,
- filter_mem_addr - transaction$start_address);
- } else {
- local i = 0;
- while (i < transaction$quantity) {
- pasad_generate_event(transaction, c, headers, registers, regtype, i);
- ++i;
- }
- }
-}
-
-## EVENT HANDLERS
-
-event bro_init() &priority=5 {
- Log::create_stream(Pasad::LOG, [$columns=RegisterData, $path="pasad-parsed"]);
-}
-
-event modbus_read_holding_registers_request(c: connection,
- headers: ModbusHeaders, start_address: count, quantity: count) {
- if (!pasad_check_filter(c$id$resp_h, start_address, quantity)) {
- if(verbose)
- print fmt("Filtered %s/%d/%d", c$id$resp_h, start_address, quantity);
- return;
- }
-
- local tid = headers$tid;
- local transaction = Transaction(
- $start_address=start_address,
- $quantity=quantity
- );
- c$pasad$transactions[tid] = transaction;
-}
-
-event modbus_read_holding_registers_response(c: connection,
- headers: ModbusHeaders, registers: ModbusRegisters) {
- if (!pasad_check_filter(c$id$resp_h, 0, 0)) {
- if(verbose)
- print fmt("Filtered %s", c$id$resp_h);
- return;
- }
-
- local tid = headers$tid;
- if (tid !in c$pasad$transactions) {
- event pasad_unmatched_response(tid);
- return;
- }
- local transaction = c$pasad$transactions[tid];
- delete c$pasad$transactions[tid];
- pasad_generate_events(transaction, c, headers, registers, "h");
-}
diff --git a/broccoli/script/pasad-parsed.bro b/broccoli/script/pasad-parsed.bro
deleted file mode 100644
index 88b1be1..0000000
--- a/broccoli/script/pasad-parsed.bro
+++ /dev/null
@@ -1,96 +0,0 @@
-## Implementation that outputs the register identification and the register
-## value. The correct register count is not checked and might lead to indexing
-## errors.
-
-module Pasad;
-
-## DATA STRUCTURES
-
-export {
- redef enum Log::ID += { LOG };
-
- type Transaction: record {
- start_address: count;
- quantity: count;
- };
-
- type TransactionTable: table[count] of Transaction;
-
- type Info: record {
- transactions: TransactionTable &default=TransactionTable();
- };
-
- type Entry: record {
- ip: addr &log;
- uid: count &log;
- regtype: string &log;
- address: count &log;
- register: count &log;
- };
-}
-
-redef record connection += {
- pasad: Info &default=Info();
-};
-
-## CUSTOM EVENTS
-
-event pasad_entry(entry: Entry)
- {
- Log::write(Pasad::LOG, entry);
- }
-
-event pasad_unmatched(tid: count)
- {
- print fmt("Unmatched response: tid=%d", tid);
- }
-
-## CUSTOM FUNCTIONS
-
-function pasad_generate_events(transaction: Transaction, c: connection, headers: ModbusHeaders, registers: ModbusRegisters, regtype: string)
- {
- # TODO: check registers size
- local i = 0;
- while ( i < transaction$quantity )
- {
- local entry = Entry(
- $ip=c$id$orig_h,
- $uid=headers$uid,
- $regtype=regtype,
- $address=transaction$start_address + i,
- $register=registers[i]
- );
- event pasad_entry(entry);
- ++i;
- }
- }
-
-## EVENT HANDLERS
-
-event bro_init() &priority=5
- {
- Log::create_stream(Pasad::LOG, [$columns=Entry, $path="pasad-parsed"]);
- }
-
-event modbus_read_holding_registers_request(c: connection, headers: ModbusHeaders, start_address: count, quantity: count)
- {
- local tid = headers$tid;
- local transaction = Transaction(
- $start_address=start_address,
- $quantity=quantity
- );
- c$pasad$transactions[tid] = transaction;
- }
-
-event modbus_read_holding_registers_response(c: connection, headers: ModbusHeaders, registers: ModbusRegisters)
- {
- local tid = headers$tid;
- if ( tid !in c$pasad$transactions )
- {
- event pasad_unmatched(tid);
- return;
- }
- local transaction = c$pasad$transactions[tid];
- delete c$pasad$transactions[tid];
- pasad_generate_events(transaction, c, headers, registers, "h");
- }
diff --git a/broccoli/script/pasad-simple.bro b/broccoli/script/pasad-simple.bro
deleted file mode 100644
index db3b4be..0000000
--- a/broccoli/script/pasad-simple.bro
+++ /dev/null
@@ -1,56 +0,0 @@
-## Simple implementation that outputs the raw request and response data
-## to a log file.
-## Currently, this only handles the read_holding_registers event. Other
-## events can be handled similarily. This implementation assumes that
-## requests and responses are exchanged within the same connection. I am not
-## sure whether this really holds.
-
-module Pasad;
-
-export {
- redef enum Log::ID += { LOG };
-
- type Info: record {
- ts_request: time &log;
- ts_response: time &log &optional;
- rtype: string &log;
- tid_request: count &log;
- tid_response: count &log &optional;
- ip_orig: addr &log;
- ip_resp: addr &log;
- start_address: count &log;
- quantity: count &log;
- registers: ModbusRegisters &log &optional;
- };
-}
-
-redef record connection += {
- pasad: Info &optional;
-};
-
-event bro_init() &priority=5
- {
- Log::create_stream(Pasad::LOG, [$columns=Info, $path="pasad-simple"]);
- }
-
-event modbus_read_holding_registers_request(c: connection, headers: ModbusHeaders, start_address: count, quantity: count)
- {
- local rec: Info = [
- $ts_request=network_time(),
- $rtype="holding",
- $tid_request=headers$tid,
- $start_address=start_address,
- $quantity=quantity,
- $ip_orig=c$id$orig_h,
- $ip_resp=c$id$resp_h
- ];
- c$pasad = rec;
- }
-
-event modbus_read_holding_registers_response(c: connection, headers: ModbusHeaders, registers: ModbusRegisters)
- {
- c$pasad$tid_response = headers$tid;
- c$pasad$ts_response = network_time();
- c$pasad$registers = registers;
- Log::write(Pasad::LOG, c$pasad);
- }
diff --git a/broccoli/script/run-midbro.sh b/broccoli/script/run-midbro.sh
deleted file mode 100644
index a9bb008..0000000
--- a/broccoli/script/run-midbro.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-if [ $# -ne 2 ]
-then
- echo "Starts Bro with the given arguments in the background and, when"
- echo "it’s ready, starts Midbro."
- echo
- echo "Usage: $0 INTERFACE SCRIPT"
- echo "Example: $0 lo modbus.bro"
- exit
-fi
-
-INTERFACE=$1
-SCRIPT=$(realpath $2)
-
-BRODIR=$(realpath "$(dirname "$0")/../..")
-BROLOG=$(realpath bro.log)
-
-MIDBRO=${BRODIR}/broccoli/bin/midbropasad
-MIDBROLOG=$(realpath midbro.log)
-
-TMPDIR=$(mktemp --directory --tmpdir pasad.XXXX)
-
-echo "* Starting Bro in background ..."
-cd "${TMPDIR}" && sudo bro -i "${INTERFACE}" "${SCRIPT}" > ${BROLOG} 2>&1 &
-BROPID=$!
-
-echo "* Waiting for Bro to listen ..."
-sleep 1
-tail -f ${BROLOG} | while read LOGLINE
-do
- [[ "${LOGLINE}" == "listening on "* ]] && pkill -P $$ tail
-done
-
-echo "* Starting Midbro ..."
-${MIDBRO}
-
-kill $BROPID
-
-rm -r "${TMPDIR}"