navigationMode: linear
---
-## Structure
-<!-- structure: start with a problem and reproduce the work leading to the working solution -->
-
-
-- Start with the problem
-- Work our way to the solution step by step
-
-::: notes
-
-This is my note.
-
-- It can contain Markdown
-- like this listt
-
-:::
-
-
-
<!-- access smart home hw on crime scenes -->
<!-- many shelly devices are based on esp32/esp8266 -->
<!-- they dont contain any usable data but contain identifiable user data -->
<!-- they are also complex, making understanding and changing the code time consuming -->
<!-- what about writing a custom extraction tool? -->
+## Introduction
+
+- Part of Project FIENDISH
+- Automatically extracts files from ESP-based Shelly smart home devices
+- Can run on a Raspberry Pi or a micro controller
+
+::: notes
+- Forensische Extraktion von IoT-Daten im Smart-Home
+- Also supports Linux but no GPIO
+- Right now supports ESPs but any MCU with enough memory could theoretically be used
+:::
+
+##
+
+{style="height: 50vh;"}
+
## The Problem
How to access data on Shelly devices?
- Extract the flash memory and read the data
- Do it read-only and document the process
+::: notes
+- make the evidence usable in court
+- include timestamps, hash values of extracted data and mac addresses of devices
+:::
+
##
- Most Shelly devices are based on ESP micro controllers
-- Existing solutions (esptool, mos) can modify memory
+- Existing solutions (esptool, mos) can modify memory and are not fully automated
- They are very complex, and thus hard to modify
-- What about a custom tool?
+- How about a custom tool?
+
+::: notes
+- esptool by espressif
+- mos my cesanta/mongoose os
+- run mongoose os
+:::
- Two modes: boot and run
- Serial pins are exposed on some Shelly devices and accessible on others
- In boot mode they can be used to communicate using a custom protocol
-<!-- * So we need a serial connection and the ability to enter boot mode -->
+
+::: notes
+- So we need a serial connection and the ability to enter boot mode
+:::
+
+##
+
+{style="height: 50vh;"}
+
+::: notes
+- connect to pins for rx/tx and gpio0/rst
+:::
+
+##
+
+{style="height: 50vh;"}
+
+##
+
+{style="height: 50vh;"}
##
- Write RAM, flash and registers
- Configure memory etc.
- On the ESP32 it can read flash, but not on the ESP8266, ESP32C3 or ESP32C6
-- How do other tools read flash?
+::: notes
+- protocol provided by bootloader in rom
+:::
+
+##
+
+{style="height: 50vh;"}
+
+<small>https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html</small>
+
+::: notes
+- How do other tools read flash?
+:::
<!-- how do other tools read flash? -->
## Reading Flash Memory
- We cannot directly read flash, but we can write RAM
-- Write a program for the ESP, load it into RAM and run
-- This is called flash loader or flasher stub
+- Write a program, load it into RAM and run it on the ESP
+- This program is called flash loader or flasher stub
- Esptool uses two versions:
- Legacy C version
- New Rust version
-##
-
-- C version is deprecated but it is much simpler and supports ESP8266
-- Customize this version by removing write and erase commands
-- Technically there is write access until the flash loader is activated
-- The extraction tool is small and contains no write or erase commands
+::: notes
+- flash loader speaks the same protocol as the boot loader
+- it knows more commands
+:::
##
-----------------------------------------------------------
```
+::: notes
+- we will get back to this later when we take a closer look at the flash loader
+:::
+
+##
+
+- C version is deprecated but it is much simpler and supports ESP8266
+- Customize this version by removing write and erase commands
+- Technically there is write access until the flash loader is activated
+- The extraction tool is small and contains no write or erase commands
+
+::: notes
+- this is as sure as we can be given that the rom includes write/erase cmds
+- a small tool such as this is easier to verify compared to a huge python project
+:::
+
<!-- how does the serial protocol work? -->
- Target sends a matching reply
::: notes
-Exceptions:
-
-- after loading flash loader it sends a slip frame on its own
-- after sync request 8 replies are sent
-- when reading flash using 0xd2 replies are not slip/request frames
+- SLIP = Serial Line IP
+- Exceptions:
+ - after loading flash loader it sends a slip frame on its own
+ - after sync request 8 replies are sent
+ - when reading flash using 0xd2 replies are not slip/request frames
:::
+<!-- ┌────┐┌────┐┌────┐┌────┐ -->
+<!-- │ F6 ││ C0 ││ A0 ││ DB │ -->
+<!-- └─┬──┘└─┬──┘└──┬─┘└─┬──┘ -->
+<!-- ┌────┘ │ │ │ -->
+<!-- │ ┌─────┤ │ ├──────┐ -->
+<!-- │ │ │ │ │ │ -->
+<!-- ▼ ▼ ▼ ▼ ▼ ▼ -->
+<!-- ┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐ -->
+<!-- │ C0 ││ F6 ││ DB ││ DC ││ A0 ││ DB ││ DD ││ C0 │ -->
+<!-- └────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘ -->
+
+##
+
+{style=""}
+
+##
+
+{style="background-color:white;"}
+{style="background-color:white;"}
+
+<small>https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html</small>
+
+
## Steps to Read Flash
- Sync
- Read Flash
::: notes
-Starting from boot mode
-sync always at 115200 but esp detects other baud rates from known payload
+- Starting from boot mode
+- sync always at 115200 but esp detects other baud rates from known payload
+- mac for logging/verification purposes
+- baud rate for speed
:::
stub_write_flash.c // write flash (remove)
```
+::: notes
+- plus some headers and linker scripts
+- containing where the sections go and where standard functions are in memory
+:::
+
<!-- compiling and uploading the flash loader -->
- This includes section's sizes, addresses and the entry point
- Upload the corresponding loader after identifying the chip
+::: notes
+- toolchains are downloaded automatically from the Makefile
+- proprietary forks of gcc and clang, only available as binary downloads
+:::
+
+##
+```c
+const unsigned char *elf_esp32_text_buffer =
+ (unsigned char[]){0x08,0x00,0xf4,...};
+const unsigned long elf_esp32_text_size = 2100;
+const unsigned long elf_esp32_text_addr = 1074520064;
+
+const unsigned char *elf_esp32_data_buffer =
+ (unsigned char[]){0x9b,0xe6,0x0b,...};
+const unsigned long elf_esp32_data_size = 60;
+const unsigned long elf_esp32_data_addr = 1073561756;
+
+const unsigned long elf_esp32_entry = 1074521000;
+```
+
+
+
+<!-- differences between esp versions -->
+<!-- - identification: -->
+<!-- - ESP32-C3 and later use GET_SECURITY_INFO which contains a chip_id -->
+<!-- - previous models have a register with a magic value identifying the chip -->
+<!-- - mac address: -->
+<!-- - different registers -->
+<!-- - esp8266 mac has to be calculated -->
+<!-- - different flash loader versions -->
+<!-- - esp8266 has no data section -->
+
+## Different ESP Versions
+
+- ESP32-C3 and later are identified using `GET_SECURITY_INFO` command
+- Earlier versions have a register with a magic value
+- Try security info first and reset on failure
+- Different registers containing MAC address
+
+::: notes
+- sec info first bc it fails with unknown command
+- read register is a known command
+- reset -> bootmode -> sync again
+- on ESP8266 mac has to be calculated
+- esp8266 has no data section when compiling flash loader
+:::
+
<!-- and how do we make the esp enter bootmode? -->
- Supported when using Raspberry Pi or ESP as host
::: notes
-For development also possible via USB on linux hosts
+- default high for rst and gpio0
+- rst = en
+- For development also possible via USB on linux hosts
:::
::: notes
what is left:
-- differences between esp versions
- how to extract files
- what is on the files?
:::
-<!-- differences between esp versions -->
-<!-- - identification: -->
-<!-- - ESP32-C3 and later use GET_SECURITY_INFO which contains a chip_id -->
-<!-- - previous models have a register with a magic value identifying the chip -->
-<!-- - mac address: -->
-<!-- - different registers -->
-<!-- - esp8266 mac has to be calculated -->
-<!-- - different flash loader versions -->
-<!-- - esp8266 has no data section -->
-
-## Different ESP Versions
-
-- ESP32-C3 and later are identified using `GET_SECURITY_INFO` command
-- Earlier versions have a register with a magic value
-- Try security info first and reset on failure
-- Different registers containing MAC address
-
-::: notes
-- sec info first bc it fails with unknown command
-- read register is a known command
-- reset -> bootmode -> sync again
-- on ESP8266 mac has to be calculated
-- esp8266 has no data section when compiling flash loader
-:::
-
-
-
<!-- extracting the file system -->
<!-- - esp8266 -->
<!-- - esp32 -->
- On newer devices file system is found using metadata
- Files can be extracted using specialized tools
+::: notes
+- find filesystems in extracted data blobs
+- tooling dependant on device version
+ - spiffs for 8266 littlefs for 32
+ - spiffs depends on the exact configuration used by mongoose os
+:::
+
<!-- interesting files -->
}
```
+::: notes
+- plain text wifi credentials
+- cloud server (mitm)
+- jwt which links the esp to a shelly cloud account
+:::
+
#### `shelly_cloud.pem`
```txt
-----END CERTIFICATE-----
```
+::: notes
+certificate verifying shelly cloud server
+:::
+
## Thank You