Skip to content

Instantly share code, notes, and snippets.

@faust93
Last active January 14, 2024 14:12
Show Gist options
  • Save faust93/8f857b2bc3f94b79ba1a275f8ed630a9 to your computer and use it in GitHub Desktop.
Save faust93/8f857b2bc3f94b79ba1a275f8ed630a9 to your computer and use it in GitHub Desktop.
ICAM-WRHD-02 Hack

Reversing WRHD-02 IP Camera

Recently bought cheap "Gembird ICAM-WRHD-02" IP camera to watch over my parrots while being away from home. https://gembird.com/item.aspx?id=11674

Seems it just works OOB but my curiosity of course made me to discover a bit more about the camera :) So after disassembling it I found it to be a generic IPC built on ANYKA AK3918 SOC flashed with Yoosee firmware It has 3 external WIFI antennas but after disassembling it turned out that 2 of these are just decorative and not connected to the WIFI PHY

Looking Deeper

Quickly looked over the pins on the main board for JTAG but found nothing so decided just to dump the whole flash My camera exemplar has XMC QH64AHIG chip. Though flashrom knows nothing about that chip I was able to use CH341A SPI programmer to read/write it successfully.

So let's look inside:

Dumping flash:

sudo flashrom -p ch341a_spi -r rom.img
Found Unknown flash chip "SFDP-capable chip" (8192 kB, SPI) on ch341a_spi.
Reading flash...
Reading flash... done.

Running binwalk to see flash layout:

binwalk rom.img

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
131204        0x20084         CRC32 polynomial table, little endian
229376        0x38000         uImage header, header size: 64 bytes, header CRC: 0x53E31A68, created: 2020-08-04 09:29:45, image size: 1515312 bytes, Data Address: 0x82208000, Entry Point: 0x82208040, data CRC: 0x868DE94F, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linux-3.4.35"
229440        0x38040         Linux kernel ARM boot executable zImage (little-endian)
243295        0x3B65F         xz compressed data
243516        0x3B73C         xz compressed data
1810432       0x1BA000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 931284 bytes, 356 inodes, blocksize: 131072 bytes, created: 2020-08-10 08:07:12
2859008       0x2BA000        JFFS2 filesystem, little endian
2863648       0x2BB220        Unix path: /var/run/udhcpd.pid
2863715       0x2BB263        Unix path: /var/lib/misc/udhcpd.leases
2867200       0x2BC000        JFFS2 filesystem, little endian
2930264       0x2CB658        JFFS2 filesystem, little endian
3118628       0x2F9624        JFFS2 filesystem, little endian
3124712       0x2FADE8        JFFS2 filesystem, little endian
3125248       0x2FB000        JFFS2 filesystem, little endian
3129896       0x2FC228        JFFS2 filesystem, little endian
3131436       0x2FC82C        JFFS2 filesystem, little endian
3132144       0x2FCAF0        JFFS2 filesystem, little endian
3230132       0x3149B4        JFFS2 filesystem, little endian
3236560       0x3162D0        JFFS2 filesystem, little endian
3238588       0x316ABC        JFFS2 filesystem, little endian
3354624       0x333000        JFFS2 filesystem, little endian
3731380       0x38EFB4        JFFS2 filesystem, little endian
3907584       0x3BA000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 4086444 bytes, 281 inodes, blocksize: 131072 bytes, created: 2020-09-16 07:31:57
8047426       0x7ACB42        xz compressed data
8049468       0x7AD33C        xz compressed data
8049798       0x7AD486        xz compressed data
8051952       0x7ADCF0        xz compressed data
8052122       0x7ADD9A        xz compressed data

Let's look inside rootfs:

Extracting first squash fs partition:

dd if=rom.img of=sqfs1.img bs=1 count=1048576 skip=1810432
unsquashfs sqfs1.img

cat ./squashfs-root/etc/shadow
root:$1$ouLOV500$zvYRvG33R/lxTS.9Gpz5H1:0:0:99999:7:::
bin:*:10933:0:99999:7:::
daemon:*:10933:0:99999:7:::
nobody:*:10933:0:99999:7:::

Seems internet knows nothing about the hash so I decided not to focus on it further since telnet or any other access methods relying on the system accounts are disabled by default:

cat ./squashfs-root/etc/init.d/rcS
#! /bin/sh

echo "mount all file system..."
mkdir /dev/pts
/bin/mount -av

echo "start telnet......"
#telnetd &

