Skip to content

Lawliet95/ANYKA-Tuya-Hacking-Journey-AK3918v200EN080-v200

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Firmware Analysis — Camera Anyka AK3918EN080-v200

TL;DR

This repository documents my hands-on analysis of a low-cost Anyka/Tuya-based camera hidden inside a USB charger. The device is sold as a stealth camera and requires a Chinese mobile app (Tuya) to configure it and connect it to your LAN. Given the device’s function (camera), its dependency on a foreign cloud service and a closed app, I was concerned about its security and decided to investigate.

anyka_soc anyka_soc

Why I looked into it

The product felt sketchy from the start. It’s marketed as a stealth camera, requires a vendor app to operate, and pushes cloud subscriptions — a combination that raises privacy and attack surface concerns:

  • Hidden camera hardware in a consumer product.
  • Reliance on a proprietary mobile app and remote cloud servers.
  • Limited or unknown modified firmware/software transparency.

Because of those factors, I wanted to answer: how secure is this device in practice? Can an owner or a third party gain unintended access? What data flows to remote servers?

What this repo contains

This repository collects everything I found during the investigation, including:

  • Firmware extraction steps and tools used.
  • Static and dynamic analysis results.
  • The modifications I made to the firmware and the rationale behind them.
  • Bootlogs, screenshots, and other artifacts (where appropriate).
  • Notes on observed network traffic and suspicious behavior.

Scope and intent

This project is a technical security analysis and documentation of the steps I took to analyze, modify and reflash a camera device. The goal is research and disclosure — to understand the risks and to document reproducible steps for defenders and researchers. It is not intended to enable wrongdoing. If you plan to reproduce any of the steps here, ensure you own the device or have explicit permission to work on it.

Reconnaissance

This document describes the initial reconnaissance steps I performed on the camera after unboxing and adding it to my LAN via the vendor app. It explains the scanning and network-observation steps, the tools used, and the high-level findings.


1) Device onboarding and network setup

  • I configured the device using the official mobile application and connected it to my home Wi-Fi.
  • After the device joined the network, I identified its local IP address from the router client list (192.168.1.28) and proceeded with active and passive network reconnaissance.

2) Port / service discovery (active scan)

Setup / tools used

Command I used:

┌──(lawliet㉿kali)-[~]
└─$ sudo nmap 192.168.1.28 -sV -O
Starting Nmap 7.95 ( https://nmap.org ) at 2025-10-10 21:36 CEST
Nmap scan report for 192.168.1.28 (192.168.1.28)
Host is up (0.0092s latency).
Not shown: 997 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
21/tcp   open  ftp     BusyBox ftpd (D-Link DCS-932L IP-Cam camera)
23/tcp   open  telnet  BusyBox telnetd
6668/tcp open  irc?
MAC Address: 30:BE:29:E9:9D:4B (Unknown)
Device type: general purpose
Running: Linux 2.6.X|3.X
OS CPE: cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3
OS details: Linux 2.6.32 - 3.10
Network Distance: 1 hop
Service Info: Host: anyka; Device: webcam; CPE: cpe:/h:dlink:dcs-932l

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 169.72 seconds
Observed (summary):
  • A telnet service was reachable on the device on port 23.

  • An ftp service was reachable on port 21 and custom vendor daemons was exposed.

  • A service was reachable on port 6668. Was it custom protocol? Can't tell more than this from nmap.


3) Passive / MITM observation between phone and camera

Setup / tools used

I quickly set up a MITM and packet captures on the LAN using Ettercap + Wireshark while the mobile app talked to the camera.

I attempted to intercept requests from the mobile app to the device and to remote servers. I was hoping to find something (maybe clear traffic) while the device was talking to my phone to configure the camera.

Findings
  • Application traffic was protected by TLS (HTTP over TLS), so payloads were encrypted and not trivially readable via a basic MITM.

  • Local live video streaming occurred over UDP on the LAN (likely RTP/RTSP or a vendor-specific UDP stream).

  • When the phone was not on the same LAN, the app still displayed the live stream — indicating the device can stream via vendor cloud/relay servers (i.e. traffic leaves the LAN and is proxied/relayed).

  • TLS (and/or certificate pinning and proprietary protocols) prevented recovering plaintext control traffic with passive MITM.


