Rick Ramgattie's InfoSec Adventures

| Posts | About |

Getting a Shell Through SD Card Updates

Published Date: 2020-03-30

In the last blog, we continued our journey to getting a shell on the eWeLink FGHGF VG-IC-01 IP Camera. We took apart the firmware that was extracted through UBoot, reverse engineered the update process, and downloaded an official copy of the firmware.

In this blog, we are going to figure out how we can leverage the firmware to further our access and gain more insight on what the device looks like when it is up and running. If you want to follow along you can download the files for this blog by clicking on the link below.

Download Files for This Walkthrough

Analyzing the Official Firmware

The first thing we will need to do is get the files out of the official firmware we downloaded. If we run the "file" command on the file we will see that it is a Zip file. Let's "unzip" it to see what it contains.

››› file V1522.2.247build20191105.zip V1522.2.247build20191105.zip: Zip archive data, at least v2.0 to extract
Figure 1. The Firmware is Distributed as a Zip file
››› unzip V1522.2.247build20191105.zip Archive: V1522.2.247build20191105.zip inflating: ServicePacks.ini extracting: ServicePacks.zip
Figure 2. Unzip the Archive to Extract it's Contents.

In "ServicePacks.ini" there is an author name and some integrity checking strings (MD5 and CRC). There is nothing all that interesting.

Unzipping "ServicePacks.zip" produces a "var" directory that contains more directories in it, all of which are empty except for "var/user/". The "file" command says that "app.bin" is a "SquashFS" filesystem.

››› unzip ServicePacks.zip Archive: ServicePacks.zip creating: var/ creating: var/rootfs/ creating: var/kernel/ creating: var/user/ inflating: var/user/app.bin
Figure 3. ServicePacks.zip Contains the System Files Used During the Firmware Upgrade Process.
››› file app.bin app.bin: Squashfs filesystem, little endian, version 4.0, 2448314 bytes, 118 inodes, blocksize: 131072 bytes, created: Tue Nov 5 06:50:02 2019
Figure 4. App.bin is a SquashFS Filesystem

Instead of mounting the filesystem manually, Binwalk will automatically do it for you when provided with the "-e" flag. The '_app.bin.extracted' that was created contains all of the contents that will be mounted on to the device during the upgrade process.

››› binwalk -e app.bin

DECIMAL HEXADECIMAL DESCRIPTION 0 0x0 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 2448314 bytes, 118 inodes, blocksize: 131072 bytes, created: 2019-11-05 06:50:02
Figure 5. Binwalk can Automatically Mount and Extract SquashFS Filesystems.
››› cd _app.bin.extracted ››› ls 0.squashfs squashfs-root ››› cd squashfs-root ››› ls AVRecSch av.xml colinkwtg.sh lib AVRecorder avencode dbback res AlarmServer captive_server devctrl rtspd App.sh cfg drive script IOTCare colink factorytest sd ProcessGuard colink.sh font version
Figure 5. Files Loaded Onto The Device.

The files that were extracted look the same as the ones that we found in "squashfs-root-0" in the previous blog. This made me think about the bootup process. As we learned in that blog, there is another group of binaries that run when the device boots up. These binaries were in "squashfs-root" when we unpacked the firmware in the previous blog.

››› ls previous_blog/squashfs-root-0 AVRecSch av.xml colinkwtg.sh lib AVRecorder avencode dbback res AlarmServer captive_server devctrl rtspd App.sh cfg drive script IOTCare colink factorytest sd ProcessGuard colink.sh font version
Figure 6.squashfs-root-0 From The Previous Blog and squashfs-root From This Blog Have The Same Structure.
››› ls previous_blog/squashfs-root bin gm proc sys boot.sh init sbin tmp dev lib sd_upgrade.sh udhcpc etc linuxrc share usr filesystemversion mnt squashfs_init var
Figure 7. The Files in squashfs-root From The Previous Blog Run During the Bootup Process.

There are a couple files in that "squashfs-root" folder that look very important. There might be details about what accounts and secrets are created every time the device boots up, or there might be some remote administration functionality that was baked in by the manufacturer. We should look at the files in this directory first since they are the ones that are evaluated first when the device boots up.

Reviewing the boot process

Although there isn’t a lot interesting going on in "boot.sh", there are calls to other scripts and binaries on lines 14-18.

Figure 8. There Are 4 Other Scripts and Binaries That Are Called When boot.sh is Called.

The first script called is "sd_upgrade.sh". This is a huge script, you can check out the gist I created for it here. The first thing that popped out to me about this script is the number of "if" statements.

There are two "if" statements at the end of the script that stuck out to me the most. In the second to last 'if' (on line 89) it checks for a file called "app.bin". Then, there is a check for a file named "after_upgrade.sh". If "app.bin" exists, it calls a "flashcp" script that writes the "app.bin" file from the SD Card to "/dev/mtd4" and then sets the "bUpgrade" flag to "1".

We have a copy of "app.bin" from when we extracted reverse engineered the official firmware image above. We might be able to unpack "app.bin", edit it, and repack it so that it runs commands we provide whenever the device is turned on.

From SD Card to Shell

With our end goal of furthering our access in mind, we need to figure out how we can get shell access to this device by running commands. When I hear "network services that provide shell access" I think "telnet". If we set up a "telnetd" listener on the device we should be able to connect to it when it boots up.

As we learned in the previous blog, there is a shell script called "App.sh" that is called every time the device boots up. After editing that script to include the line provided below, I repacked "app.bin" with mksquashfs, copied it onto the SD Card, and booted the device. After the device was fully booted I connected to it with netcat as was greeted by a "#" and a telnet shell.

telnetd -l $(which sh) -p 1234
Figure 9. Automatically Evaluate All Messages Sent Over an Established Connection.
mksquashfs /squashfs-root app.bin
Figure 10. Edit "App.sh", Repackage "app.bin" and Copy Onto The SD Card.
nc <device ip> 1234
Figure 11. Connecting to telnetd Will Grant You Root Shell Access.


We were able to take what we learned from the official firmware image to get a full shell on the device through it's "SD Card Upgrade" functionality. Although this is a full root shell, it is important to remember that this isn't necessarily a vulnerability. We had physical access to the device and used that physical access to escalate our access. I wanted to truly own my device, this isn’t supposed to be geared towards exploiting other user devices on the Internet.

One of the details I glossed over was the value of the firmware that I extracted from UBoot in the first blog. It helped me understand the architecture of the device once the firmware was already written and the device was fully booted.

This blog wraps up my adventures with the eWelink Camera. It was a very lengthy and tricky journey that started with some debug pins and ended with a full root shell. I learned about hardware electronics, embedded device hacking tooling, and binary reverse engineering tooling. I recommend similar projects to anyone in application security (or anyone for that matter) that wants to get a feeling for auditing the security of embedded devices. If there is anything that you would like clarification on, please check out the “About” tab above and feel free to hit me up.