Furbo2
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-file aplay
|
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
.