4) Active / Telnet & FTP:

Setup / tools used

telnet_bad

Well.. What would you do if you find telnet opened on port 23? Of course you try a quick brute force using wordlist and hope to find out the password so you just get in.. I was not expecting much from this,but I spent some time trying to bruteforce both ports.

A strange thing I found out was FTP allowed me to get in with anonymous access,but could not run any command (system was asking for credentials).

ftp_bad

4.1) High-level conclusions from reconnaissance

  • The device exposes multiple services on the local network (telnet and others). Those services can be entry points for local attacks.

  • Live video streaming occurs locally over UDP and can be relayed via vendor cloud servers for remote access.

  • TLS protects the app<>device control channel, preventing straightforward passive inspection (could be proper TLS or certificate pinning or a custom crypto layer).

  • Device behavior extends beyond the LAN due to outbound connections to cloud/relay servers — so security concerns include both local attack surface and remote exfiltration/command channels.

5) Device Tearing:

Setup / tools used

At this point I had to tear apart the device to see what was under that cheap plastic shell. I were afraid some glue was there to prevent the internal structure from coming out,but on my surprise,I was able to took the shell away using a thin needle and pushing towards the top of the board. This is how the device looked after removing the plastic shell:

device_naked device_naked2

That reavealed an Anyka SoC,the model is AK3918v200EN080-v200. You can clearly see the Wi-Fi Antenna on the side.

There were some screws that was holding that tiny board in place. After removing them,this is the back of the board:

behind_board

The first thing I noticed was that XMC flash chip,the first candidate for hosting firmware. The chip was so small I had to had a look with the microscope to see the label on it:

flash_chip

It is a XM25QH. A big classic for storing fw.

6) UART Interface Analysis:

Setup / tools used

Well,this one has been undoubtly the most creative and funny part. After finding the flash chip where fw was stored,the next thing I wanted to try was UART interface to get some boot logs and see what we can find from them. My intention was trying to get a shell from U-Boot (interrupting auto boot or smth like that). I saw two unlabeled pins next to the power flat cable and thought they could be for UART Serial communication:

UART

I took my multimeter and measured the voltage.

  • One was outputting 3,34V (stable). Probably the RX Pin (the one you can send command to the board).
  • The other one was outputting a fluctuating voltage that moved around 3,28V. Probably the TX Pin (the one that outputs UART logs.)

I don't know if it's clear from the pics,but that board is so freaking small.. Normally,in situations like this you would solder a cable on the pads and see if it output logs. I can solder but I'm not definitely a master,I'm at completely beginner level,and in this scenario,I could've easily burn/screw the board or shortcircuit UART serial pads with iron,or even worse... So I started thinking how could I plug to them in a phisical way that was not permanent or so risky. I started to think out and had an idea,so I soldered a Sewing Needle to a copper cable and I came out with two of this tinkered "clip",let's call it Unholy Cable Clip.

unholy_thing

Well,thanks to my engineering (😂) I was able (!) to get UART logs (I admit that when that happened I got so excited and proud ahahah).

The final result was this one: miracle_exists

miracle_exists1

That looked soooo satisfying to me.

Command used:

┌──(lawliet㉿kali)-[~/Scrivania/dump_firmware/_dumpfw.bin.extracted]
└─$ screen -L /dev/ttyUSB0 115200

The UART Logs said:

U-Boot 2013.10.0-AK_V2.0.04 (Oct 30 2023 - 14:13:57)

DRAM:  64 MiB
8 MiB
Create flash partition table init OK!
ANYKA SDHC/MMC4.0: 0
Load Env CRC OK!
In:    serial
Out:   serial
Err:   serial
write 1 to pin 13 on address 0x2017000c down
write 1 to pin 47 on address 0x20170010 down

Hit any key to stop autoboot:  0 


SF: 2199432 bytes @ 0x33000 Read: OK
## Booting kernel from Legacy Image at 81808000 ...
   Image Name:   Linux-3.4.35
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2199368 Bytes = 2.1 MiB
   Load Address: 81808000
   Entry Point:  81808040
   Verifying Checksum ... OK
   XIP Kernel Image ... OK

Starting kernel ...

As expected, U-Boot starts and loads the system kernel.

If you want to read the complete log,you can find it inside the logs directory.

Observations and Findings

When U-Boot starts,it says

Hit any key to stop autoboot: 0

I was assuming that 0 means that there is no delay to let the user press a key and the system just won't wait to perform kernel loading. More than this,the system won't catch/get any keyboard input before kernel is compleately loaded and linux is started (I even made up a quick python script that was just basically spamming buttons as soon as the UART communication starts). Due to the fact that the system has this behaviour,I realised I could't get a shell from here.

Security Concerns:

  • I noticed in the log that at some point (exactly here) my Wi-Fi SSID and Password was exposed completely in clear text.

Not surprised by that,but surely more worried than I was before. It was obviously an isolated router,but it has to be connected on internet to configure the cam on your LAN. If the bootlog is sent for some reason to the vendor,they basically have your Wireless Network credentials.

After a while,you can see in the log:

start telnet......
starting mdev...
**************************
    Love Linux ! ! ! 
**************************
200+0 records in
200+0 records out
102400 bytes (100.0KB) copied, 0.017081 seconds, 5.7MB/s
aksensor_module_init


anyka login: default log level=4

***************************************
******** cmd server has running! ******
***************************************
[main:309] Success to create TCP socket.
[main:343] Waiting for connect......
[atbm_log]:atbm_usb_module_init 0
[atbm_log]:platform_init(251)
[atbm_log]:SVN_VER=34074,DPLL_CLOCK=2,BUILD_TIME=2024-07-17_11:36:31
[atbm_log]:atbm_usb_probe : idVendor[7a] idProduct[8890] 
[atbm_log]:reset wifi_chip_probe!
[atbm_log]:Probe called -1 v1
[atbm_log]:not CONFIG_USE_DMA_ADDR_BUFFER
[atbm_log]:CONFIG_TX_NO_CONFIRM
[atbm_log]:ble_spin_lock init 
[atbm_log]:Allocated hw_priv @ c2082ea0
[atbm_log]:atbmwifi USB_USE_TASTLET_TXRX enable (c2082ea0)
[atbm_log]:atbmwifi USB_USE_TASTLET_TXRX enable (c2082ea0)
[atbm_log]:atbm_get_chiptype, chipver=0xa3, g_wifi_chip_type[14]
[atbm_log]:atbm_before_load_firmware++
[atbm_log]:+++++++++++++++++1.1v++++++++++++++++++
[atbm_log]:===================~_~====================
[atbm_log]: wait_event_interruptible from  send_prbresp_wq
[atbm_log]:atbm_start_load_firmware++
[atbm_log]:
======>>> load WIFI BLE COMB firmware <<<======

From that point (after telnet service is started and Love Linux banner is shown),the system performs an auto login (outputs anyka login:,the same prompt we're getting when connecting via telenet) and starts accepting keyboard input from my Linux system. If I pressed enter,the system prompted me with the same anyka login: message. The UART interface keep spamming logs,but if I blinded input root (for username) another prompt even showed up asking for Password:.

Looked like I got at the same point of before when tried to connect to telnet (but I had a lot more informations),so I had to go furhter.

7) Firmware Extraction and Firmware Analysis:

At this point,I had to bring out the big guns.

Setup / Tool Used

CHprogr

I took my CH341A programmer,my intention was to dump out the fw from the chip,hoping it was not encrypted,but on these cheap IoT devices they usually are not.

I plugged the SOIC8 clip to the board XMC XM25QH chip and started dumping the firmware.

dumping_fw

From the firmware I could of course recovered crucial information for my security analysis.

