Monday, March 27, 2017

BACnet - Bro - Spicy Part 1

I've been working on creating a CTF challenge that involves the BACnet/IP Building and Automation Control Networks protocol. I found Steve Karg's BACnet-Stack project, which is a great way to get to know the protocol.  He has included with the stack a demo server and client that let's you start sending packets without needing a physical device. You can also set it up on a Raspberry Pi or similar device to bring the physical world into play with LEDs, or sensors, or whatever you want to manipulate.

Unfortunately, I don't know enough C programming to get his demo client and server to do exactly what I wanted. I did learn a bunch about compiling and debugging C code as I tried to understand what was happening at different points in the communication. I also found that Steve is tremendously kind and was very responsive to my emails.

So I continued to use the demo server and client, but needed something else to detect a specific action. I'm being vague since it is a CTF challenge I'm creating.  Anyway, I needed not only to detect that the change was made, but also "who" made the change. Since BACnet is unauthenticated and over UDP, I was going to have to rely on the IP address in the packet, and due to the way the protocol layers of BACnet are stacked on UDP, it didn't look like I could get that information from the bacnet-stack.  At least not without learning C programming and rewriting the demo server code.

I then got the idea to use Bro to detect a specific packet as it came across the wire. Bro doesn't have a parser for BACnet, and I wasn't about to try to write one for the whole protocol, but I thought maybe I could write one for that very specific packet.  Luckily, I didn't have to try that path. I found a BACnet parser that is written in Spicy (formerly BinPAC++) so I went about trying to use that.


Here is my learning adventure:


I started by watching this presentation by Robin Sommer from a few years ago describing how easy it is to create a parser. (BinPAC++ Demo by Robin Sommer)  At least it sounded easy when he explained it!

I also found these articles:
Which led me to these sites:


The Plan:

  1. Set up some virtual machines in my VMware environment to experiment. 
    1. Install the BACnet-stack on two: server and client.
    2. Install Docker and the rsmmr-hilti docker image on the bacnet server machine.
  2. Write a Bro script that uses the events created by the BACnet parser to log the source IP address from packets with the correct BACnet command.
  3. Install the php-apache docker image on the bacnet server machine and run it with the same shared volume as the rsmmr-hilti container where the log file is saved.
  4. Write a PHP webpage/script that shows the flag only to the IPs in the log file and a different page to all other IPs.

1) Virtual Machines - BACnet

I ended up just using some VMs I already had. It works with many operating systems fairly easily. I used Ubuntu and a Kali Linux box.


bacnet-stack Installation Steps:

  1. Get up to date
    • sudo apt-get update
  2. Install compiler package
    • sudo apt-get install build-essential
  3. Make a directory to install to and run it from
    • mkdir /opt/bacnet 
    • cd /opt/bacnet 
  4. Download the latest version of bacnet-stack
    • wget http://sourceforge.net/projects/bacnet/files/bacnet-stack/bacnet-stack-0.8.3/bacnet-stack-0.8.3.tgz
  5. Unzip
    • tar xvfz bacnet-stack-0.8.3.tgz
  6. Make/install all including demos.
    • cd /opt/bacnet/bacnet-stack-0.8.3
    • make clean all

Edit device being served by bacserv (server)


The server represents a device that uses BACnet to communicate. They are often sensors or controllers of some sort that report back to a control system.  They are object oriented. Each device is a "Device Object" and has a set of properties with values and services or methods. A device object can have will have several standard objects, such as sensor objects like an Analog Input object. Each standard object will also have properties with values and services to perform on them. (See http://www.bacnet.org/Bibliography/ES-7-96/ES-7-96.htm for more info.)

I wanted to add some customization to my device, but didn't really know how. I poked through the code and found some static char variables that I edited just to see if it would work.


  1. Make a backup of original
    • cp demo/object/device.c  demo/object/device.bak
  2. Edit device.c with changes
    • static uint16_t Vendor_Identifier = BACNET_VENDOR_ID;
      static char Model_Name[MAX_DEV_MOD_LEN + 1] = "My Changed Model Name";
      static char Application_Software_Version[MAX_DEV_VER_LEN + 1] = "2017.0";
      static char Location[MAX_DEV_LOC_LEN + 1] = "My Changed Location";
      static char Description[MAX_DEV_DESC_LEN + 1] = "My Changed Description";
  3. From /opt/bacnet/bacnet-stack-0.8.3/  run:
    1. make clean all


Run Demo device (server)

  • sudo ./demo/server/bacserv    //let device ID be auto generated 
  • sudo ./demo/server/bacserv 123   //designate the device ID

Run query and discovery tools on device (client)

  • Get help
    • use the --help switch on any of the demo tools to get usage.
  • Device discovery on network
    • ./demo/whois/bacwi -1 
  • Read all the required properties from the device 123 and display values
    • ./demo/epics/bacepics -v  123
  • Read the object_identifier property from device 123
    • ./demo/readprop/bacrp 123 8 123 75
  • Write 100.0 (REAL=4 datatype) to the present_value property (85) of Device 123 Analog Output (1) One (1) at priority 16 with no index (-1)
    • ./demo/writeprop/bacwp 123 1 1 85 16 -1 4 100.0  
  • Read in value set
    • ./demo/readprop/bacrp 123 1 1 85  
  • Read in the present_value property (85) of Analog Output (1) One (1) of Device 123
    • ./demo/readprop/bacrp 123 1 1 85 
  • Write to device 1234's Binary Output (4) number one (1) present_value property (85) at priority 16 with no index (-1) the data type Enumerated (9) to make active (1)
    • /demo/writeprop/bacwp 1234 4 1 85 16 -1 9 1

Part 2 will pick up from here with Docker, Spicy, and Bro files.


No comments:

Post a Comment