I’ve been watching you.. a lalala long – Reverse Engineering IP cameras (Part 1)

The Foscam FI9816P is a wireless Internet Protocol (IP) camera commonly employed for surveillance and it can send and receive data via a computer network and the Internet. This particular model costs around $70 USD and can help you, according to Foscam, keep an eye on what matters most (a lalalala long).

There are numerous Foscam models out there with critical security vulnerabilities; so, Tasos had the idea to order the new FI19816P model and check if this is the case. The goals of this side project is to undestand how IP cameras work, find bugs and exploit them to get internal access, and dump and backdoor the firmware. In order to achieve all these, the first step is to teardown the camera and look for a serial port. Serial ports are typically used by the embedded system developers for debugging and various other technical support purposes. Access to the serial port interface can allow us to observe the booting process, access the bootloader, check debug messages, and ultimately interact via a shell with the system.

Identifying the serial headers

Most serial port headers have between 4-6 pins (typically 4):

  • Vcc (3.3 V)
  • Ground (GND)
  • Transmit (TXD)
  • Receive (RXD)

Since the UART port is not designed to be utilized by the end users it almost never has pins or connectors attached. After taking a quick look at the board of FI9816P, 3 sets of unused pads call our attention.



Time to get out the multimeter.

Pad 2 (J6) is unlikely to be the UART console. All 4 pins indicate 0 V (metal shielding is a convenient ground point to use for testing). Pad 3 has half of its pins to ground, and half to 5 V. It is also unlikely to be the serial port: the 5 V pins are not steady to 5 V indicating that none of them is Vcc (also, most Foscam models have 3.3 V as the Vcc pin). On the other hand, pad 1 (J5) has a grounded pin and the other pins around 3.3 V (time for a short celebration).

In order to verify that pad 1 is the UART port, JTAGulator  can help us identify the pinout.  JTAGulator is a hardware tool  that can assist in identifying on-chip debug interfaces like JTAG and UART. A logic analyzer, an oscilloscope, or even the variations of the multimeter can also help identify the pins.

Once we have connect the JTAGulator to pad 1 (GND to GND, and the other 3 pins to channels 8-10 of JTAGulator), we set the target system voltage to 3.3 V and issue the :u command to identify the UART pinout.


The JTAgulator permutation results reveal that channel 9 of JTAGulator is connected to TXD and channel 8 to RXD. Among these results, only the 115200 bits per second baudrate returns the 0D hexadecimal ASCII representation of Carriage Return (CR).



The 115200 b/s baudrate is also verified with baudrate.py, a python script that attempts to auto detect the baud rate of an actively transmitting serial port.

Connecting to serial port


Once we have both the pinout and baudrate, we are ready to start communicating with the device. In contrast with pad 2 and 3, we cannot attach headers to the serial port – pad 1 (J5). Therefore, we need to solder the J5 pinout connection.


To verify the correctness of the soldering we use JTAGulator one more time.



Now that we’ve got the hardware setup ready, it’s time to talk to the device. To achieve that, any UART to USB bridge would do the job. We used the 3.3 V C232HD USB – UART cable. In this part, it is important to connect the TXD and RXD pins of the device to RXD and TXD of the UART – USB bridge respectively.


Serial terminal

We are ready to open a serial terminal in our computer and communicate with the IP camera (any serial communication program would do, e.g. screen, minicom, putty, etc.). The video below presents how UART spits out information during the booting of the device.

Hitting any key during the booting process it allows to interrupt the bootloading and get (presumably) a shell after typing the correct password.


Getting the password

A way to get the password is to disassemble the firmware of the FI9816P camera and check if it resides over there. Unfortunately, the firmware of this particular camera model is openssl-encrypted.


Next steps

In order to decrypt the file, both the cipher and the password must be known. So, it seems that the firmware path is a dead end.

If anybody has any ideas how to get the password and thus shell access on the device, it would be greatly appreciated. If not, I am sure we will find a way with Tasos.



IDA plugins and scripts

A collection of IDA plugins and scripts can be found in the following places:

  • OpenRCE: a collection of about 80 plugins.
  • devttys0: several IDA plugins and scripts from Craig Heffner.
  • PatchDiff2:  IDA plugin that can analyze two IDB files and find the differences between both.
  • RebuildFunctions: rebuild functions and fix the disassemble code in IDA (kudos to Santamarta).
  • bniemczyk: a collection of reversing tools for IDA.
  • tuts4you:  several plugins from tuts 4 you community.
  • flare-ida: IDA utilities from FLARE team.
  • newgre: three IDA plugins from newgre.net
  • IDApalace: plugins from old.idapalace.net
  • IDA ClassInformer: IDA plugin to fix/extract/view RTTI information.
  • IDAPython: IDA plugin that integrates Python, allowing scripts to run in IDA Pro.
  • Diaphora: a program diffing plugin for, at the moment, IDA Pro.
  • idapathfinder: an IDA plugin to graph all paths between two functions.
  • IDAScript: a wrapper around IDA that makes it easy to automate the execution of IDA scripts against target files from the command line.
  • Hex-Rays: sample plugins from IDA official website. Useful information can be found at the hexblog as well.
  • IDACyber: a plugin for the Interactive Disassembler which is capable of visualizing the currently loaded IDB’s data (useful for identifying structures and patterns of binary blobs where extended information such as a header is not available).
  • HeapViewer: An IDA Pro plugin to examine the heap, focused on exploit development.

Disassemble firmware completely (rebuild functions in IDA)

The first steps after acquiring the firmware of an embedded system are mainly to:

  1. determine the processor of the device,
  2. disassemble the firmware image,
  3. reconstruct the firmware: rebuild functions, determine the base address, collect information from strings, rebuild symbols etc.

Regarding the processor identification, there is Skochinsky’s presentation which is actually amazing. For disassembling the binary image there is IDA. In order to proper reconstruct the firmware however, several techniques must be applied on the file. For example, one must determine the base address of the firmware i.e. the starting location of the firmware in order to have accurate interpretations of segments referenced by immediate addresses. The “load technique” is usually used for this step, given that there exist immediate address references in the disassembly. We will talk in future tutorials about this technique.

Today, we will present a simple trick how to rebuild functions and thus fix the disassemble code in IDA. The script below (kudos to Santamarta) simply instructs IDA to explore the remaining unexplored functions in the firmware. The example firmware in our case is based on ARM ISA. In addition, the prologue signature of the already IDA automatically identified functions is a STMFD instruction that pushes the current register values to the stack. The registers pushed to the stack are different between each STMFD instruction but the two most significant bytes of the instruction remain the same (“E9 2D”). This is verified also from the ARM instruction encoding standard. Hence, by editing Santamarta’s script to target this signature (+corrected for endianness), the script is applied to the loaded in IDA firmware. Consequently, a significant part of the firmware binary image is explored since more functions are identified.

/* Ruben Santamarta www.reversemode.com */
/* Fix functions - Schneider NOE 110 firmware */
/* Edited by Harrys Kon Feb. 2015*/
/* FixARMfunctions.idc*/
#include <idc.idc>
static main() {
 auto ae;
 auto funct;
 auto minea;
 auto prolog;
 auto j;
 auto fun_array;
 minea = MinEA();
 fun_array = CreateArray("ProGos");
 if (fun_array == -1) 
   fun_array = GetArrayId("ProGos");
 SetArrayString(fun_array,0,"2D E9"); 
 for (j=0;j<1;j++){
   ae = minea;
   prolog = GetArrayElement(AR_STR,fun_array,j);
   while (1) {
     funct = FindBinary ( ae, SEARCH_DOWN, prolog); 
     if (funct == BADADDR )
     funct = funct - 2;
     MakeCode (funct);
     MakeFunction (funct, BADADDR); 
     ae = funct + 4;