Adventures with a cheap webcam from Amazon
I week ago I decided to pickup a couple cheapo webcams from Amazon and see if I could do a security assessment on the products. Once they arrived I decided to first dive into the Galayou G7 camera. I hope this post serves as a good primer into IoT security assessments and hardware hacking. While I have not completed all the work I intend to, I was able to get started with recon and gaining access to the system itself. I will likely create follow up posts diving deeper into the system as I learn more.
Reconnaissance
First thing first, we can see the potential attack surfaces of the device. This includes a couple hardware interfaces, such as USB and an micro SD card slot. Being a wireless webcam we can safely assume there is WiFi on the system as well. Additionally, the box shows that there is some kind of smart phone app integration. The next step is to open the case and get our eyes on the board.
Cracking the case
Using a spudger along the edge of the black faceplate around the camera allowed us to remove the front from the shell and remove the internals. There were a few connectors plugged into the board, these correspond to the indicator LED, microphone, speaker, and the camera itself. Removing the first three allowed us to separate the main board from the faceplate.
On the front side we can see a few ICs and the reset button as well. On the reverse is the USB-C header, SD Card slot, the main CPU, and a couple more ICs. The main SoC in this system is an Ingenic T31. Next to this chip is a Winbond W25Q32JV a 32-Megabit SPI Flash IC. This NOR Flash chip is likely contains the bootloader and OS for the camera. At this point I have no idea what kind of system it is running, either some form of Linux, custom firmware, or some RTOS. Luckily, next to these two chips are 3 test points labeled: Tx, Rx, and GND.
The test pins almost certainly represent a UART serial port. Many times these pads are not so nicely labeled. But since they are in this case I set off to connect a serial adapter so I could see if any data is sent during the boot process. I set the board up with my PC Bite to connect to the pads and ran the wires back to a FTDI FT232RL and connected it up to my PC.
This worked better than I had imagined. Upon powering up the board with USB-C, I was greeted with all kinds of information about the system during its boot process. The bootloader appears to be U-Boot, it also confirmed our thoughts about the type of SoC and the SPI Flash. We also now know that it is booting a Linux enironment running Kernel 3.10.14.
image entry point: 0x80100000
U-Boot 2013.07 (May 19 2022 - 13:47:10)
Board: ISVP (Ingenic XBurst T31 SoC)
DRAM: 64 MiB
Top of RAM usable for U-Boot at: 84000000
Reserving 479k for U-Boot at: 83f88000
Reserving 32784k for malloc() at: 81f84000
Reserving 32 Bytes for Board Info at: 81f83fe0
Reserving 124 Bytes for Global Data at: 81f83f64
Reserving 128k for boot params() at: 81f63f64
Stack Pointer at: 81f63f48
Now running in RAM - U-Boot at: 83f88000
MMC: msc: 0
the manufacturer ef
SF: Detected W25Q64
In: serial
Out: serial
Err: serial
Net: ====>PHY not found!Jz4775-9161
Hit any key to stop autoboot: 1 0
the manufacturer ef
SF: Detected W25Q64
--->probe spend 4 ms
otabakpaddr:0x0
Card did not respond to voltage select!
gvsdupdate - just run
Usage:
gvsdupdate please just run
the manufacturer ef
SF: Detected W25Q64
--->probe spend 4 ms
SF: 1835008 bytes @ 0x40000 Read: OK
--->read spend 590 ms
## Booting kernel from Legacy Image at 80600000 ...
Image Name: Linux-3.10.14__isvp_swan_1.0__
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 1671232 Bytes = 1.6 MiB
Load Address: 80010000
Entry Point: 80415290
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
Starting kernel ...
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Initializing cgroup subsys cpuacct
[ 0.000000] Linux version 3.10.14__isvp_swan_1.0__ (spock@spock-PC) (gcc version 4.7.2 (Ingenic r2.3.3 2016.12) ) #6 PREEMPT Fri May 27 14:39:39 CST 2022
[ 0.000000] bootconsole [early0] enabled
[ 0.000000] CPU0 RESET ERROR PC:401C001D
[ 0.000000] CPU0 revision is: 00d00100 (Ingenic Xburst)
[ 0.000000] FPU revision is: 00b70000
[ 0.000000] CCLK:1104MHz L2CLK:552Mhz H0CLK:250MHz H2CLK:250Mhz PCLK:125Mhz
[ 0.000000] Determined physical RAM map:
[ 0.000000] memory: 004ce000 @ 00010000 (usable)
[ 0.000000] memory: 00042000 @ 004de000 (usable after init)
This log also provided me information about the structure of the data on the SPI flash. In the code snippet below we can see the various partitions that will be created when to divide up the Flash memory when the system is booted. This will be useful later when assessing the contents of the flash.
0.349144] JZ SFC Controller for SFC channel 0 driver register
[ 0.355308] 5 cmdlinepart partitions found on MTD device jz_sfc
[ 0.361425] Creating 5 MTD partitions on "jz_sfc":
[ 0.366392] 0x000000000000-0x000000040000 : "uboot"
[ 0.371898] 0x000000040000-0x000000200000 : "kernel"
[ 0.377502] 0x000000200000-0x0000002f0000 : "rootfs"
[ 0.383119] 0x0000002f0000-0x0000007a0000 : "app"
[ 0.388428] 0x0000007a0000-0x000000800000 : "config"
[ 0.394061] SPI NOR MTD LOAD OK
Finally when the system fully booted, I pressed enter to see if I would have a command prompt. Unfortunately, I was met with a login and could not easily guess the password. Time to get creative and look for another way in.
Dumping the Flash
We know a lot about the system now just by booting it up one time. We weren’t about to get into the OS but if we can get our hands on the firmware images and filesystem then maybe we can alter the software or extract the password. To do this we will need the data sheet for the Winbond chip. This is easily located with a quick search for W25Q32JV. The data sheet provides us with the pinout used to communicate with the flash memory.
To use this diagram you need to locate the small divot on the top of the flash IC so you know the correct pin order. Then we need to wire up the various pins to a BusPirate which we can use with the flashrom utility to dump the contents to a file. We will need to connect all off the pins with the exception of WP and HOLD/RESET. On the other end we will connect these to the corresponding pins on the BusPirate itself.
Chip Select (CS) activates the IC for communications, CLK provides the common clock signal for the communication bus, MISO stands for Master In, Slave Out and should be wired to Data Out (DO) on the IC, MOSI is the opposite and should be wired to the DI pin on the SOIC. Finally, the Vcc should be connected to the 3v3 pin and GND to GND. This should be enough for us to begin to interface with the chip itself. Since I only have 4 PC Bite test leads, I also utilized clips on a couple of the pins.
Unfortunately, when I ran flashrom to probe for the chip nothing was located. The issue is because the 3.3V the BusPirate is applying to the Flash is also powering the SoC which is interfering with our communications. To the left of the SoC in the picture above you can see the Oscillator. To solve the issue I actually shorted the capacitor between the oscillator and the SoC to ground (the purple wire in the foreground). Once I did that, flashrom was able to recognize the chip and dump the flash.
Examining the Filesystem
Now we have the filesystem from the SPI Flash in an image on our computer for testing. The first thing I did here is use binwalk to see if it could recognize any of the contents. Luckily, we also had the MTD structure in the boot log from earlier. In this case, binwalk found all the pieces we were looking for and automatically extracted them all. In the following screenshot you can see how nicely these elements line up with the MTD partitions listed before.
We can see the the header for the U-boot bootloader image. At 0x40000 binwalk found the Linux kernel. Then at 0x200000 is the squashfs partition which we know is named “rootfs”, followed by “app” at 0x2F0000 and “config” at 0x7A0000. Binwalk happily extracted the rootfs image and unsquashed it for us.
I started to dig into this filesystem looking to get my bearing on the system. This included examining the various boot scripts and checking config files for clues as to what is running on the system, as well as looking at available binaries. But our main goal right now is to gain access to the system. I did see in an init RC file the getty command for starting the UART shell. I figured I could add the auto login flag with the root user to circumvent the password protection entirely. However, I ended up using the old tried and true method of replacing the password hash.
Looking in the passwd file I could see that the only user was root. Looking in the shadow file I could see that the root account password was hashed with md5crypt. Next I used the mkpasswd utility locally to generate a new password based on the word “password”. With the new password hash generated I made a backup of the unsquashed filesystem and edited the shadow file placing my new hash in it.
I also extracted the old hash and tried to crack it with hashcat to no avail. With the shadow file updated, I used the mksquashfs tool to compress this filesystem back into a compressed image. The blocksize and compression type options were chosen to match the original image.
Now came the tricky part for me. I didn’t know how rebuild the original flash image extracted from the chip. I don’t know if there is a utility to do this or if it is specific to the SoC or flash storage or what. Finally, what I discovered is that I could use dd to overwrite just certain bytes of a file without altering the rest of the image. Of course, this wouldn’t work if there was any kind of hashes or integrity checks in the other portions of the boot. To just overwrite a portion of a file with dd you need to use the “conv=notrunc” and “seek” options. Because the new squashfs image is longer than the old one I didn’t need to clean up any bytes after the image.
With a new firmware image created, I tried my luck with flashing it back to the camera. This was accomplished via the same method used to dump the image originally.
Moment of truth
With the new image flashed it was time to move our test pins back to the UART header and test the system by booting it.
Success!
Next Steps
Now that I have access to the system I can begin to assess the OS running there. I have started to pair it with the app and I started the telnet daemon so I could access the device remotely without having to jump to my test box with the UART adapter. When I make configuration changes in the app I can see log messages related to them.
My goal next is to try and capture the packets coming into see if I can reverse any of this communications. I have also started to disassemble some of the binaries related to the custom functions this system runs. The device also used the camera to read a QR code when connecting to Wi-Fi for the first time so there is some sort of functionality there that may be interesting to explore. Finally, the Android app itself can be examined further to see its functionality.
I hope to continue with this investigation and will make future posts with any updates.