Command used

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware]
└─$ sudo flashrom -p ch341a_spi -w dumpfw.bin                    
[sudo] password di lawliet: 
flashrom v1.6.0 on Linux 6.12.38+kali-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Found XMC flash chip "XM25QH64C/XM25QH64D" (8192 kB, SPI) on ch341a_spi.
===
This flash part has status UNTESTED for operations: WP
The test status of this chip may have been updated in the latest development
version of flashrom. If you are running the latest development version,
please email a report to flashrom@flashrom.org if any of the above operations
work correctly for you with this flash chip. Please include the flashrom log
file for all operations you tested (see the man page for details), and mention
which mainboard or programmer you tested in the subject line.
You can also try to follow the instructions here:
https://www.flashrom.org/contrib_howtos/how_to_mark_chip_tested.html
Thanks for your help!
Reading flash chip contents... done.

After dumping the firware, I run binwalk:

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware]
└─$ binwalk -e dumpfw.bin                          

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
215688        0x34A88         LZO compressed data
216048        0x34BF0         LZO compressed data
2185321       0x215869        xz compressed data
2506752       0x264000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 850190 bytes, 226 inodes, blocksize: 131072 bytes, created: 2025-05-20 02:22:25
3424256       0x344000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 4522164 bytes, 300 inodes, blocksize: 131072 bytes, created: 2025-05-20 02:22:27
7966732       0x79900C        JFFS2 filesystem, little endian

WARNING: One or more files failed to extract: either no utility was found or it's unimplemented

That revealed squashfq and jffs2 file system partitions. This is common for chinese IP cams.

I had a quick look inside the binwalk extracted directory:

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware]
└─$ cd _dumpfw.bin.extracted                   

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware/_dumpfw.bin.extracted]
└─$ ls   
215869.xz        dmesg          ifenslave              libdl-0.9.33.2.so           lsmod          ps               sys
264000.squashfs  dnsdomainname  ifup                   libdl.so.0                  makedevs       pwd              sysconfig
344000.squashfs  dumpkmap       init                   libgcc_s.so                 mdev           rc.local         sysctl
34A88.lzo        echo           init.d                 libgcc_s.so.1               mdev.conf      rcS              syslogd
34BF0            egrep          inittab                libiw.so.29                 mkdir          reboot           tar
34BF0.lzo        etc            inotifyd               libm-0.9.33.2.so            mkdosfs        resolv.conf      telnetd
79900C.jffs2     false          insmod                 libm.so.0                   mkfs.vfat      rm               tmp
acpid            fbsplash       ionice                 libnsl-0.9.33.2.so          mknod          rmdir            touch
adjtimex         fdflush        iostat                 libnsl.so.0                 mkswap         rmmod            true
arp              fdisk          ip                     libpthread-0.9.33.2.so      mmc_test       route            tunctl
ash              fgrep          ipaddr                 libpthread.so.0             mnt            run              tuya.key
base64           free           ipcalc                 libresolv-0.9.33.2.so       modinfo        runlevel         udhcpc
bin              freeramdisk    iplink                 libresolv.so.0              modprobe       sbin             udhcpd
blkid            fsck           iproute                librt-0.9.33.2.so           modules        scriptreplay     udhcpd.conf
blockdev         fstab          iprule                 librt.so.0                  more           sed              uevent
bootchartd       fstrim         iptunnel               libstdc++.so                mount          services         umount
busybox          fsync          jffs2                  libstdc++.so.6              mountpoint     setarch          uname
cat              ftpd           jffs2-root             libstdc++.so.6.0.19         mpstat         setconsole       uncompress
catv             getopt         kill                   libstdc++.so.6.0.19-gdb.py  mt             setserial        updater
chattr           getty          killall                libubacktrace-0.9.33.2.so   mv             sh               usleep
chgrp            grep           killall5               libubacktrace.so.0          nameif         shadow           usr
chmod            group          klogd                  libuClibc-0.9.33.2.so       netstat        slattach         var
chown            gunzip         ldconfig               libutil-0.9.33.2.so         nice           sleep            vconfig
cp               gzip           ld.so.conf             libutil.so.0                nsswitch.conf  squashfs-root    vi
cpio             halt           ld-uClibc-0.9.33.2.so  linux32                     passwd         squashfs-root-0  watch
cttyhack         hdparm         ld-uClibc.so.0         linux64                     pidof          stat             watchdog
custom           host.conf      lib                    ln                          ping           stty             xxx
date             hostname       libatomic.so           loadkmap                    pivot_root     su               zcat
dd               HOSTNAME       libatomic.so.1         login                       poweroff       sulogin
depmod           hosts          libatomic.so.1.0.0     logread                     powertop       swapoff
dev              hwclock        libcrypt-0.9.33.2.so   losetup                     printenv       swapon
devmem           ifconfig       libcrypt.so.0          ls                          proc           switch_root
df               ifdown         libc.so.0              lsattr                      profile        sync

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware/_dumpfw.bin.extracted]
└─$ cd squashfs-root         

