Reversing the Parrot SkyController Firmware

Share

Introduction

The Parrot SkyController is a remote control sold for long range flights with the Parrot Bebop drone, sometimes used in the real estate sector. It enables integration of smartphones and tablets for flight control via Wifi connection, allowing transmission of real-time data from the drone. In other words, the SkyController acts as an intermediate between the flight management software (smartphone/tablet) and the actual drone. In this post, we explain how to reverse the firmware of the SkyController to be able o view the contents of the internal operating system and understand its inner workings. A lot of the information provided is based on [1] and is applied on this specific firmware. Code is provided along this post that will extract files and information from the SkyController firmware.

The Parrot SkyController Device
The Parrot SkyController Device (taken from the Parrot Store)

Contents

The firmware of the Parrot Skycontroller appears to be a well-defined format which is reused across multiple products from the company. The firmware contains 2 types of structures the header and a sequence of “data entries”. The header is located at the beginning of the file and is followed by multiple entries which contains configuration and file system information. We will look at both structures in the following sections.

Header

The firmware header starts with four magic bytes which spells out “PLF!”. These can therefore be used to identify valid Parrot firmware files. A quick Python snippet is included below as an example.

Immediately after the magic bytes, a sequence of thirteen 32-bit unsigned integers provides additional information about the firmware. Defined as a C structure, the header would look something like this:

The header version specify the type of format used for the firmware header. Within the SkyController firmware, the value for this field was “0x0D”, possibly indicating that there are 14 variations of header formats. The header size provides the number of bytes included in the header while the entry header size specifies the number of bytes in headers of entries within the firmware. The next 5 integers are undefined at the moment, as is the before-last integer. One of them is likely a CRC32 checksum. The dwVersionMajor, dwVersionMinor and dwVersionRevision defines the version of the firmware. Lastly, the header contains the size of the file in bytes.

Entries

Each entry has a header of constant size, which is specified within the firmware header by the dwEntrySize value. In the SkyController, each entry is composed of 20 bytes used as follows:

 

The section type specify the type of data contained within the entry. This can be configuration data, partition details or file information. These will be explained in further details in the sections below. The entry size contains the number of bytes within the entry, without consideration for null-byte padding. This field is followed by a CRC32 value. It’s unclear at this point how this value is calculated. The last known integer is the size of the data once uncompressed. If this value is 0, then the contents are not compressed. Each type of entry have further fields defined, and these are explained below.

Firmware Entries

There are multiple types of entries within the firmware. In this section we will describes the one we came across in the file we have analyzed.

Bootloader and Boot Configuration (0x03, 0x07)

Entry 0x03 contains a binary file which appears to be the bootloader of the system based on strings contained within, however more analysis will be required to understand how it actually works. In the SkyController, a PLF file was observed, but within that PLF file, this entry had binary data. Similarly, entry 0x07 also appears to be related to the boot process as shown by the string “ecos-bootloader-p7-start-246-ge30badf”, “ecos” referring to the eCos operating system.

File System Data (0x09)

There is a  “File System Data” entry for each file contained in the firmware. As such, this entry is the most common one. Depending on whether the file is compressed or not, the structure of this entry is slightly different: when its contents are uncompressed, this entry starts with the filename (or directory name), which is a zero-terminated string. The name is then followed by 3 unsigned integers.

The first integer contains flags specifying the type of file, which can be a directory, a normal file or a symbolic link. This is specified by reading the bits 12 to 15. The 12 other bits contains the permissions of the file. Converted into octal form, the last 12 bits will provide the same format as the one used in Linux. For example:

Extracting File Permissions from the Firmware Entry
Extracting File Permissions from the Firmware Entry

When compressed, the flags are within the Gzip-compressed data. The data must therefore be first uncompressed and then, the same procedure applies: the filename will be a null-terminated string right at the beginning, followed 3 unsigned integers, the first containing the type and permissions. The remaining bytes are the content of the file. In the example below, the filename is system/pulsar/etc/boxinit.hosted. The flags are 0x000081A0 (little-endian) and the contents of the file starts at 0x32. 

Partition Data (0x0B)

The 0x0B entry contains information about partitions on the device.The header of this entry is composed of 10 values. The first 4 integers are version information, the next 5 ones are unknown and the last unsigned integer is the number of partitions defined within the entry.

For each partition defined within the entry, a sub entry is available which contains further information about the partition: the device ID, volume data and the mount point on the target device. The defining structure for this entry are:

Volume type can be either RAW, STATIC and DYNAMIC. A raw partition contains no file systems, for example swap partitions. Static partitions are read-only, such as the boot partition and finally, the dynamic partitions are read-write and contains modifiable files.

Installation Data (0x0C)

This entry was included early in the file and contained another PLF file within its data. This PLF file contained a 0x00 entry, which is unknown, a 0x03 entry and a 0x07 entry. The 0x07 entry contained boot options:

Conclusion

I have upload a Python program [2] which will extract information and files from the SkyController firmware here. It also successfully extracted files for a Bebop2 firmware and I suspect it will work for other recent firmware. With additional work, it may reverse older ones. Repacking an unpacked firmware should be doable, but I do not have any of the device to test it out. Before doing so, determining how the CRC value for the header and each entry is calculate is required. Future work would include testing additional firmware files and implementing the program to repack an unpacked and modified firmware. Finally, reading the eCos documentation may clarify many of the unidentified values.

References

[1] “PLF File Format”, E/S and I, https://embedded-software.blogspot.ca/2010/12/plf-file-format.html (accessed 2016-12-13)

[2] Racicot, J. “Vulture”, https://github.com/InfectedPacket/vulture (accessed 2017-01-03)

The Byte-BOS Real-Time Multitasking Operating System

Compared to operating systems in general computing, the world of embedded devices remains a world to be discovered by security analysts and hackers alike, and it offers much to explore. While reverse engineering of many newer appliances is revealing well known operating systems such as Windows or Linux, others remains fairly unexplored, such as TinyOS or μOS. Legacy devices, still in used across many industries, also provide a rich variety of unknown software and architectures. One of them is the Byte-BOS Real-Time Multitasking Operating System (RTMOS).

Share

Introduction

Compared to operating systems in general computing, the world of embedded devices remains a world to be discovered by security analysts and hackers alike, and it offers much to explore. While reverse engineering of many newer appliances is revealing well known operating systems such as Windows or Linux, others remain fairly unexplored, such as TinyOS or μOS. Legacy devices, still in use across many industries, also provide a rich variety of unknown software and architectures. One of them is the Byte-BOS Real-Time Multitasking Operating System (RTMOS). This short article attempts, based on limited information, to detail this little known system, explore its history, usage and basic composition.

History

The Byte-BOS RTMOS was initially developed in 1994 by Numerical Services Inc. The company, defunct since 2004, sold the full C source code of the RTMOS to customers for 7495 $USD. Possession of the source code allowed the buyer full customization of the operating system according to the device being designed. The system supported a restricted set of microcontrollers (see table 1) including the Intel x86 and Motorola M68000. Other lesser known microprocessors supported included architectures from Hitachi, Mitsubishi and Texas Instruments, which were used in embedded devices within the medical, industrial and telecommunications sectors. Due to the long life-cycle of these devices, it may still be possible to identify devices leveraging the Byte-BOS RTMOS. Development and support for the RTMOS ceased around 2004. As such, documentation is very scarce, and remnants of information are available only via the Internet Archive [1]. At the time of writing, the domain “www.bytebos.com” resolves to “Scheumacher Engineering”, owned by the original developer of Byte-BOS. However the website is nothing more than a single page which was last updated in 2013.

Table 1 – Microprocessors supported by the Byte-BOS RTMOS.
Intel 80×86 Coldfire Mitsubishi M16C Texas Instruments
C2x/C5x DSP
Intel 80188/86 Motorola 68000 Mitsubishi M32D Texas Instruments
C3x/C4x DSP
Intel 80×86 (32bit) Motorola 68HC11 Hitachi H8300 ARM/THUMB
Intel 8096 Motorola 68HC16 Hitachi H8300H
Intel i960 Mitsubishi
M37700
Hitachi SHX

Description

The Byte-BOS RTMOS is a minimal operating system providing task scheduling management for user applications, along with typical OS activities such as interprocess messaging, memory allocation and prioritization. It performs pre-emptive and non-pre-emptive scheduling of an unlimited number of queued tasks. The system enforces scheduling via interrupt service routines (ISRs) which can suspend and/or resume tasks based on events and their priority. When multiple tasks with a similar priority are requesting resources, the RTMOS assign the resources via a round-robin selection method.

As other operating systems, memory allocation appears to follow a standard process by keeping track of used and free memory chunks via a heap implemented by a double-linked list, which is the data structure used across the RTMOS to store unlimited numbers of objects. Tasks can dynamically allocate and free memory as needed. It also manages events and interaction with devices on behalf of user applications by abstracting the underlying hardware via a Device object (see figure 1). Byte-BOS also provides inter-tasks communications mechanisms for synchronization amongst tasks such as messages and semaphores.  In terms of data structures the double linked list and buffer objects appear to be the main structures used across the RTOS. Memory chunks, tasks and most of the other objects are all managed via the List object.  It also supports the queue structure used to manage tasks. A software stack is also provided and used by tasks to run.

Security-wise, Byte-BOS does not have any authentication or specific security methods for access to memory or special “kernel” functions; all tasks have the same level of authority than the RTOS. Basically, Byte-BOS is completely flat.

Architecture

The RTMOS is written in C or specific variety of C specification depending on the targeted microprocessor. The 10 main components of the operating systems are represented in figure 1 and provide an excellent overview of the functions accomplished. A simulated “this” pointer to the various “struct”s is made available to the developer to give an Oriented-Object Programming (OOP) feel. This section describes briefly the main components of Byte-BOS, along with some of the features marketed by the original developer.

UML Representation of the different objectsfooun in the Byte-BOS RTMOS
Figure 1 – UML Representation of the different objects defined in the Byte-BOS RTMOS

The Task Object

The main object of the RTMOS is the Task object, which is very similar to the similar concept modern software development. Just as in any C/C++ object, a constructor is initiated prior to executing the body of the task, which is defined by the developer to conduct a specific task. Data of the task is allocated and accessible via the this_data pointer. Tasks also allocate sub-objects, opens required devices, initialize variables and synchronize state machines. Once constructed, the task runs its main function until it returns or is removed. Access to a task is done via the this_task pointer. Both pointers described are always in scope and usable within the task. Once the main task completes, the destructor of the structure is called, which frees memory and pointers of sub-objects. It also terminates any internal state machine.

The Memory Object

This object manages the memory heap and stores the pointer to the heap, the block size and the number of memory blocks. It also exposes various functions for memory management, mainly alloc_fmem and free_fmem. The heap is implemented using a double-linked list in which each node contains metadata about the memory blocks. While details are not available, it can be assumed that the size of the block, its status (free or allocated) and a pointer to the next block is included.

The Semaphore Object

As its name implies, the Semaphore is used for signaling and control between multiple tasks by either being in the Up or Down status. A timeout can be defined as needed.

The MessageBox Object

The MessageBox acts as a central repository for tasks to exchange data. Tasks and ISRs can create messages to initiate other tasks or exchange . The MessageBox basically provides two functions: put and get. When a new message is created, memory is allocated. Similarly, the memory is freed when retrieved from the box.

The Timer Object

Similar to any standard timer in other system, this object is used to create timeouts and schedules of tasks and events.

The Event Object

Events are created by tasks and ISRs to schedule other tasks.

The Device Object

This item abstracts interaction between the user application and the hardware device. It does so by pointing to the memory blocks used by the device and managing input/output to the area.

The List, Queue and Buffer Objects

These objects, as their name implies, are implementation of a linked list, a queue and buffer data structures.

Features

Byte-BOS boasted the following additional features on their website from 2000, providing some extra insight on the internals of the system.

Interrupt Handling

ISRs can make operating systems calls and schedule tasks by including the ENTER_ISR and EXIT_ISR macros at the beginning and end of the routine. Most services are available to ISRs, giving them considerable access over the entire OS.

Critical Section Handling

Byte-BOS provides critical section handling by protecting non-reentrant code sections from both interrupt and task pre-emption. Protection of critical sections appears to be done via the following mechanisms:

  • Disabling interrupts
  • Locking and unlocking code sections
  • Prioritization of tasks

Task Execution Trace

Tasks are provided with a trace buffer configurable at both compile time and run time. The trace buffer contains information about the sequence of calls, the parameters passed, and the return value of the called function. The tracing option is extremely useful for debugging purposes.

System Requirements

The Byte-BOS RTMOS requires very little in terms of resources. While the requirements varies depending on the underlying processor, the size of the kernel is a few kilobytes, while the RAM requirements are less than 100 bytes of globally accessible memory and less than 100 bytes per task and ISR. The detail figures are listed in table 2.

Table 2 – Memory requirements for the Byte-BOS RTMOS according to microprocessor
Microprocessor Minimum Kernel
Size (KB)
Maximum Kernel
Size (KB)
RAM Requirement
for Global Variables
(bytes)
RAM Requirement
per Task (bytes)
Intel 80×86* 4 10 28 30
Intel 80×86
(32bit)*
6 15 48 58
Intel 80188/86* 2 10 28 30
Intel 8096 2 8 20 20
Motorola 68000 1.5 12 50 70
Motorola 68HC11 1.2 8 28 20
Motorola 68HC16 2 8 28 20
Mitsubishi M37700 2 10 28 20
Mitsubishi M16C 2 12 64 48
Mitsubishi M32D N/A N/A N/A N/A
Hitachi H8300 1.2 8 28 20
Hitachi H8300H 2 10 38 40
Hitachi SHX 7.8 19.5 72 60
Texas Instruments
C2x/C5x DSP
1.2 8 28 20
Texas Instruments
C3x/C4x DSP
2.3 19.5 28 words 20 words
ARM/THUMB 4 15 50  70

* For Intel-based architecture, the memory footprint reported above is based on usage of the Borland C++ compiler.

Additional volatile memory is required for objects created dynamically. As such, the numbers provided above do not represent the total amount of memory consumed by Byte-BOS.

Compilers Supported

In general, Byte-BOS supports the development tools and compilers provided by the semi-conductor manufacturer. For Intel-based processors, the Borland C/C++ compiler was supported. The complete list of supported compilers is provided in table 3.

Table 3 – Supported compilers by the Byte-BOS RTMOS.
Microprocessor Supported Compilers
Intel 80×86 Microsoft C/C++ (large model)
Borland C/C++
Watcom C/C++
Intel 80×86(32bit) Watcom, Metaware and most of C compilers
Intel 80188/86 Microsoft C/C++ (large model)
Borland C/C++
Intel 8096 IAR
BSO Tasking Compiler
Motorola 68000 Cross-Code
Intermetrics
Introl
Microtec
Motorola 68HC11 IAR
Introl
Cosmic
Motorola 68HC16 Introl
Cosmic
Mitsubishi M37700 IAR
Microtec
Mitsubishi M16C IAR
Mitsubishi Compiler
Mitsubishi M32D N/A
Hitachi H8300 IAR
Microtec
Hitachi H8300H IAR
Hitachi SHX GNU
Green Hills
Texas Instruments
C2x/C5x DSP
Code Composer /
Texas Instrument Compiler
Texas Instruments
C3x/C4x DSP
Code Composer /
Texas Instrument Compiler
ARM/THUMB  ARM

Identification

Devices using the Byte-BOS RTMOS can be identified by looking at ASCII and Unicode strings in their firmware. In almost all cases, if not all, the firmware will contain a copyright notice identifying it as well as the target microcontroller it was compiled for. For example, by extracting the strings from the firmware for the Seagate Cheetah 10K.6 Disc Drive, either using the simple strings.exe (or strings in Linux) or IDA, the copyright notice string “Byte-BOS 8096 Multitasking Operating System — Copyright 1990 Numerical Services Inc.” can be observed (see figure 2).

Byte-BOS Copyright Notice into the Firmware of the Seagate 10K.6 Disc Drive
Figure 2 – Byte-BOS Copyright Notice into the Firmware of the Seagate 10K.6 Disc Drive

While appliances posterior to 2004 will likely use modern RTMOS such as Linux , Byte-BOS can still be found on legacy devices. One such example is the Baxter IPump pain management medical device, which refers to its usage in the manual [2]. Of note, the manual refers to the detection of stack overflows within the Byte-BOS RTMOS. Industrial controls, aircraft, telecommunications systems and other systems designed prior to the 2000s may still harbour this little known RTMOS.

Conclusion

The Byte-BOS RTMOS will likely disappear as legacy embedded devices are life-cycled for newer systems with more processing power and extended memory. Until that moment, for developers of these systems, or simple hobbyists, information remains scarce and limited. While we provided a brief overview of its architecture and features, details about creating user applications remains obscured by the lack of online information such as an API description, code examples or more importantly, the source code. Such data would greatly ease development and engineering efforts of legacy systems.

References

[1] “Bytebos Home Page.” Bytebos Home Page. Internet Archive, 20 Oct. 2000. Web. 01 Nov. 2015. <https://web.archive.org/web/19990208011926/http://www.bytebos.com/>.

[2] Baxter IPump Pain Management System – Service Manual, Baxter Healthcare Corporation, Chapter 4 – Troubleshooting, p.4-8. 2007. Web. 01 Nov. 2015. <Link>