X-Git-Url: https://gitweb.ps.run/ouroboros-slides/blobdiff_plain/758f808544b19cfeee8fba9da045d06bd3357ea7..HEAD:/pres.md diff --git a/pres.md b/pres.md index 20c971e..7b3cec2 100644 --- a/pres.md +++ b/pres.md @@ -1,21 +1,13 @@ --- -title: Ourosboros Flash Reader +title: Ouroboros Flash Reader author: Patrick Schönberger date: 16.07.2025 transition: none revealjs-url: https://cdn.jsdelivr.net/npm/reveal.js@5.2.1 slideNumber: true +navigationMode: linear --- -## Structure - - - -- Start with the problem -- Work our way to the solution step by step - - - @@ -27,20 +19,48 @@ slideNumber: true +## 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 +::: + +## + +

+ ## The Problem -- How to access data on Shelly devices? -- Most Shelly devices are based on ESPs -- They don't contain usable data like logs -- They do contain user-identifiable data +How to access data on Shelly devices? ## - Extract the flash memory and read the data - Do it read-only and document the process -- Existing solutions (esptool, mos) can modify memory + +::: 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 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 +::: @@ -63,7 +83,27 @@ slideNumber: true - 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 - + +::: notes +- So we need a serial connection and the ability to enter boot mode +::: + +## + +

+ + +::: notes +- connect to pins for rx/tx and gpio0/rst +::: + +## + +

+ +## + +

## @@ -72,8 +112,20 @@ slideNumber: true - 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 +::: + +## + +

+ +https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html + +::: notes +- How do other tools read flash? +::: @@ -90,19 +142,94 @@ slideNumber: true ## 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 the flash loader or stub loader +- 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 +::: notes +- flash loader speaks the same protocol as the boot loader +- it knows more commands +::: + +## + +```txt +$ cloc esp-flasher-stub/ +----------------------------------------------------------- +Language files blank comment code +----------------------------------------------------------- +Rust 12 327 78 1863 +Logos 14 32 0 249 +YAML 3 34 12 214 +Markdown 1 34 0 89 +TOML 4 8 2 61 +----------------------------------------------------------- +SUM: 34 435 92 2476 +----------------------------------------------------------- +``` + +## + +```txt +$ cloc esp-hal +----------------------------------------------------------- +Language files blank comment code +----------------------------------------------------------- +Rust 492 18739 26120 115809 +Linker Script 51 499 1404 11315 +Markdown 66 2014 12 5262 +TOML 43 505 412 4481 +Logos 44 229 15 1105 +YAML 13 151 67 1054 +Jinja Template 3 52 0 255 +JSON 2 0 0 48 +CSV 3 0 0 21 +SVG 1 0 0 4 +----------------------------------------------------------- +SUM: 718 22189 28030 139354 +----------------------------------------------------------- +``` + ## -- The C version is getting replaced but it is much simpler and it supports ESP8266 -- We customize this version by removing write and erase commands -- This way we technically have write access until the flash loader is activated +```txt +$ cloc esptool-legacy-flasher-stub/ +----------------------------------------------------------- +Language files blank comment code +----------------------------------------------------------- +Linker Script 32 787 1188 18751 +C 6 1284 636 7689 +C/C++ Header 8 463 557 1687 +make 1 36 33 130 +YAML 4 19 0 114 +Python 2 25 21 80 +Markdown 3 58 0 76 +Bourne Shell 2 9 8 23 +TOML 1 1 0 20 +Jinja Template 1 4 2 14 +----------------------------------------------------------- +SUM: 60 2686 2445 28584 +----------------------------------------------------------- +``` + +::: 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 +::: + @@ -118,7 +245,56 @@ slideNumber: true ## Serial Protocol -- SLIP frames... +- Bytes are grouped using SLIP frames +- Host sends requests containing commands +- Target sends a matching reply + +::: notes +- 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 +::: + + + + + + + + + + + + +## + +![](img/slip.png) + +## + +![](img/packet_req.png) +![](img/packet_res.png) + +https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html + + +## Steps to Read Flash + +- Sync +- Identify Chip +- (Read MAC) +- (Change baud rate) +- Upload Stub +- Read Flash + +::: notes +- 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 +::: @@ -132,6 +308,26 @@ slideNumber: true + +## Modifying the Flash Loader + +- Consists mostly of six C files: + ```txt + miniz.c // compression + slip.c // slip + stub_commands.c // handle commands (modify) + stub_flasher.c // main program + stub_io.c // serial communication + 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 +::: + + + @@ -141,6 +337,64 @@ slideNumber: true + +## Uploading the Flash Loader + +- Compile using specific toolchains +- Extract text and data sections from resulting ELF file +- Generate header file that is compiled with the extraction tool +- 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; +``` + + + + + + + + + + + + + +## 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 +::: + + + @@ -148,94 +402,144 @@ slideNumber: true + +## Boot Mode + +- GPIO0 low at start +- Wire pins to RST and GPIO0 +- Pull both low +- Then pull RST high first and GPIO0 after +- Supported when using Raspberry Pi or ESP as host + +::: notes +- default high for rst and gpio0 +- rst = en +- For development also possible via USB on linux hosts +::: + + + - - - - - - - - - - - - - + +## Summary + +- Connect to serial and set to boot mode +- Use serial protocol to identify the chip +- Upload modified flash loader +- Extract + +::: notes +what is left: + +- how to extract files +- what is on the files? +::: + + + - - - - +## Extracting File Systems -## Demo +- SPIFFS/Littlefs +- Gen 1 devices have known layout +- 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 +::: -## cloc -## -```sh -$ cloc esp-flasher-stub/ ------------------------------------------------------------ -Language files blank comment code ------------------------------------------------------------ -Rust 12 327 78 1863 -Logos 14 32 0 249 -YAML 3 34 12 214 -Markdown 1 34 0 89 -TOML 4 8 2 61 ------------------------------------------------------------ -SUM: 34 435 92 2476 ------------------------------------------------------------ + + + + + +#### Shelly Plus 1 File System + +```txt +api_math.js +ca.pem // signing CA +conf0.json // empty configuration +conf3.json // initial configuration +conf9.json // current configuration +index.html.gz // web frontend +init.js +rpc_acl_auth.json // list of rpc endpoints +rpc_acl_no_auth.json +shelly_cloud.pem // Shelly Cloud certificate +shelly_plugin_api.js +storage.json // user data +tzinfo +updater.dat ``` -## +#### `conf9.json` + +```txt +{ + "wifi": { + "sta": { + "enable": true, + "ssid": "SSID", + "pass": "PASSWORD" + "last_bssid": "aa:17:5d:15:ae:03", + }, + }, + "shelly": { + "cloud": { + "enable": true, + "server": "192.168.112.231:6022/jrpc", + "token": "eyJhbGciOiJIUzI1NiIsInR..." + }, + }, + ... +} +``` -```sh -$ cloc esp-hal ------------------------------------------------------------ -Language files blank comment code ------------------------------------------------------------ -Rust 492 18739 26120 115809 -Linker Script 51 499 1404 11315 -Markdown 66 2014 12 5262 -TOML 43 505 412 4481 -Logos 44 229 15 1105 -YAML 13 151 67 1054 -Jinja Template 3 52 0 255 -JSON 2 0 0 48 -CSV 3 0 0 21 -SVG 1 0 0 4 ------------------------------------------------------------ -SUM: 718 22189 28030 139354 ------------------------------------------------------------ +::: notes +- plain text wifi credentials +- cloud server (mitm) +- jwt which links the esp to a shelly cloud account +::: + +#### `shelly_cloud.pem` + +```txt +Subject: O = Allterco +Not Before: Aug 4 12:03:41 2020 GMT +Not After : Aug 2 12:03:41 2030 GMT +-----BEGIN CERTIFICATE----- +MIICrTCCAZUCFCuIEEAQJOFLZuEtr/CWkvxi9YPAMA0GCSqGSIb3DQEBCwUAMBMx +ETAPBgNVBAoMCEFsbHRlcmNvMB4XDTIwMDgwNDEyMDM0MVoXDTMwMDgwMjEyMDM0 +MVowEzERMA8GA1UECgwIQWxsdGVyY28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDHGDBDHpPUbtC9QAAjX3bi487AVY5JgYB2gyp6R9cjdsNGMbYnWdxn +BmsIUKJPg7B5NcQObiMe6djUvwo0c2Xl9L+P9LOskP2WNDdpquX3XJu580hXHHVB +mwOgJ0fi+5U9mOFHhc1gYGLmhO9oqsE80SgpmsPQHloMIqmcaolLzgC9PWGu8nSD +ToJq+dXyNFHzLVyBEugHQpeIR8Fq0do4dtlsfTWvv9U+fpGPegjdkPenSxGrOVwd +syFzNahxQGKmpZE/1fsq5QSh9+ZgwpdDChVNpkj9TBC1ApDTUasNco/6Meb/0Xur +pxpWPNfkIpZ7ebtGHVd/ZkGTPUnL7FXHAgMBAAEwDQYJKoZIhvcNAQELBQADggEB +ADwbvD7Mf7SOinV8JkOue8D/tvp+OiYTYLHYppzCLcBK3D1kQ7aqla2T8ebEFbLh +hpau7MxJcizVWZs4vJvFYxEwBTQldobhmG5lHnoKQcOSxis1kWr5xdKhji/QYo6T +wS/cird9hAcuc+RmLCMdpEDyia/vX+vvvRdyKsmB7A6Vkdu8s2B2jlhQNkitYzvq +UDKogJrWe6fQUTpTThMyGbqhp9cQ64M4DJG1cwSBZ/hiUAMKO/y5WVNWFbXIb/Om +xwkXgof2RXN1AjjqMcBh3GNVK4ZV5XM9WCocZjOCi2yZxaxaRWyuGR7EqAQZ+wdr +P5XrzYspeVl1WtBzwGFssPc= +-----END CERTIFICATE----- ``` -## +::: notes +certificate verifying shelly cloud server +::: -```sh -$ cloc esptool-legacy-flasher-stub/ ------------------------------------------------------------ -Language files blank comment code ------------------------------------------------------------ -Linker Script 32 787 1188 18751 -C 6 1284 636 7689 -C/C++ Header 8 463 557 1687 -make 1 36 33 130 -YAML 4 19 0 114 -Python 2 25 21 80 -Markdown 3 58 0 76 -Bourne Shell 2 9 8 23 -TOML 1 1 0 20 -Jinja Template 1 4 2 14 ------------------------------------------------------------ -SUM: 60 2686 2445 28584 ------------------------------------------------------------ -``` +## Thank You