There is some documentation in the famous deoptim's repository, but this is unlikely to help you. Qualcomm's SB3.0 hasn't been exploited so far, what you can do is look for bugs further in the boot chain, like one that was found (and not tested so far) in Z3. Pin you're referring to is boot_config0 which refers to application code segment, not the boot chain - and IIRC if this configuration is fused, the fused configuration takes precedence.
Don't know it, could you share it?
If you are very, very lucky, it may behave similarly as ipq807x - using atf=1
to circumvent the secure boot check.
That's hot!
I was on a lookout for them on local auction sites, but haven't picked one up yet, prices were quite high. Now it's worth way more
What is the way you forced it to boot OpenWrt?
Exactly as described previously. Change the device major in EEPROM, replace part.safe
on flash with a modified u-boot build packaged as a FIT image:
Format: Log Type - Time(microsec) - Message - Optional Info
Log Type: B - Since Boot(Power On Reset), D - Delta, S - Statistic
S - QC_IMAGE_VERSION_STRING=BOOT.BF.3.1.1-00096
S - IMAGE_VARIANT_STRING=DAACANAZA
S - OEM_IMAGE_VERSION_STRING=CRM
S - Boot Config, 0x00000025
S - Core 0 Frequency, 0 MHz
B - 261 - PBL, Start
B - 1340 - bootable_media_detect_entry, Start
B - 2615 - bootable_media_detect_success, Start
B - 2629 - elf_loader_entry, Start
B - 7270 - auth_hash_seg_entry, Start
B - 1382352 - auth_hash_seg_exit, Start
B - 1447639 - elf_segs_hash_verify_entry, Start
B - 1569353 - PBL, End
B - 1569377 - SBL1, Start
B - 1658051 - pm_device_init, Start
D - 6 - pm_device_init, Delta
B - 1659570 - boot_flash_init, Start
D - 87594 - boot_flash_init, Delta
B - 1751205 - boot_config_data_table_init, Start
D - 14010 - boot_config_data_table_init, Delta - (419 Bytes)
B - 1767914 - clock_init, Start
D - 7572 - clock_init, Delta
B - 1778887 - CDT version:2,Platform ID:8,Major ID:1,Minor ID:0,Subtype:1
B - 1782376 - sbl1_ddr_set_params, Start
B - 1787361 - cpr_init, Start
D - 2 - cpr_init, Delta
B - 1791851 - Pre_DDR_clock_init, Start
D - 5 - Pre_DDR_clock_init, Delta
D - 13143 - sbl1_ddr_set_params, Delta
B - 1805130 - pm_driver_init, Start
D - 2 - pm_driver_init, Delta
B - 1876340 - sbl1_wait_for_ddr_training, Start
D - 27 - sbl1_wait_for_ddr_training, Delta
B - 1893870 - Image Load, Start
D - 1312117 - QSEE Image Loaded, Delta - (268504 Bytes)
B - 3206486 - Image Load, Start
D - 2118 - SEC Image Loaded, Delta - (2048 Bytes)
B - 3216578 - Image Load, Start
D - 1308369 - APPSBL Image Loaded, Delta - (292616 Bytes)
B - 4525372 - QSEE Execution, Start
D - 56 - QSEE Execution, Delta
B - 4531549 - SBL1, End
D - 2964253 - SBL1, Delta
S - Flash Throughput, 1969 KB/s (563587 Bytes, 286154 us)
S - DDR Frequency, 672 MHz
U-Boot 2017.07-RELEASE-g39cabb9bf3 (May 24 2018 - 14:07:32 -0700)
DRAM: 242 MiB
machid : 0x8010001
Product: meraki_Stinkbug
NAND: ONFI device found
ID = 1d80f101
Vendor = 1
Device = f1
128 MiB
Using default environment
In: serial
Out: serial
Err: serial
machid: 8010001
ubi0: attaching mtd1
ubi0: scanning is finished
ubi0: attached mtd1 (name "mtd=0", size 112 MiB)
ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
ubi0: VID header offset: 2048 (aligned 2048), data offset: 4096
ubi0: good PEBs: 896, bad PEBs: 0, corrupted PEBs: 0
ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
ubi0: max/mean erase counter: 214/99, WL threshold: 4096, image sequence number: 2086049366
ubi0: available PEBs: 0, total reserved PEBs: 896, PEBs reserved for bad PEB handling: 20
Read 0 bytes from volume part.safe to 84000000
No size specified -> Using max size (507904)
## Loading kernel from FIT Image at 84000000 ...
Using 'config@1' configuration
Trying 'kernel-1' kernel subimage
Description: Kernel
Type: Kernel Image
Compression: uncompressed
Data Start: 0x840000d0
Data Size: 381216 Bytes = 372.3 KiB
Architecture: ARM
OS: Linux
Load Address: 0x87300000
Entry Point: 0x87300000
Hash algo: sha1
Hash value: 89c319b76738e71147631f87311fc8f31e8ac8aa
Verifying Hash Integrity ... sha1+ OK
## Loading fdt from FIT Image at 84000000 ...
Using 'config@1' configuration
Trying 'fdt-1' fdt subimage
Description: Insect DTB
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x8405d2d4
Data Size: 235 Bytes = 235 Bytes
Architecture: ARM
Hash algo: sha1
Hash value: 86c47255d86f2bd6301e7772ca65b3548493875b
Verifying Hash Integrity ... sha1+ OK
Booting using the fdt blob at 0x8405d2d4
Loading Kernel Image ... OK
Using Device Tree in place at 8405d2d4, end 840603be
Using machid 0x8010001 from environment
Starting kernel ...
U-Boot 2017.07-DEVEL (Apr 01 2024 - 14:50:01 +0000)
DRAM: 242 MiB
machid : 0x8010001
NAND: ONFI device found
ID = 1d80f101
Vendor = 1
Device = f1
128 MiB
Using default environment
In: serial
Out: serial
Err: serial
machid: 8010001
Net: MAC0 addr:e0:cb:bc:11:22:33
PHY ID1: 0x4d
PHY ID2: 0xd0b1
ipq40xx_ess_sw_init done
eth0
Autoboot in 5 seconds
FUZZY CRICKET #
In this case, it was that easy. But I am sure Meraki won't make the same mistake twice, so this kind of exploit is only possible for select ipq40xx devices.
Flashing is "pretty easy," you just dump+modify EEPROM, overwrite everything on NAND past 0xc00000
with a dump containing the new u-boot built in a ubivol, tftpboot initramfs and sysupgrade
.
Not sure how OpenWrt will feel about adding support since it requires directly flashing both I2C EEPROM and TSOP48 NAND. It also means most users won't be able to flash OpenWrt since it requires a significant investment in hardware flashing tools or very good soldering skills.
I don't think Meraki can patch this, since the QFPROM fuses are blown with their cert and I don't think the SoC has rollback protection. However, this is speculation and I may be wrong.
I will make a PR for support and write documentation soon™.
I'm optimistic about this. We have clips available both for the I2C EEPROM, and this is relatively safe operation, and with used MR33's we have to deal with the same issues as here - so not much changes, really.
Also, since we now know how to chainload U-boot, maybe finally it'll be possible to provide web recovery, as done on GL-iNet devices.
BTW, which power supply is used for Z3? I'm trying to organize some units, but the cheaply-available ones are sans PSU - and IIRC the connector isn't a typical 5,5/2.1mm barrel jack. And genuine Cisco adapters for that cost as much as the device itself.
The original PSU is MA-PWR-50WAC.
Output: 54V 0.92A (centre positive)
Barrel dimensions are approximately 6.3x3.0mm
Blog post with details on how the secure boot bypass works: https://watchmysys.com/blog/2024/04/breaking-secure-boot-on-the-meraki-z3-and-meraki-go-gx20/
BTW, this is also applicable to the Meraki Go GX20 since they are largely the same device (GX20 lacks WiFi radios):
Hi,
i got a cheap Meraki Z3 from ebay.
It has U-Boot 2017.07-RELEASE-ge148443fbd (Jun 06 2019 - 15:23:18 -0700)
and Secure boot enabled.
So i tried to modify the EEPROM at offset 0x4a and 0x104a.
But there is no information at this offset. did the EEPROM changed in any way?
Or has the Z3 post something todo with date 1 April?
I should be clear that the workaround does not disable secure boot, it just disables u-boot from enforcing signature validation on the payload. Secure boot is always enabled on the Z3. This is why we cannot replace u-boot, the signature is checked and verified by the SBL.
My mistake, it is at offset 0x49
, the data in your screenshot at that address is 0x24
.
Please send me an email (my contact details are on GitHub) and I will send you the installation instructions and OpenWrt build.
So, does this mean we can look forward to possible Z3/Z3c/GX20 support in the future Now if we can figure out the MR30/H, MR46, and Mist AP33, I'll be super happy.
Hi,
did some research in the u-boot sources.
Values for EEPROM are in DEC.
So iEEPROM should have 0x1E at offset 0x49.
static const struct product_map_entry product_map[] = {
/* BOARD=insect */
{ "meraki_Stinkbug", 30, "STINKBUG # ", MERAKI_BOARD_STINKBUG, "config@1" },
{ "meraki_Ladybug", 31, "LADYBUG # ", MERAKI_BOARD_LADYBUG, "config@3" },
{ "meraki_Noisy_Cricket", 32, "NOISY CRICKET # ", MERAKI_BOARD_NOISY_CRICKET, "config@2" },
{ "meraki_Maggot", 37, "MAGGOT # ", MERAKI_BOARD_MAGGOT, "config@4" },
{ "meraki_Dungbeetle_Omni", 38, "DUNGBEETLE OMNI # ", MERAKI_BOARD_DUNGBEETLE_OMNI, "config@5" },
{ "meraki_Dungbeetle_Patch", 39, "DUNGBEETLE PATCH # ", MERAKI_BOARD_DUNGBEETLE_PATCH, "config@6" },
{ "meraki_Grub", 44, "GRUB # ", MERAKI_BOARD_GRUB, "config@4" },
{ "meraki_Toe_biter_Omni", 45, "TOE_BITER OMNI # ", MERAKI_BOARD_TOE_BITER_OMNI, "config@5" },
{ "meraki_Toe_biter_Patch", 46, "TOE_BITER PATCH # ", MERAKI_BOARD_TOE_BITER_PATCH, "config@6" },
/* BOARD=wired-arm-qca */
{ "meraki_Fuzzy_Cricket", 36, "FUZZY CRICKET # ", MERAKI_BOARD_FUZZY_CRICKET, "config@1" },
{ "meraki_Fairyfly", 43, "FAIRYFLY # ", MERAKI_BOARD_FAIRYFLY, "config@2" },
{ "meraki_Heart_of_Gold", 42, "HOG # ", MERAKI_BOARD_HEART_OF_GOLD, "config@3" },
{ NULL, MERAKI_BOARD_UNKNOWN },
};
Yes. I am waiting on a Z3C to arrive to add support before I submit a PR for the devices (Z3/GX20/Z3C).
Great! Best of Luck. Anything so Meraki can stop scamming people.
I was able to read the NAND in circuit.
binwalk shows usable informations, now it´s to replace the ubi part.
Wiki pages created: