Furbo2

From Leo's Notes
Last edited on 25 October 2023, at 05:43.

Some notes on the Fubo2 treat thrower.

The Furbo2 is based on the Ambarella S2Lm IronMan Board. It has 128MB NAND flash. It appears to have a 2Gbit DDR3 memory chip but the system only shows 110MB available.

Hacking the Furbo2

Exploit the RTSP server

See Somerset Recon's blog post on this: https://www.somersetrecon.com/blog/2021/hacking-the-furbo-part-1

The GitHub repo with the presentation and exploit code is available at: https://github.com/Somerset-Recon/furbo-research

Enabling root access

In order to log in as root on the serial console, you'll have to first set the root password. Initially, the root password is set to something unknown. To work around this, you'll have to use the RTSP server exploit to get a root shell and then run echo -e "root\nroot" | passwd root.

You may try to boot into the system using init=/bin/sh by connecting the UART, then hold down [enter] while powering on the device to get into the Ambarella bootloader. Once in the bootloader, run:

amboot>  boot console=ttyS0 ubi.mtd=lnx root=ubi0:rootfs rw rootfstype=ubifs init=/bin/sh video=amb0fb:720x480,720x480,1,0

You'll be dropped into a shell as root and you may try to run passwd as root to set the new root password. You can also set the passwords for the other accounts as well. This method doesn't seem to update the password expiry value and causes the login to fail with 'token manipulation error'.

Stop Furbo2 services

The Furbo2 systemd service seems to be responsible for starting the primary Furbo daemon that's responsible for phoning home to Furbo's servers and allowing your phone app to work. This service also sets up the WiFi interface.

Since my plan is to have the device 'offline' from the Internet, I disabled the furbo2 service and replaced the WiFi setup functionality with another systemd service. I noticed that something still triggers the furbo2 service even when it's disabled, so you'll have to stop this service when the device starts for the first 30 or so seconds.

Enable telnetd

The busybox version that's bundled has the telnetd applet. Enable the telnetd backdoor with this service file:

[Unit]
Description=Very important backdoor.

[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/bin/busybox telnetd -F -l /bin/bash

[Install]
WantedBy=multi-user.target

Keep in mind that this is wildly insecure.

Enable dropbear / sshd

Use the statically compiled version of dropbear for ARMv7 from https://github.com/mzpqnxow/arm-dropbear-static. Copy the binary to /usr/bin/dropbear and then add the following systemd service file:

[Unit]
Description=Dropbear SSH Server
After=network.target

[Service]
Type=simple
ExecStartPre=/bin/mkdir /tmp/dropbear
ExecStart=/usr/bin/dropbear -F -P /run/dropbear.pid -R

[Install]
WantedBy=multi-user.target

That should open port 22 for SSH access. Access the system using your root account credentials.

RTSP access

The RTSP server is available on port 554. Use /stream0 for 1080p, /stream1 for 720p, /stream2 for 360p.

Disabling the overlay image

The Furbo logo is an overlay which is added from the image at /usr/share/oryx/video/overlay/FurboLogo{360,720,1080}p.bmp files.

To disable it, edit /etc/oryx/video/overlay.acs. which contains the definitions for each of the streams. Comment out the 'area1' sections by prepending a double dash.

Furbo scripts

There are a bunch of Furbo/Ambarella scripts under /usr/local/bin. Some noteworthy scripts are listed below:

Script Function Usage
fb_aplay.sh Plays an audio clip. Wrapper around aplay. fb_aplay.sh audio-input-fileaplay
fb_arecord.sh Records from onboard microphone fb_arecord.sh audio-output-file duration
fb_led.sh Sets the LED color fb_led.sh <color>
fb_icr.sh Controls the IR led fb_icr.sh day|night
fb_toss_loop.sh Triggers the toss functionality fb_toss_loop.sh 1

Other notes

The whole Furbo2 system seems quite disorganized and unpolished. There are a lot of test/dev scripts that are on the system and a lot of Ambarella SDK files on the filesystem.

Here are some files of interest for further tinkering:

  • WiFi settings are saved at: /etc/furbo_ap.info, /dev/adc/furbo_ap.info
  • Furbo API endpoint defined at: /dev/adc/furbo_endpoint_url
  • The RTSP password is set in /dev/adc/furbo2_rtsp.password and appears to be a 6 character [a-zA-Z0-9] password.
  • /dev/adc/CloudCamUpgrade.7z contains the ubifs filesystem (64MB).
  • The reset button on the rear is connected to GPIO53. Read it using while true ; do cat /sys/class/gpio/gpio53/value ; sleep 1 ; done.
  • Use amixer to set the volume. Eg: amixer set Master 50%.
  • The media service will record to /tmp/video/0. This can be disabled by editing /etc/oryx/stream/muxer/muxer-mp4-0.acs and make it not auto-start or set the disk space threshold sufficiently high.

Troubleshooting

Corrupt UBIFS

The Furbo2 unit I was working with had periods of unresponsiveness.

After getting root access via the serial UART, it was clear what the cause for this was. The UBIFS was corrupt and certain files were entirely unreadable. When such an error occurs, the CPU gets pegged and a kernel error gets printed to the console. Here's an example of one of those errors.

[  805.549949] ambarella-nand e0001000.nand: nand_amb_request: dma_status=0x05000800, cmd=0xe, addr_hi=0x0, addr=0x6d51800, dst=0x0, buf=0x69e3000, len=0x800, area=0x2, ecc=0x2, block addr=0x6d40000!
[  805.591063] UBI warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 725:4096, read only 126976 bytes, retry
[  805.609732] ambarella-nand e0001000.nand: nand_amb_request: dma_status=0x05000800, cmd=0xe, addr_hi=0x0, addr=0x6d51800, dst=0x0, buf=0x69e3000, len=0x800, area=0x2, ecc=0x2, block addr=0x6d40000!
[  805.633049] UBI warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 725:4096, read only 126976 bytes, retry
[  805.666476] ambarella-nand e0001000.nand: nand_amb_request: dma_status=0x05000800, cmd=0xe, addr_hi=0x0, addr=0x6d51800, dst=0x0, buf=0x69e3000, len=0x800, area=0x2, ecc=0x2, block addr=0x6d40000!
[  805.694074] UBI warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 725:4096, read only 126976 bytes, retry
[  805.715750] ambarella-nand e0001000.nand: nand_amb_request: dma_status=0x05000800, cmd=0xe, addr_hi=0x0, addr=0x6d51800, dst=0x0, buf=0x69e3000, len=0x800, area=0x2, ecc=0x2, block addr=0x6d40000!
[  805.740404] UBI error: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 725:4096, read 126976 bytes
[  805.757653] CPU: 0 PID: 13579 Comm: systemd-coredum Tainted: P           O 3.10.73+ #1
[  805.774193] [<80012424>] (unwind_backtrace+0x0/0x118) from [<80010ca4>] (show_stack+0x10/0x14)
[  805.784910] [<80010ca4>] (show_stack+0x10/0x14) from [<80223a98>] (ubi_io_read+0x20c/0x31c)
[  805.794399] [<80223a98>] (ubi_io_read+0x20c/0x31c) from [<80221294>] (ubi_eba_read_leb+0x328/0x454)
[  805.804256] [<80221294>] (ubi_eba_read_leb+0x328/0x454) from [<8021ffe8>] (ubi_leb_read+0x110/0x170)
[  805.814064] [<8021ffe8>] (ubi_leb_read+0x110/0x170) from [<8012c568>] (ubifs_leb_read+0x24/0x80)
[  805.824539] [<8012c568>] (ubifs_leb_read+0x24/0x80) from [<80134e64>] (ubifs_start_scan+0xa4/0x120)
[  805.834996] [<80134e64>] (ubifs_start_scan+0xa4/0x120) from [<801351b8>] (ubifs_scan+0x28/0x33c)
[  805.847428] [<801351b8>] (ubifs_scan+0x28/0x33c) from [<80139fb8>] (ubifs_garbage_collect_leb+0x1d4/0x764)
[  805.862859] [<80139fb8>] (ubifs_garbage_collect_leb+0x1d4/0x764) from [<8013a7b8>] (ubifs_garbage_collect+0x270/0x620)
[  805.882061] [<8013a7b8>] (ubifs_garbage_collect+0x270/0x620) from [<8013d034>] (ubifs_budget_space+0x5e8/0x810)
[  805.903137] [<8013d034>] (ubifs_budget_space+0x5e8/0x810) from [<80123758>] (ubifs_write_begin+0x398/0x528)
[  805.926206] [<80123758>] (ubifs_write_begin+0x398/0x528) from [<80065698>] (generic_file_buffered_write+0xd0/0x240)
[  805.938495] [<80065698>] (generic_file_buffered_write+0xd0/0x240) from [<80066ba8>] (__generic_file_aio_write+0x3c4/0x3e4)
[  805.962743] [<80066ba8>] (__generic_file_aio_write+0x3c4/0x3e4) from [<80066c1c>] (generic_file_aio_write+0x54/0xb4)
[  805.994949] [<80066c1c>] (generic_file_aio_write+0x54/0xb4) from [<80123df4>] (ubifs_aio_write+0x164/0x17c)
[  806.005759] [<80123df4>] (ubifs_aio_write+0x164/0x17c) from [<80090ef0>] (do_sync_write+0x74/0x98)
[  806.016082] [<80090ef0>] (do_sync_write+0x74/0x98) from [<800915c0>] (vfs_write+0xd0/0x170)
[  806.025470] [<800915c0>] (vfs_write+0xd0/0x170) from [<80091a7c>] (SyS_write+0x3c/0x64)
[  806.034319] [<80091a7c>] (SyS_write+0x3c/0x64) from [<8000e180>] (ret_fast_syscall+0x0/0x30)
[  806.047018] UBIFS error (pid 13579): ubifs_check_node: bad CRC: calculated 0x7bb81e99, read 0x63c69111
[  806.062566] UBIFS error (pid 13579): ubifs_check_node: bad node at LEB 547:68928
[  806.076638]  magic          0x6101831
[  806.080400]  crc            0x63c69111
[  806.084186]  node_type      1 (data node)
[  806.088208]  group_type     0 (no node group)
[  806.092561]  sqnum          1770285
[  806.096029]  len            3518
[  806.099258]  key            (6219, data, 6)
[  806.103418]  size           4096
[  806.106685]  compr_typ      1
[  806.109658]  data size      3470
[  806.112864]  data:
[  806.114867]  00000000: 00 0a c0 f2 01 01 00 95 c0 f2 01 00 40 f2 bc 63 42 4a fc f7 70 ef 63 e7 45 f6 f8 21 03 46 6c 03
[  806.125547]  00000020: 00 06 2a 46 03 20 fc f7 da ee 44 f2 64 11 45 f6 20 30 40 f2 c5 63 cd f8 04 a0 6d 03 00 9c 06 00
[  806.136225]  00000040: 06 35 4a fc f7 56 ef 4b f2 d1 13 cf f6 ff 73 9e 42 85 d1 45 f6 54 31 06 20 64 04 0d fc f7 be ee
[  806.146906]  00000060: 00 23 04 f8 28 3c 39 e7 45 f6 e8 21 f4 02 0a b2 ee 40 46 fc f7 0c ef 0b e7 45 f6 8c 27 ad 00 a8
[  806.157642]  00000080: cc 05 02 23 e7 45 f6 c4 27 55 00 9c d4 02 05 18 e7 45 f6 a0 11 87 22 7c 0a 6c 12 01 90 ee 87 23
[  806.168333]  000000a0: b4 12 09 cc 10 00 93 64 18 64 03 00 03 40 f2 8a 63 10 4a fc f7 0e ef 00 20 fc f7 3c ed 45 f6 24
[  806.179071]  000000c0: 21 22 84 19 6d 06 76 de 18 64 20 7e 05 00 94 a4 06 04 97 63 04 4a fc f7 f4 8c 12 00 1a 24 ed 00
[  806.189752]  000000e0: bf 14 42 4d 00 30 3f 01 00 2d e9 f0 4f 41 f2 24 78 c0 f2 02 08 2d ed 04 8b ad f5 96 2d 98 f8 18
[  806.200428]  00000100: 30 99 b0 4b b9 45 f6 2c 40 6c 08 00 02 fc f7 84 ed c8 20 fc f7 30 ef fb e7 44 f2 54 41 08 f1 18
...
[  807.183977]  00000c80: ef 6c 02 a6 12 34 20 94 78 9c c2 0b 01 93 40 f2 72 73 47 4a fc f7 24 e8 f3 e5 fe 0b 30 46 28 84
[  807.194652]  00000ca0: 01 01 fd f7 dd fe 7c 2a 0f fc f7 b0 e8 30 46 fb f7 c6 ef 46 f2 68 21 33 46 3b 4a 6c 1a 04 06 20
[  807.205327]  00000cc0: fb f7 7c ef d6 35 e5 00 c0 c5 07 92 84 07 06 aa ef 46 f2 ac 21 33 46 2c 27 e4 00 01 5e ef b9 e5
[  807.216017]  00000ce0: b6 20 0a 90 fc 15 05 fb f7 54 ef dd f8 28 c0 6c 15 6c 21 74 0c 9c 15 0e 00 cd f8 04 c0 40 f2 65
[  807.226704]  00000d00: 73 1b 4a fb f7 ce ef 23 e7 f4 15 28 34 3b 28 d4 02 0d fb f7 30 ef 30 46 fd f7 7f fe 88 e5 46 f2
[  807.237380]  00000d20: cc 11 74 1f 64 09 09 32 46 06 20 be 62 fb f7 22 ef 7c e5 6e 25 7c 11 74 02 0c 06 20 27 71 fb f7
[  807.248082]  00000d40: 18 ef 67 e6 00 27 46 f2 a4 29 4c 00 01 0e ef 5d e6 8c 49 08 41 01 00 70 b5 48 f6 48 71 14 4c 64
[  807.258776]  00000d60: 06 00 16 07 20 4f f0 ff 35 12 4a 04 f5 ae 66 fb f7 fa ee 74 22 00 21 a4 f1 2c 00 fb f7 52 ee 05
[  807.269465]  00000d80: 23 44 f8 2c 5c 44 f8 1c 5c 20 46 11 00 00

I suspect the flash is beginning to go bad on the device. It's not a surprise since core dumps are generated and saved on the flash memory and we were triggering the RTSP server to crash over and over. ☹

Fixing the broken filesystem

The only way to really fix this is just to delete the broken files. One possible way to find out which files are unreadable on this BusyBox environment is to run:

# find . -type f | while read i ; do echo $i ; cat "$i" > /dev/null || break ; done

Whenever an IO error occurs, find the last file which triggered the issue and delete it.

A few things were bad on my device: hostapd, pjsua-arm-unknown-linux-gnueabihf, test_tuning, tfp2pd. tfp2pd is described as 'Furbo P2P service" by its systemd service file and is used by the Furbo servers to allow your phone to interact with the Furbo. Unfortunately for me, since the binary is restarted periodically, the Furbo also ends up hanging periodically as tfp2pd is restarted and triggers IO errors.

Fortunately, nothing critical for the OS (like the kernel, or some kernel module) was corrupt. The broken files should be recoverable if you extract it from /dev/adc/CloudCamUpgrade.7z.