┌──(lawliet㉿kali)-[~/Scrivania/dump_firmware/_dumpfw.bin.extracted/squashfs-root]
└─$ ls
bin  custom  dev  etc  init  lib  mnt  proc  sbin  sys  tmp  usr  var             

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware/_dumpfw.bin.extracted/squashfs-root]
└─$ cd etc          
                                               
┌──(.venv)─(lawliet㉿kali)-[~/…/dump_firmware/_dumpfw.bin.extracted/squashfs-root/etc]
└─$ ls
fstab  host.conf  init.d   jffs2       mdev.conf      passwd   resolv.conf  shadow     tuya.key     xxx
group  hosts      inittab  ld.so.conf  nsswitch.conf  profile  services     sysconfig  udhcpd.conf

I went straight to the squashfs-root/etc directory and I saw a bunch of important files,more than others,the passwd file ,the shadow file,the inittab file and the init.d directory.

┌──(.venv)─(lawliet㉿kali)-[~/…/dump_firmware/_dumpfw.bin.extracted/squashfs-root/etc]
└─$ cat shadow            
root:$1$SALT$HASH:0:0:99999:7::: <--- Redacted 
bin:*:10933:0:99999:7:::
daemon:*:10933:0:99999:7:::
nobody:*:10933:0:99999:7:::

At this point,I already got some important information. The camera username was root (as expected) and we even got the root hash. The format is md5crypt:

$1$SomeSalt$hash

From this point,I had just to decide how to attack the device and get access to invesrigate furthermore.

I found a gist on GitHub with a bunch of users trying to decrypt similiar hash from kinda similiar devices (made by other vendors,looks like there's a lot of modified firmware combined with different hardare, and every firmware has its hash). Some users got lucky and got their hash decrypted due to community being active. I obviously got no luck,so that mf is still laying there unbroken. I had to find another way.

Guessed it,right? That way was patching the firmware and got access to the system.

I obviosly can't post exactly what I did,otherwise all this work would be taken down by GitHub, but if you point your attention on the right stuff,you can outsmart the boot logic and gain access kinda easily. Just think about what I told you til now (from UART logs and system behaviour),and look what I'm showing from this point.

First of all,I wanted to understand how the boot happens.

The files responsible for that are basically:

  • inittab file
  • init.d directory that contains:
    • rcS file
    • rc.local file

Had a quick look into them:

┌──(lawliet㉿kali)-[~/Scrivania/dump_firmware/_dumpfw.bin.extracted/squashfs-root/etc]
└─$ cat inittab                    
# /etc/inittab

# Copyright (C) 2010 Anyka

# Note: BusyBox init doesn't support runlevels.  The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use
# sysvinit.
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id        == tty to run on, or empty for /dev/console
# runlevels == ignored
# action    == one of sysinit, respawn, askfirst, wait, and once
# process   == program to run

# Startup the system
::sysinit:/etc/init.d/rcS # <--------- The system Loads rcS file

ttySAK0::respawn:/sbin/getty -L ttySAK0 115200 vt100 # GENERIC_SERIAL <-- This is where the system start accepting keyboard input: when getty is launched. Before of that,rcS file is launched.

::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

As I showed in the file,the system Loads rcS file,that loads rc.local file.

┌──(.venv)─(lawliet㉿kali)-[~/…/dump_firmware/_dumpfw.bin.extracted/squashfs-root/etc]
└─$ cd init.d
                                                                                                                                          
┌──(.venv)─(lawliet㉿kali)-[~/…/_dumpfw.bin.extracted/squashfs-root/etc/init.d]
└─$ ls
rc.local  rcS
                                                          
┌──(.venv)─(lawliet㉿kali)-[~/…/_dumpfw.bin.extracted/squashfs-root/etc/init.d]
└─$ cat 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

We can clearly see this is the boot part when the Love Linux banners shows up. After that,the rc.local file is loaded

┌──(lawliet㉿kali)-[~/…/_dump_2_fw.bin.extracted/squashfs-root/etc/init.d]
└─$ cat rc.local                       
#!/bin/sh

#print kernel error default
echo 4 > /proc/sys/kernel/printk

# mount usr file-system. 
/bin/mount -t squashfs /dev/mtdblock5 /usr
# mount jffs2 file-system. 
/bin/mount -t jffs2 /dev/mtdblock6 /etc/jffs2
# note: can't recommend running other app before `mount` command.

#start ftp server, dir=root r/w, -t 600s(timeout)
/usr/bin/tcpsvd 0 21 ftpd -w / -t 600 &

#start syslogd & klogd, log rotated 3 files(200KB) to /var/log/messages
syslogd -D -n -O /var/log/messages -s 200 -b 3 & # -l prio
klogd -n & # -c prio

#create ramdisk
dd if=/dev/zero of=/tmp/zero bs=512 count=200
losetup /dev/loop0 /tmp/zero
mkfs.vfat /dev/loop0
mkdir /tmp/ramdisk
mount /dev/loop0 /tmp/ramdisk

ifconfig lo 127.0.0.1

#load camera module
/usr/sbin/camera.sh setup

dmesg > /tmp/start_message
#start system service
/usr/sbin/service.sh start &

## set min free reserve bytes
echo 2048 > /proc/sys/vm/min_free_kbytes

Here service.sh is launched, under /usr/sbin/service.sh and it is responsible for launching anyka_ipc, the main ELF binary that runs the Anyka Services and make the camera bind with Tuya App. I tried some basic reversing stuff,like launching strings on the file and opening it in Ghidra. The binary is not obfuscated,but as you know reversing takes a lot of time due to the fact that symbols get removed and you have to guess what the pseudo code is doing. I saw some basic hashing functions,and saw the system calculates the md5 sum of the FW,but despite that,he never checks it (LOL) . If you're interested in anyka_ipc ELF file,you can find it in the bin directory of this repo. At time of publishing,I'm not sure if publishing FW dump is a good idea,I'll think about it. In this file,I made the major changes to get access to the system.

8) Firmware Patching :

Setup / Tool Used

After modifying squashfs-root, I had to flash the modified firmware onto the XMC flash chip.

Command used:

The first thing was to recompress the squashfs-root folder to create a patch to write inside the firmware using dd. To make it:

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware]
└─$ mksquashfs _dumpfw.bin.extracted/squashfs-root \
  /tmp/A_new.squashfs \
  -comp xz -Xbcj arm -b 131072 -noappend -all-root -no-xattrs

Parallel mksquashfs: Using 6 processors
Creating 4.0 filesystem on /tmp/A_new.squashfs, block size 131072.
[===========================================================================================================================|] 52/52 100%

Exportable Squashfs 4.0 filesystem, xz compressed, data block size 131072
        compressed data, compressed metadata, compressed fragments,
        no xattrs, compressed ids
        duplicates are removed
Filesystem size 785.90 Kbytes (0.77 Mbytes)
        32.59% of uncompressed filesystem size (2411.46 Kbytes)
Inode table size 1178 bytes (1.15 Kbytes)
        15.10% of uncompressed inode table size (7803 bytes)
Directory table size 2014 bytes (1.97 Kbytes)
        57.12% of uncompressed directory table size (3526 bytes)
Number of duplicate files found 0
Number of inodes 226
Number of files 37
Number of fragments 5
Number of symbolic links 171
Number of device nodes 0
Number of fifo nodes 0
Number of socket nodes 0
Number of directories 18
Number of hard-links 0
Number of ids (unique uids + gids) 1
Number of uids 1
        root (0)
Number of gids 1
        root (0)

Then you want to make all the needed checks to avoid binary segments overlapping (be extremely careful here,if you make mistakes and creates a squashfs-root folder bigger than the original,you should then re-align binary sections,otherwise you'll create a corrupted binary and the system will likely went down as soon as he gets fucked up due to bad section alignment. Trust me,it's not good).

For e.g.:

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware]
└─$ stat -c '%n %s' /tmp/A_new.squashfs

In my case the output should be <= 917504 byte, that's the size squashfs-root partition (you can see it from binwalk extraction logs).

After you performed all the checks,you basically write the new partition inside the firmware:

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware]
└─$ cp dumpfw.bin dumpfw_patched_squashA.bin  

To make a backup the old firmware,and then use dd to write inside the new copy of the fw:

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware]
└─$ sudo dd if=/tmp/A_new.squashfs of=dumpfw_patched_squashA.bin \
  bs=1 seek=$((0x264000)) conv=notrunc status=progress
[sudo] password di lawliet: 
466935 bytes (467 kB, 456 KiB) copied, 1 s, 467 kB/s
806912+0 records in
806912+0 records out
806912 bytes (807 kB, 788 KiB) copied, 1,73171 s, 466 kB/s

If everything is good,you're now ready to flash the patched firmware.

The command here is straightforward:

┌──(.venv)─(lawliet㉿kali)-[~/Scrivania/dump_firmware]
└─$ sudo flashrom -p ch341a_spi -w dumpfw_patched_squashA.bin     
flashrom v1.6.0 on Linux 6.12.38+kali-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Found XMC flash chip "XM25QH64C/XM25QH64D" (8192 kB, SPI) on ch341a_spi.
===
This flash part has status UNTESTED for operations: WP
The test status of this chip may have been updated in the latest development
version of flashrom. If you are running the latest development version,
please email a report to flashrom@flashrom.org if any of the above operations
work correctly for you with this flash chip. Please include the flashrom log
file for all operations you tested (see the man page for details), and mention
which mainboard or programmer you tested in the subject line.
You can also try to follow the instructions here:
https://www.flashrom.org/contrib_howtos/how_to_mark_chip_tested.html
Thanks for your help!
Reading old flash chip contents... done.
Updating flash chip contents... Erase/write done from 0 to 7fffff
Verifying flash... VERIFIED.

Logging into system:

Setup / Tool Used

  • telnet
  • ftp

At this point we're basically done. If everything I did was correct, and in this case was (but not at first try), the system should go up and now you can login as root. There's no need to plug in my complex engineered-needle system again,as we know we've got telenet opened waiting for someone to basically break in :D

As expected,after patching:

telnet_pwnd

I was able to login with FTP as well :

ftp_pwnd

This basically makes the offensive part over. Now it's time to investigate inside of the OS,but now we're root and we can see everything.

Network Analysis:

Work in progress, To Be Continued

Structure

  • logs/ — boot logs.
  • images/ — screenshots and photos taken while interacting with the device.
  • scripts/ — tbd
  • bin/ — a place for original firmware dumps/binary.

Disclaimer & Ethics

Only perform these actions on devices you lawfully own. Do not use these instructions to access devices you do not own or to perform unauthorized operations. This repository is meant for documentation and defensive research.

About

This repo is a POC for demostrating the poor security of cheap chinese IoT devices,such this one

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages