Skip to content
HN On Hacker News ↗

A story of wifi secrets, UART lockdowns and a damaged flash memory chip |

▲ 95 points • 7 comments • by michidk • 3w ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this text is a mix of AI and human-written content.

23 %

AI likelihood · overall

Mixed
76% human-written 24% AI-generated
SEGMENTS · HUMAN 1 of 1
SEGMENTS · AI 0 of 1
WORD COUNT 1,394
PEAK AI % 0% · §1
Analyzed
Oct 16
backend: pangram/v3.3
Segments scanned
1 windows
avg 1394 words each
Distribution
76 / 24%
human / AI fraction
Verdict
Mixed
Pangram v3.3

Article text · 1,394 words · 1 segments analyzed

Human AI-generated
§1 Human · 0%

Dear Fellowlship, just as we announced in our previous post, our beloved God Debugger has seen fit to cast his divine light -laden with opcodes- upon his humble servant, and we have a new homily here in our temple. Please, take a seat and listen to the story of how one of our owls, along with his brother-in-law, moved on to dissect the next component of the Eufy ecosystem: the Eufy HomeBase 2. Prayers at the foot of the Altar a.k.a. disclaimer We focused our analysis in Eufy Homebase2 instead of Homebase3 because, as we explained in From your doorbell to your home network it’s the version that I found deployed in my city, and also was the easiest to buy. The firmware version we analyze here is 3.4.2.2h (2026-06-05 18:45:48) This is the first time I touched something related to “hardware”. I always did vuln hunting on firmwares that I could download from internet, so please forgive the sins I commited IMPORTANT!!! You must read first the previous article before you continue reading this one. Table of contents Just as with the previous article, we will be covering a variety of topics here; consequently, some members of this fellowlship may have no interest in certain sections and might wish to skip straight to whatever appeals to them most. That is why we present this blessed offering: a table of contents. 0x00 Firmware extraction. Description of how the firmware was extracted (and how we damaged part of the flash memory). 0x01 Identifying the Wifi credential generation algorithm. Reverse Engineering the algorithm used to generate the Wifi credential for OCEAN_XXXXXX management wifi. 0x02 Rubber-hose treatment to the UART lockdown. Reflashing a backdoored U-Boot image to get a shell via UART. 0x03 Filesystem gardening for debugging purposes. Recovery image is limited so some filesystem quirks are needed in order to run the main binary. 0x04 Final Words. I share the lack of enthusiasm for writing articles in the age of AI. In the previous chapter of this saga, I mentioned that we were only able to extract the doorbell’s firmware because the Homebase’s flash memory was soldered directly to the board and did not expose any pins to which we could attach test hooks to dump the firmware. Initially we did not want to desolder it (although in the end we had to as I will explain later) so I had to wait to acquire additional hardware. Craig S. Blackie pointed me to spring clips that would suit the size needed for the Winbond 25Q256JWEQ (WSON8 8.6mm). Once the clip arrived I created the most makeshift setup imaginable, using rubber bands to secure the clip while I proceeded to take readings using the Raspberry Pi’s SPI0 interface, just as we did with the doorbell. Setup using rubber bands to read the firmware. I performed three reads and the three had different checksums, which usually is a indicator of something being wrong. After inspecting the dumps, I quickly realized they were garbage and completely useless. Unlike with the doorbell, in this case, the power supplied for the read operation also activated other components on the board that interacted with the memory; therefore, to extract the firmware, we had to desolder the chip and read it off-board. My brother-in-law (Óscar Lestón) was the brave soul that desoldered the flash memory (I was too scared to even try it): Desoldering Although the memory module looked terrible once removed, it was barely damaged… Extracted flash memory And finally we replicated the same setup using the Raspberry Pi SPI 0 to dump the firmware. This time the three dumps had the same checksum and contained “interesting data”. The only problem was… a block of 64kbs was erased / could not be read, highly probable because we damaged it when extracting the chip. Using the Raspberry Pi to read the chip off-board Most of the firmware could be extracted using Binwalk. /home/psyconauta/research/Eufy/homebase2-firmware/chipoff/STUFF/extractions/homestation2_firmware00.bin ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- DECIMAL HEXADECIMAL DESCRIPTION ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 83328 0x14580 U-Boot version string: 1.1.3 (Jun 14 2023 - 16:18:56) 3022226 0x2E1D92 XZ compressed data, total size: 11514432 bytes 14536660 0xDDCFD4 XZ compressed data, total size: 2200 bytes 14538862 0xDDD86E XZ compressed data, total size: 2084 bytes 14540948 0xDDE094 XZ compressed data, total size: 1868 bytes 14542818 0xDDE7E2 XZ compressed data, total size: 168 bytes 14542988 0xDDE88C XZ compressed data, total size: 4192 bytes 14547182 0xDDF8EE XZ compressed data, total size: 2844 bytes 14550028 0xDE040C XZ compressed data, total size: 244 bytes 14550282 0xDE050A XZ compressed data, total size: 1452 bytes 15138816 0xE70000 uImage firmware image, header size: 64 bytes, data size: 3429849 bytes, compression: lzma, CPU: MIPS32, OS: Linux, image type: OS Kernel Image, load address: 0x80000000, entry point: 0x802E04F0, creation time: 2023-06-14 12:56:37, image name: "Linux Kernel Image" 21233664 0x1440000 JFFS2 filesystem, little endian, nodes: 3426, total size: 12255244 bytes Some parts were recovered, others no. Because there was a lot of XS streams, we choose the stupid (or maybe not so stupid) idea of using directly 7z to extract all in a big blob (and hopefully search by needles there to carve files). ➜ extractions mkdir -p 7z_mandanga ➜ extractions 7z e -y -o7z_mandanga homestation2_firmware00.bin 7-Zip 23.01 (x64) : Copyright (c) 1999-2023 Igor Pavlov : 2023-06-20 64-bit locale=es_ES.UTF-8 Threads:16 OPEN_MAX:1024 Scanning the drive for archives: 1 file, 33554432 bytes (32 MiB) Extracting archive: homestation2_firmware00.bin ERRORS: There are data after the end of archive -- Path = homestation2_firmware00.bin Type = xz ERRORS: There are data after the end of archive Offset = 3022226 Physical Size = 11514432 Tail Size = 19017774 Method = LZMA2:17 Streams = 358 Blocks = 358 Characteristics = BlockPackSize BlockUnpackSize ERROR: There are some data after the end of the payload data : homestation2_firmware00 Sub items Errors: 1 Archives with Errors: 1 Open Errors: 1 Sub items Errors: 1 ➜ extractions ls -hal 7z_mandanga total 42M drwxrwxr-x 2 psyconauta psyconauta 4,0K sep 19 19:41 . drwxrwxr-x 4 psyconauta psyconauta 4,0K sep 19 19:34 .. -rw-rw-r-- 1 psyconauta psyconauta 42M sep 19 18:35 homestation2_firmware00 0x01 Identifying the Wifi credential generation algorithm One of the key questions we wanted to investigate via the firmware was the new algorithm for generating credentials for the OCEAN_XXXXXX management Wi-Fi, as we observed that it differed completely from what was expected based on the 2024 paper. Specially, we were interesting in know if the algorithm was weak as previously or no. After writing the previous article, I realized I had failed my brother-in-law as a mentor. I had shown him how to use Ghidra and pseudo-C instead of leading him down the path of light and reason. I atoned for my sin and drew radare2. First we checked where the Wifi network ESSID and password could be found in the firmware. A simple grep was enough to identify NVRAM variables containing both wifi names and credentials (the ad-hoc wifi used to enroll the doorbell and the mangement wifi): ➜ extractions strings homestation2_firmware00.bin_83358_unknown.raw | grep F1VSXfNQL_ZCd3k -A5 -B5 AuthMode=WPAPSKWPA2PSK;WPAPSKWPA2PSK EncrypType=AES;AES RekeyInterval=3600 RekeyMethod=TIME PMKCachePeriod=10 WPAPSK1=F1VSXfNQL_ZCd3k WPAPSK2=913ceac3 DefaultKeyID=2;2 Key1Type=0 Key1Str1= Key2Type=0 ➜ extractions strings homestation2_firmware00.bin_83358_unknown.raw | grep OCEAN_E9A5FC -A5 -B5 DDNSPassword= CountryRegion=0 CountryRegionABand=7 CountryCode=ES BssidNum=2 SSID1=OCEAN_E9A5FC SSID2=4350c372 WirelessMode=9 TxRate=0 Channel=0 BasicRate=15 Then we tried a more broad search to try to identify binaries and/or scripts related to the wifi setup: ➜ 7z_mandanga strings homestation2_firmware00 | rg 'OCEAN_' %s,<%d>file not exist.return OCEAN_TEST_TF_CARD_NOT_FOUND. OCEAN_MAGIC out of memory of OCEAN_TEST_DATA OCEAN_TF_CARD_FORMAT_SUCCESSED OCEAN_TF_CARD_FORMAT_FAIL_MOUNT OCEAN_TF_CARD_FORMAT_FAIL OCEAN_TF_CARD_FORMAT_IN_USE ssid_prefix="OCEAN_" ssid_prefix="OCEAN_" CONFIG_LEDS_OCEAN_PWM=y OCEAN_RUN=/mnt/ocean.sh if [ -f $OCEAN_RUN ];then chmod +x $OCEAN_RUN sh $OCEAN_RUN & Unraveling a bit more this thread we found an interesting line that matches what we already knew: the ESSID is the concatenation of “OCEAN_” and MAC address: ➜ 7z_mandanga strings homestation2_firmware00 | rg 'ssid_prefix' ssid_prefix="ocean_factory_" ssid_prefix="OCEAN_" WIFI_SSID=$ssid_prefix$SSID_MAC ssid_prefix="`nvram_get ssid_pre`" if [ "$ssid_prefix" = "" ];then ssid_prefix="OCEAN_" WIFI_SSID=$ssid_prefix$SSID_MAC Let’s zoom out to get the full script: ➜ 7z_mandanga strings homestation2_firmware00 | rg 'ssid_prefix' -B30 -A40 .sdata .sbss .bss .pdr .gnu.attributes .mdebug.abi32 #!/bin/sh work_mode="`cat /var/run/testmode`" def_mode="`nvram_get 2860 work_mode`" SSID_MAC="" nvram_ssid="`nvram_get 2860 SSID1`" bssid_num=`nvram_get 2860 BssidNum` eth_state=`apcliDaemon get_eth_state` repeater_enable=`nvram_get 2860 RepeaterEnable` wifi_11bgn_enabled=`nvram_get 2860 wifi_11bgn_enabled` Wireless_Mode=9 if [ "$eth_state" = "0" -a "$repeater_enable" = "1" -a "$wifi_11bgn_enabled" = "1" ]; then Wireless_Mode=9 get_wifi_mac() SSID_MAC="`ifconfig ra0 | grep HWaddr | awk '{print $5}' | awk -F ':' '{print $4$5$6}'`" #SSID_MAC="`ifconfig ra0 | grep HWaddr | awk '{print $5}' | awk -F ':' '{print $5$6}'`" while [ "$SSID_MAC" = "" ] sleep 1 SSID_MAC="`ifconfig ra0 | grep