Rooting a VMC2040 security camera part 4: Deeper analysis
Brief
This part will focus on gather as much information as possible about the system. As I in this stage don't know what I'm looking for, I will just try to document everything I find interesting.
The other parts of the series are:
U-Boot environment
I used dd to extract the U-Boot environment from the NAND dump. The environment is stored in the ENV partition, which starts at offset 0x440000 and is 0x140000 bytes long:
1dd if=nand_no_oob.bin bs=1 skip=$((0x440000)) count=$((0x140000)) of=ENV.imgThis is U-boot environment extracted:
bootargs=ubi.mtd=11,2048 root=/dev/mtdblock9 rootfstype=squashfs ro init=/linuxrc LX_MEM=0xffc6000 mma_heap=mma_heap_name0,miu=0,sz=0x2400000 mma_memblock_remove=1 mtdparts=nand0:0xC0000@0x140000(IPL0),0xC0000(IPL_CUST0),0xC0000(UBOOT0),0xC0000(UBOOT1),0x140000(ENV),0x140000(ENV_P1),0xC0000(MANUFACTURE),0x5C0000(KERNEL),0x5C0000(KERNEL_P1),0x1E00000(ROOTFS),0x1E00000(ROOTFS_P1),-(UBI) bootcmd=nand read.e 0x22000000 KERNEL 0x5C0000; bootm 0x22000000;nand read.e 0x22000000 KERNEL_P1 0x5C0000; bootm 0x22000000 bootdelay=0 bootparts=mtdparts=nand0:0x60000@0x140000(IPL0),0x60000(IPL1),0x60000(IPL_CUST0),0x60000(IPL_CUST1),0xC0000(UBOOT0),0xC0000(UBOOT1),0x60000(ENV0),0x340000(KERNEL),0x340000(RECOVERY),-(UBI) ethact=usb_ether ethaddr=00:30:1b:ba:02:db fileaddr=23ab6698 filesize=282 gatewayip=192.168.201.101 ipaddr=192.168.201.2 mtddevname=IPL0 mtddevnum=0 mtdids=nand0=nand0 mtdparts=mtdparts=nand0:0xC0000@0x140000(IPL0),0xC0000(IPL_CUST0),0xC0000(UBOOT0),0xC0000(UBOOT1),0x140000(ENV),0x140000(ENV_P1),0xC0000(MANUFACTURE),0x5C0000(KERNEL),0x5C0000(KERNEL_P1),0x1E00000(ROOTFS),0x1E00000(ROOTFS_P1),-(UBI) netmask=255.255.255.0 partition=nand0,0 serverip=192.168.201.101 stderr=serial stdin=serial stdout=serial usb_folder=images usbnet_devaddr=00:11:22:33:44:55 usbnet_hostaddr=00:11:22:33:44:66
The SquashFS (rootfs)
Root password
/etc/passwd contains the encrypted root password:
root:$5$rounds=999999$3y7Gr3/skKaK$//m/9T7NLLgTyGWnxt17LuYR5CcS28/w.pqUzt70dfD:0:0:root:/home:/bin/sh
SHA-256 crypt ($5$) with 999,999 rounds. Expensive but maybe crackable.
Cloud API endpoints
/env/vzdaemon.*.env and /env/xagent.*.conf contain all of Arlo's cloud environments, baked into the firmware:
| Environment | Device API | Firmware updates |
|---|---|---|
| Production | deviceapi.messaging.arlo.com | updates.arlo.com/.../production |
| Development | deviceapi-goldendev.messaging.arlo.com | arloupdates.arlo.com/.../dev |
| Staging | deviceapi-staging.messaging.arlo.com | updates.arlo.com/.../staging |
| QA | deviceapi.messaging.arlo.com | updates.arlo.com/.../qa |
The xagent (cloud registration daemon) talks to:
- presence.arloxcld.com — device discovery
- registration.arloxcld.com — device registration and claiming
- advisor.arloxcld.com — cloud command broker
Development variants use *.dev.arloxcld.com for all of the above.
The pegacmd
/bin/pegacmd is a big shell script for controlling very much on the camera. Running it with no arguments prints the menu:
pegacmd start_media_manufacture pegacmd start_media_service pegacmd stop_media_service pegacmd misc get als pegacmd misc get nvmode pegacmd misc get temp pegacmd misc set console uart pegacmd misc set console ssh pegacmd iva get info pegacmd iva get intrusion pegacmd iva set on pegacmd iva set msg pegacmd lsd set console uart pegacmd lsd set console ssh pegacmd lsd set msg pegacmd lsd get info pegacmd version camif pegacmd version pega_misc pegacmd version audio pegacmd version iq pegacmd version vzdaemon pegacmd json_camif_conn pegacmd json_dbif_conn pegacmd regGet <JSON-Reg-Name> pegacmd regSet <JSON-Reg-Name> <value>
No firewall
There is no iptables/nftables/bpfilter binary on the camera or other configuration files indicating a firewall is in use.
The UBI volume
Device identity
From the UBI config volume (device_config_0.json):
Serial: A4U222KA0005C Model: VMC2040A Hardware: 1.2 Firmware: 1.22.0.0_33_53d2844_f5c0b43 MAC: a4:11:62:c1:05:04
Configuration
The UBI config volume (/config/nvram/) holds over 250 configuration files, one key per file. Some notable ones:
- pega_sys_en_uart_tx = 1 — UART output enabled
- pega_sys_en_uart_rx = 1 — UART input enabled (not enabled by default)
What the logs reveal
Logs and core dumps from earlier are stored in the UBI nvrservice volume. Here are some information extracted from those.
Boot time sequence
[0s] Kernel init, module loading [1s] syslogd, chronyd (NTP) start [2s] camif (camera control daemon) starts [3s] Battery: 90%, 30°C, charging [4–9s] WiFi: MT7682 firmware wifi_s.0.3.4, EU region, associating [20s] vzdaemon (cloud messaging daemon) starts [30s] xagent (cloud registration agent) starts [36s] Camera online, connected to Arlo cloud
Processes
Thirteen processes, 65 threads total:
1Sat Jan 6 20:50:41 UTC 2024
2===== pstree -p =========
3linuxrc(1)-+-ArloRateAdapt(867)-+-{ArloRateAdapt}(875)
4 | -{ArloRateAdapt}(876)
5 |-busybox(887)
6 |-camif(743)-+-{camif}(751)
7 | |-{camif}(752)
8 | |-{camif}(753)
9 | |-{camif}(754)
10 | |-{camif}(767)
11 | |-{camif}(834)
12 | `-{camif}(1231)
13 |-chronyd(620)
14 |-fflauncher(775)-+-{fflauncher}(784)
15 | |-{fflauncher}(785)
16 | |-{fflauncher}(786)
17 | `-{fflauncher}(901)
18 |-ffserver(1496)-+-{ffserver}(1510)
19 | |-{ffserver}(1512)
20 | |-{ffserver}(1513)
21 | |-{ffserver}(1514)
22 | `-{ffserver}(1515)
23 |-linuxrc(888)
24 |-pega_misc(744)-+-{pega_misc}(762)
25 | |-{pega_misc}(763)
26 | |-{pega_misc}(764)
27 | |-{pega_misc}(765)
28 | |-{pega_misc}(766)
29 | `-{pega_misc}(768)
30 |-pega_watchdog(746)-+-pegacmd(2467)---pstree(2499)
31 | `-{pega_watchdog}(749)
32 |-pega_wifilog(745)
33 |-prog_mediaserve(759)-+-{prog_mediaserve}(778)
34 | |-{prog_mediaserve}(779)
35 | |-{prog_mediaserve}(817)
36 | |-{prog_mediaserve}(818)
37 | |-{prog_mediaserve}(819)
38 | |-{prog_mediaserve}(827)
39 | |-{prog_mediaserve}(828)
40 | |-{prog_mediaserve}(829)
41 | `-{prog_mediaserve}(864)
42 `-syslogd(616)
43 Message queues
The applications seems to be using Messages queues for IPC communication:
1===== ipcs -q ========
2
3------ Message Queues --------
4key msqid owner perms used-bytes messages
50x050a37ee 65536 root 666 56 2
60x050a3397 98305 root 666 732 3
70x03d0ad88 131074 root 666 0 0
80x04fb620c 196611 root 666 0 0
90x0529115c 229380 root 666 0 0
100x00d5bd10 262149 root 666 0 0
110x00d5bd08 294918 root 666 0 0 Netstat
Allmost all network services are listening on localhost only, and there are several established connections to the cloud. No services are exposed on the WiFi interface.
1===== netstat -npal ========
2Active Internet connections (servers and established)
3Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
4tcp 0 0 127.0.0.1:8090 0.0.0.0:* LISTEN 1496/ffserver
5tcp 0 0 127.0.0.1:4000 0.0.0.0:* LISTEN 743/camif
6tcp 0 0 0.0.0.0:554 0.0.0.0:* LISTEN 1496/ffserver
7tcp 0 1 192.168.20.12:52952 54.247.91.176:443 FIN_WAIT1 -
8tcp 0 0 127.0.0.1:4000 127.0.0.1:39312 TIME_WAIT -
9tcp 0 1 192.168.20.12:59356 23.72.139.27:443 FIN_WAIT1 -
10tcp 0 0 127.0.0.1:4000 127.0.0.1:39310 TIME_WAIT -
11udp 0 0 169.254.103.8:12345 0.0.0.0:* 743/camif
12udp 0 0 127.0.0.1:323 0.0.0.0:* 620/chronyd
13udp 0 0 127.0.0.1:60268 127.0.0.1:8700 ESTABLISHED 775/fflauncher
14udp 0 0 127.0.0.1:8700 0.0.0.0:* 867/ArloRateAdapt
15Active UNIX domain sockets (servers and established)
16Proto RefCnt Flags Type State I-Node PID/Program name Path
17unix 11 [ ] DGRAM 1950 616/syslogd /dev/log
18unix 2 [ ] DGRAM 1961 620/chronyd /var/run/chrony/chronyd.sock
19unix 2 [ ] DGRAM 2347 775/fflauncher
20unix 2 [ ] DGRAM 2038 744/pega_misc
21unix 2 [ ] DGRAM 2035 743/camif
22unix 2 [ ] DGRAM 5252 1496/ffserver
23unix 2 [ ] DGRAM 2500 867/ArloRateAdapt
24unix 2 [ ] DGRAM 2041 746/pega_watchdog
25unix 2 [ ] DGRAM 1954 620/chronyd
26unix 2 [ ] DGRAM 2336 759/prog_mediaserve
27unix 2 [ ] DGRAM 2040 745/pega_wifilog Firmware update analysis
The camera checks for updates at:
https://updates.arlo.com/arlo/fw/fw_deployed/production/updaterules/VMC2040_UpdateRules.json
Which points to:
binaries/VMC2040/VMC2040_OTA-1.22.0.0_33_53d2844_f5c0b43.prod.enc
The .enc extension indicates the firmware package is encrypted. distribution.
The dev branch
Swapping production for dev in the update URL is publicly accessible:
https://updates.arlo.com/arlo/fw/fw_deployed/dev/binaries/VMC2040/VMC2040_OTA-1.24.0.0_61_11739de_f079ad8.dev.enc
Development firmware (version 1.24.0.0) is available to anyone who knows the URL. Whether this is intentional or an oversight I don't know.
Summary
This part only focuses on gathering information about the system, and there are still many things to analyze. In part5 I will go through a few things that I tried but that didn't work so well.