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

@Arakon
Copy link

Arakon commented Dec 9, 2021

I seem to have a very similar device, the 1080p one, at least chipset-wise. Basically nothing is enabled on it, though.. http on 80 and port 10000 is open, but I haven't been able to get any sort of access to it outside of the app (IP Pro). I'm hoping there'll be a way to install/activate RTSP or something on it for use with home assistant. Will take it fully apart on the weekend and see if I can dump the firmware somehow.
PXL_20211208_182511746

@bolt1502
Copy link

bolt1502 commented Dec 9, 2021

https://drive.google.com/file/d/1hsEEnDklFa31tFJymZWfQsxLAOs2Cehb/view?usp=sharing
If you have access to the camera, you can try to throw the Factory folder from the archive on the USB flash drive (the map is formatted in FAT32), insert the map, on the camera, after a couple of minutes the camera will reboot, off the camera, the backup images should remain on the flash drive.

@faust93
Copy link
Author

faust93 commented Dec 9, 2021

Well, SOC could be the same but as for firmware it's likely vendor specific. Mine cam works with Yoosee app, there's an option in the app settings - "NVR connection", if enabled - it turns on RTSP/ONVIF on the camera (<cam_ip>:5000)

@Arakon
Copy link

Arakon commented Dec 9, 2021

Thanks, unfortunately, that did nothing at all.

@bolt1502
Copy link

@RataDP
Copy link

RataDP commented Jul 31, 2022

hi https://transfer.sh/QXhak1/ipcam.img.bz2

I know this thread is old, but can you reupload the bin file? I just screwed my camera trying things...
Thanks,
Borja

@faust93
Copy link
Author

faust93 commented Aug 1, 2022

@faust93
Copy link
Author

faust93 commented Aug 23, 2022

ANYKA CPU AK3918
Hi! It looks like your cam is based on ANYKA soc. The first thing I would suggest is to dump/disassemble camera firmware and try to poke around, may be it's possible to change default camera behavior using configuration files.
Regarding firmware - no idea which one could fit for your cam, the only option is to try different fw dumps from the same SOC based cameras closest to your one.

@adeelahmed11
Copy link

try this one https://svr4.win/.tmp/whd_fw.img.gz

is this original firmware or modded ?
please share original firmware dump so i can try this on my camera because my camera does not has sdcard.

@rtek1000
Copy link

rtek1000 commented Mar 3, 2023

Hello,

I have 2 Yoosee cameras with identification number 3325xxxx (SoC AK3918).

One of them stopped booting.

I tried to clone the W25s64 data from a 'good camera' to the other 'bad camera', and it worked, but the access was replaced.

If I add a camera, the other one stops working.

Apparently the firmware has access keys (accessKeyId) that need to be unique for each device.

I found this ID 3325xxxx, I changed the number in the 'bad camera', but even so the wifi AP appears with the 'good camera' code.

So it's a good idea to save the W25s64 data in case you want to have a backup, because my camera stopped for no apparent reason a few days after updating the firmware.

  • Attention, warning:

One thing I noticed is the presence of email and email password in plain text without any masking, available in various parts of the firmware (W25s64), accessible via EEPROM programmer CH341.

Even after performing a factory reset, the data remains there.

Do not use a primary email (better to create one for each device) on these IoT devices.

@LuizCastroINV
Copy link

LuizCastroINV commented Nov 24, 2023

boot 1

Hello everyone, good morning, I updated my camera using the Yoose app, but in the middle of the process there was a power outage and the LED only remained on, will this image file help me? and how do I do this? Thank you very much, I know the post is old, but my problem is recent.

boot2

@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