From bc5ecd6da7f068a12b9ee5397178723481c7a3ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Lindh=C3=A9?= Date: Tue, 31 Oct 2017 08:33:46 +0100 Subject: Move all files one level down --- broccoli/script/README | 9 --- broccoli/script/investigate.sh | 53 ------------- broccoli/script/livegraph.sh | 38 ---------- broccoli/script/measure-packets.sh | 119 ----------------------------- broccoli/script/modbus.bro | 150 ------------------------------------- broccoli/script/pasad-parsed.bro | 96 ------------------------ broccoli/script/pasad-simple.bro | 56 -------------- broccoli/script/run-midbro.sh | 40 ---------- 8 files changed, 561 deletions(-) delete mode 100644 broccoli/script/README delete mode 100755 broccoli/script/investigate.sh delete mode 100755 broccoli/script/livegraph.sh delete mode 100644 broccoli/script/measure-packets.sh delete mode 100644 broccoli/script/modbus.bro delete mode 100644 broccoli/script/pasad-parsed.bro delete mode 100644 broccoli/script/pasad-simple.bro delete mode 100644 broccoli/script/run-midbro.sh (limited to 'broccoli/script') 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}" -- cgit v1.2.1