Erdu lighting - erdu
The full file list that I know of is here:GET /ajax-loader.gifGET /aws_iot/privKeyGET /aws_iot/pubCertGET /aws_iot/regionGET /aws_iot/thingGET /aws_starter.js.gzGET /common.js.gzGET /custom.css.gzGET /favicon.icoGET /icons-18-black.pngGET /icons-18-white.pngGET /icons-36-black.pngGET /icons-36-white.pngGET /index.html.gzGET /jquery.js.gzGET /jquery.mobile.css.gzGET /jquery.mobile.js.gzGET /prov.js.gzGET /reboot.js.gzGET /server_cert.pemGET /server_key.pemGET /signal0L.pngGET /signal0.pngGET /signal1L.pngGET /signal1.pngGET /signal2L.pngGET /signal2.pngGET /signal3L.pngGET /signal3.pngGET /sysGET /sys/connectionGET /sys/interfaceGET /sys/modeGET /sys/networkGET /sys/scan (returns 404 but is mentioned in .js files)GET /sys/servicesGET /sys/timePOST /sys/commandPOST /sys/prov_status
Investigating these URLs and the file system led me to some conclusions. First, the file system is very basic. There’s an initial catalog section containing file names, their size, and start location. Following that are all the files. The catalog has no directory structure. It’s entirely flat. Any URLs starting with /sys are handled by a WSGI server. I’m assuming that’s true for /aws_iot URLs as well. Any plain text URLs are stored in gzip form. Requesting the unzipped file name or the .gz file name results in the gzipped version of the file.
All trademarks and registered trademarks appearing on ProductFrom.com are the property of their respective owners.
I thought the 3 parts were relevant some how. I decided to make a byte map of the entire flash dump. I opened up Google Sheets and started mapping out the bytes in the flash dump beginning with what I knew, and researched what I didn’t (partial screenshot below).
In the end, I came to a startling and disappointing conclusion. Parts 1 and 3 were just sample file systems that were either left in the project or left on the chip. Part 2 (the second occurrence of 88888888) contained all the real files and binaries needed.
2. Up-to-date It is almost impossible to always have up-to-date information about the country of origin of a particular product. We are unable to constantly trace each product if it still manufactured in the same location as before. The production site of a particular product can change over time and we may not be able to reflect that change in a timely manner. Each product has information about the date it was added or updated. The place of production may have changed since then or new place may have been added. We collect data for several years and part of our data can be outdated. Some products can be no longer manufactured. Place of production of some other products may have changed.
0x00258000 WLFW Wireless Firmware (XZ) 157,448 of 294,912 (again but different)0x002a1000 8888 File System, 3rd 157,694 of 196,608 bytes (sample)0x002d1000 Other 88 of 1,241,088 bytes
The actual CA cert is evident in the flash dump using “strings”, “binwalk”, or “hexdump”. I validated it against the cert and key returned by the cert and key URLs and they validated successfully. I believe this is the last piece of info needed to mimic the device and make calls to AWS IoT service. Although all the other info was retrievable unauthenticated over the WLAN, the CA cert was only retrievable by hands-on access with flashdump. Therefore, I still see this as a device that leaks info but doesn’t have any remotely accessible vulnerabilities.
…could do more than just reboot. Having the Marvell app converted to elf let me load it up in Ghidra successfully. A string search led to the right function, and a few minutes later I had my answer. Literally the only command it accepts is “reboot”. I was a bit disappointed but very happy to have gone through the process and learned so much.
ProductFrom.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to amazon.com. As an Amazon Associate Productfron.com earns from qualifying purchases.
Dumping the firmware led to more system URLs that weren’t obvious by just viewing the source. Here’s a what I know about them:
3. Reliability & Liability This site is for informational purposes only. We do not pretend to be the comprehensive or ultimate source of information. We are rather trying to show a broader picture and a structure of the production across the world. We do our best to ensure that the information is accurate and up to date, but this is not always possible. Since the vast majority of producers do not want to cooperate with us, we have to rely on other sources of information, the credibility of which may vary. Therefore, we cannot guarantee that our data is 100% accurate and we cannot take any responsibility for this.
Another interesting tidbit, these Marvell models start with “88”. In the flash dump, there are three instances of a magic number “0x88888888”. I divided the flash dump into 3 parts based on the 0x88888888 magic number.
0x00030000 8888 File System, 2nd 138,553 of 196,608 bytes (real)0x00060000 WLFW Wireless Firmware (XZ) either 154,064 bytes or 299,008 bytes0x000a9000 Oddly spaced stuff either 1,549,864 bytes or 1,404,920 bytes0x00200000 MRVL App firmware 347,560 of 360,448 bytes
Requesting the URLs with curl -v showed me the web server calls itself “Marvell-MW”. Googling this led me to a project called MICOAPI. Comments in that project mention the same server name and show an example of the /sys/time URL’s output. Also the behavior of the .gz URLs is identical to how MICOAPI describes its behavior. There’s a pretty good chance this is the base code used for the WSGI server.
A few next steps jump out at me but I’m in no rush at this point. Instead, I’d rather take what I learned about firmware/flash static analysis and go back to my Zyxel project.
Part 1: 0x00000000 -> 0x00030000 (192 KB in size, 154 KB used)Part 2: 0x00030000 -> 0x002A1000 (2.5 MB in size, 2.4 MB used) Part 3: 0x002A1000 -> 0x04000000 (1.4 MB in size, 193 KB used)
Knowing the true file system, true wireless firmware, and the Marvell app firmware was a real breakthrough. I was then able to use firmware2elf to translate the Marvell app firmware into a normal Linux elf file and begin analysis!
See Part 1 for the history of this project and early findings. Part 2 is a journey into trying to reverse engineer embedded device firmware. It will be a brain dump of facts and assumptions as I analyze the Pro1 T701i Wifi Thermostat firmware.
First published July 4, 2022.Edited July 11, 2022 to include URL list, file system, and WSGI server details.Copyright © 2022 Gerry Gosselin
My intention is to responsibly disclose any exploitable vulnerabilities. Thus far my findings have been superficial or trivial for anyone with physical access to the device. Other than some minor information disclosure, I’ve found nothing that can be compromised remotely.
The T701i has an Atmel SAM D20 ARMv6 Cortex CPU. For storage it uses a Winbond 25Q32FVS1G 4MB flash chip. Using “strings” on the flash dump, there’s evidence there’s a Marvell 88W8782 wifi microcontroller onboard but that may not be accurate. I saw an AzureWave AW-CU282 on the board itself. It turns out the Marvell Avastar 88W8782 with Marvell Easy Connect (remember the github in the last article) was a first generation product. This device uses the Marvell 88WMC200 wifi microcontroller with a Cortex-M3. I think the Atmel SAM D20 is used for analog-digital conversion, like reading a temperature sensor, and used for controlling relays that turn on/off the environmental systems. Whereas the AzureWave microcontroller is for the web interface, wifi, and AWS IoT integration.
Neil
Neil