runlevel=S
prevlevel=N
umask 022
export runlevel prevlevel

echo "starting mdev..."
/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

mkdir /var/cache
mkdir /var/run
mkdir /var/log
mkdir /var/spool

echo "**************************"
echo "    Love Linux ! ! ! "
echo "**************************"

/bin/hostname -F /etc/sysconfig/HOSTNAME

#local service
/etc/init.d/rc.local

Interesting part of rc.local file:

....
RESETKEY=`cat /sys/user-gpio/gpio81-RST`
if [ $RESETKEY -eq "0" ]; then
  echo "Detected reset button has been pressed."

  i=1
  while [ $i -le 6 ]
  do
    if  [ -b /dev/mmcblk0p1 ]; then
      break
    fi
    let i++
    sleep 1
  done

  if [ -b /dev/mmcblk0p1 ]; then
    echo "Detected TF Card"
    cd /
#    mount -t vfat -o errors=continue /dev/mmcblk0p1 /mnt/disc1
    mount /dev/mmcblk0p1 /mnt/disc1

    if [ $? -eq 0 ]; then
      echo "mount sdcard ok"
      if [ -f /mnt/disc1/gwell_config/custom_setting.ini ]; then
        echo "Detected custom_setting.ini"
        cp /mnt/disc1/gwell_config/custom_setting.ini /rom/device.config
      fi

      if [ -f /mnt/disc1/upg.bin.enc ]; then
        echo "Detected /mnt/disc1/upg.bin.enc"
        ln -s /mnt/disc1/upg.bin.enc /tmp/upg.bin.enc
        gwellupdater.sh /tmp/upg.bin.enc
        if [ 0 -eq 0 ]; then
          exit
        else
          rm -f /tmp/*
        fi
      fi
    fi
    umount /mnt/disc1/
  fi
fi
....

From the above it could be seen that placing gwell_config/custom_setting.ini file on the SD Card allows to override camera settings and it looks like reset button must be pressed during camera initial boot for that Camera firmware upgrade could be performed by placing upg.bin.enc inside the root folder of the SD Card but it must be encrypted with RSA key (look at ./squashfs-root/etc/keyrsa/1912ak1.5.00.prv but it is a public key obviously)

Firmware modding

I decided to enable telnetd and make SD Card to serve as an external storage with ability to launch custom user binaries during camera startup With telnetd it's just enough to uncomment #telnetd in rcS script. Login as root, no password required And as for SD Card we need to mark it out with two partitions formatted as VFAT or ExFAT. User binaries should go to the second partition as well as rc.local script which will be triggered during camera boot up

I added the following block at the end of rc.local init script:

if [ -b /dev/mmcblk0p2 ]; then
    mount /dev/mmcblk0p2 /opt
    if [ -f /opt/rc.local ]; then
        echo "Detected rc.local"
        /opt/rc.local &
    fi
fi

Now I need to create /opt folder inside unpacked rootfs and re-pack it:

mkdir ./squashfs-root/opt
mksquashfs squashfs-root sqfs1.img -force-uid 1016 -force-gid 1016 -comp xz

Assembling final rom file and flashing it back:

dd if=sqf1.img of=rom.img bs=1 seek=1810432 conv=notrunc
sudo flashrom -p ch341a_spi -w rom.img

Found Unknown flash chip "SFDP-capable chip" (8192 kB, SPI) on ch341a_spi.
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.

Done!

21.06.21 faust93

@Hellangel1987
Copy link

hijacking this gist to share a discovery ( this is what comes up for google when i search anyka ipcam firmware )

so, i bought a light bulb ipcam off amazon, it had exposed ftp at port 21 once i set it up, the password was blank, and the user was root...... and getting tenlnet to start was as easy as putting telnetd in /etc/jffs2/timezone.sh

from there youre on your own. these things are meant to be bought, rebranded, and sold real quick to make a buck. my brand, service, nothing was on any "supported camera list"

model: TVQ11-200W (on box) FCC: gts202208160-1-1

im gonna activate rtsp on this thing though. you watch me

hey thank you for your hint after searching 3 hours to find a suitable break into the camera.

did you managed to get RTSP working or HTTP?

still tried to do changes in anyka_cfg.ini but camera does not boot up again after changes here.
I saw some possibilites :

[cloud]
dana = 1
onvif = 0
rtsp = 0

But seems every time i change to 1 the cam does brick and i need to reset it.

Any options?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment