Hacking into a Foscam FI9853EP camera, part 1

I have a Foscam FI9853EP, which was introduced in 2014 and has long since been obsoleted. One of the things that stands out, is that all firmware is encrypted:

$ file FosIPC_B_patch_ver2.x.2.31_3_20190718_150013.bin 
FosIPC_B_patch_ver2.x.2.31_3_20190718_150013.bin: openssl enc'd data with salted password

I was curious: what could be in the firmware that needs this amount of protection? Usually, firmwares are plaintext but signed so that you can’t installed any unauthorized software in your device.

My end goal is to be able to decrypt the most recent (2019) firmware. But I’m not there yet.

Finding an UART

There is a lot of information available on how to locate a serial port on the device so you can interact with it. You tend to be looking for a 3-pin or 4-pin header. On the Foscam, there is a 4-pin header close to the ESD warning symbol on the board.

The picture below shows where the header is located. I soldered the second wire using the other side of the board:

Counting pins from left to right, we have:

  • Pin 1 = TX
  • Pin 2 = GND
  • Pin 3 = RX
  • Pin 4 = ?

Using a FTDI I had lying around and the standard 115200/8N1 settings, we have a console!

U-Boot, or not yet

It turns out the system uses standard U-Boot. However, there is a catch:

System startup

U-Boot 2010.06 (Nov 16 2017 - 11:43:05)

Check Flash Memory Controller v100 ... Found
SPI Nor(cs 0) ID: 0xc2 0x20 0x18
##uboot 020sdk patch!##
Block:64KB Chip:16MB Name:"MX25L128XX"
SPI Nor total size: 16MB
MMC:   
EMMC/MMC/SD controller initialization.
Card did not respond to voltage select!
No EMMC/MMC/SD device found !
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Hisilicon ETH net controler
init rmii phy led completed
Hit any key to stop autoboot:  1 
1st input Passwd:

There is a password protection mechanism in place: whenever you interrupt the boot process, it asks for a password that we don’t have.

Where is the firmware stored and how do we get to it?

If you take a closer look at the picture above, you’ll spot a 8-pin SOIC chip to the right. This chip is a MX25L12835F, which is a 128MBit SPI NOR flash memory IC. This is also what the boot log mentions right before we stop it. This chip will likely contain the firmware.

It would be possible to desolder the IC, dump its content and solder it back. This felt like a lot of work, and I like to avoid soldering if I can help it, since we already have a device that can interact with the IC: the device itself. But to dump the contents of the IC, we either need access from Linux or from U-Boot. The latter is easiest, but we still have that pesky password prompt…

Getting U-Boot shell, the easy way

I had an idea: if I could somehow stop the boot process, it will likely just error out and give me a prompt. To this end, I tried shorting pins 5 (SI) and 6 (SCLK) of the flash memory chip with a screwdriver while I powered the device on. Sometimes I was too quick and U-Boot wouldn’t start at all, and usually I was too late and the kernel was already loaded. However, after a few tries, success!

Wrong Image Format for bootm command
ERROR: can't get kernel image!
hisilicon # 

Since I stopped shorting the pins, I can interact with the flash IC now and inspect its contents:

hisilicon # sf probe 0
16384 KiB hi_fmc at 0:0 is now current device
hisilicon # sf read
Usage: sf read addr offset len
hisilicon # sf read 0x82000000 0 0x10000
hisilicon # md.b 0x82000000 0x10000
82000000: 17 04 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5    ................
...

Dumping the flash

The approach above with the md.b command works, but it’s very slow. I really did not fancy dumping 16MB this way. There is an ethernet port on the device. Let’s see if we can use it:

hisilicon # setenv serverip 192.168.1.1
hisilicon # setenv ipaddr 192.168.1.2
hisilicon # ping 192.168.1.1
MAC:   00-00-23-34-45-66
eth0 : phy status change : LINK=DOWN : DUPLEX=FULL : SPEED=100M
eth0 : phy status change : LINK=UP : DUPLEX=FULL : SPEED=100M
host 192.168.1.1 is alive

Hooray! The U-Boot is also built with TFTP upload and download capabilities. I decided to dump the flash in 4 parts, as I was getting TFTP errors if I tried to do it in one go and I could easily retransfer the problematic pieces this way.

hisilicon # sf read 82000000 0 400000
hisilicon # tftp 82000000 flash0 400000
hisilicon # sf read 82000000 400000 400000
hisilicon # tftp 82000000 flash400000 400000
hisilicon # sf read 82000000 800000 400000
hisilicon # tftp 82000000 flash800000 400000
hisilicon # sf read 82000000 c00000 400000
hisilicon # tftp 82000000 flashc00000 400000

I can re-combine the flash by just concatenating the flash files together:

$ cat flash0 flash400000 flash800000 flashc00000 > flash.bin

Making sense of the flash

I wanted to split the 16MB flash image up, as it isn’t used as a single blob. Allowing the device to boot and looking at the bootlog revealed the flash layout:

Creating 5 MTD partitions on "hi_sfc":
0x000000000000-0x000000080000 : "boot"
0x000000080000-0x000000380000 : "kernel"
0x000000380000-0x000000e80000 : "app"
0x000000e80000-0x000000f80000 : "app_ext"
0x000000f80000-0x000001000000 : "para"

So we can split it using the following commands:

$ dd if=flash.bin of=boot.mtd ibs=1 skip=0 count=524288
$ dd if=flash.bin of=kernel.mtd ibs=1 skip=524288 count=3145728
$ dd if=flash.bin of=app.mtd ibs=1 skip=3670016 count=11534336
$ dd if=flash.bin of=app_ext.mtd ibs=1 skip=15204352 count=1048576
$ dd if=flash.bin of=para.mtd ibs=1 skip=16252928 count=524288

Let’s see if the resulting images make any sense:

$ file *.mtd
app_ext.mtd: Linux jffs2 filesystem data little endian
app.mtd:     Squashfs filesystem, little endian, version 4.0, xz compressed, 11298912 bytes, 462 inodes, blocksize: 131072 bytes, created: Thu Nov 16 07:51:11 2017
boot.mtd:    data
kernel.mtd:  u-boot legacy uImage, Linux-3.4.35, Linux/ARM, OS Kernel Image (Not compressed), 2976536 bytes, Tue Nov  7 02:41:11 2017, Load Address: 0X80008000, Entry Point: 0X80008000, Header CRC: 0XAF395D8A, Data CRC: 0X36BDB2E2
para.mtd: Linux jffs2 filesystem data little endian

Learning the U-Boot password

The boot.mtd is just a binary data blog, which means it likely contains the bootloader as-is. I decided to look at the strings within to see if there is anything worthwhile, and indeed:

$ strings boot.mtd
[...]
Hit any key to stop autoboot: %2d 
%dst input Passwd:
ipc.fos~
%2d 
[...]

After the 1st input Passwd: we find the string ipc.fos~ ! I decided to try it, and this is indeed the U-Boot password. I no longer have to mess with the pins to get a prompt, and I have the current (factory) firmware of the device.

Next step: extracting data from the images

This post is already long enough, so I’ll leave it at that. However, I plan om extract the images to figure out how the device boots, updates and hopefully learn a thing or two on how to proceed. Stay tuned!

This entry was posted in Reverse engineering and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *