Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CGA4233 support #34

Open
madushan1000 opened this issue Jul 7, 2021 · 42 comments
Open

CGA4233 support #34

madushan1000 opened this issue Jul 7, 2021 · 42 comments

Comments

@madushan1000
Copy link

@arrobazo provided a nand dump of CGA4233-sto here(nox-x/TG3442DE-Teardown#3 (comment)). I wasn't able to extract the main filesystem(looks like it uses a custom nand controller) but I was able to extract the spi flash dump which seems to store the permnv and dynnv.
I can upload the extracted files, but just run binwalk on the smaller file in the archive and it'll dump a bunch of jffs2 filesystems.
Not sure if this is enough to add support, but please take a look when you have some time :)

@madushan1000
Copy link
Author

Vodafone sent me the gpl patches for a slimier device cga4233vfg, I think it's probably the same device because I asked for gpl sources for cga4233de.
https://mega.nz/file/plMDgAIZ#DOlhHaMaeaks1HcGt2Q-dY0igi-J44D6eR7NfLGh7kk

@jclehner
Copy link
Owner

Do you have access to this device's CM console?

@madushan1000
Copy link
Author

Unfortunately no, but I think cmboot.img, cmrun*.img files in the extracted volumes are the cable modem firmware?

@jclehner
Copy link
Owner

Yes. cmboot.img is the bootloader, and the cmrun{1,2}.img files are the CM firmware. However, the cmrun files appear to be corrupted too.

@madushan1000
Copy link
Author

I have some cmrun files from I extracted from CGM4231 and CGA4131 firmware, they look slimier(no strings except the file name + no clear disassembly). Maybe it's a new firmware format?
I received the gpl sources from cga4233 from vodafone(https://mega.nz/file/plMDgAIZ#DOlhHaMaeaks1HcGt2Q-dY0igi-J44D6eR7NfLGh7kk) and it looks like it has a new programstore version, but I didn't manage to get it working with the cmrun files.

@jclehner
Copy link
Owner

I don't think that it's actually a new file format. I've managed to extract the first few megabytes from these files, using unlzma after fixing the LZMA header, which resulted in correct MIPS assembly, albeit incomplete.

@madushan1000
Copy link
Author

Hmm, I'm attaching the files I got from other modems here, see if you can make any sense of them.
CGA4131-images.tar.gz
CGM4231-images.tar.gz

@jclehner
Copy link
Owner

I've had a look at the ARM bootloader, and found the code which seems to initialize the AES key used by the cm_{perm,dyn}.bin encryption. The encrypted data starts at offset 8 for these files.

However, the encryption key 32cec90383ce291737d5fa200bdb401331776f67734f27deca96fef6641a689c doesn't seem to work. Strings in the stage2 bootloader suggest that this key is unique to every chip, but the stage1 bootloader initializes it to the above value at a fixed address in memory (0x1fefc040), which is then passed to the next stage.

The key is also copied to 0xd384bfe0, which appears to be a shared memory location that is then used by the CM firmware to encrypt/decrypt the nonvol files.

Do you have access to the Linux console?

@arrobazo
Copy link

I recently made a backup of a CGM4331COM bcm3390 (xb7-t) in case you want to review it
https://mega.nz/file/5Uo2RIhA#3KODzQG09iz6xuqhlrjSAv4HcS-gWAWJhJKN09xZFYQ

Pinout SDINBDG4-8G emmc isp 1bit up to 8bit (logic voltage is 3.3v)
https://fccid.io/G954331X/Internal-Photos/Internal-Photos-4519089
19f9df0b467caa4cf60647f190effdf6
pinout 8bit
photo1626746659
photo1626746675

@madushan1000
Copy link
Author

@jclehner unfortunately no access to the linux console. + uart seems disabled. Old snmp trick to enable uart didn't work either. @arrobazo and I have been trying to get access to the linux console on his device without success. Let us know if you know any exploits to this generation of technicolor devices.

@jclehner
Copy link
Owner

Hmmm. Since you've provided the dumps, I'm assuming you've got hardware access to the SPI NOR flash? If so, you could try setting 32 bytes at offset 0x140 of the flash to 0xff.

Apparently, this clears the "unique-key", causing "secure boot" to be disabled. If I'm understanding these devices correctly, this would also disable encryption of the cm_{perm,dyn}.bin files, which in turn might allow enabling telnet access.

I haven't got a bcm3390 device myself, so I unfortunately can't test this myself. I have yet to come across a reasonably priced used device.

@madushan1000
Copy link
Author

@arrobazo has access to the spi flash of cga4233-sto, maybe he might be able to give it a try. I have a cga4233de, but I don't have the hardware know how/equipment to dump/flash the nor flash. If you live in Europe, you can often find cga4233de on https://www.ebay-kleinanzeigen.de/ for less than 20eur(I think I got mine for 10eur).

@madushan1000
Copy link
Author

@jclehner , @arrobazo tried editing the spi dump and flashing it back, the router refuse to boot. Looks like it has some sort of a checksum somewhere.

@madushan1000
Copy link
Author

@jclehner Hi, so we managed to get access to the CM console(prefer not to tell how yet). But the console doesn't have the flash/read, etc.. commands, or memory read/write commands. We can't dump the firmware from there.

@madushan1000
Copy link
Author

Actually it looks like we can dump the ram 4 bytes at a time using these mibs(https://github.com/copslock/cisco-kusanagi_mibs.snmplabs.com/blob/48bb18954e5db428383114ff13b372b9d0cccfb2/asn1/BRCM-CABLEDATA-ENGINEERING-MIB#L87-L129). I'll try to write a script to dump the whole ram via snmp.

@jclehner
Copy link
Owner

jclehner commented Aug 4, 2021

If you live in Europe, you can often find cga4233de on https://www.ebay-kleinanzeigen.de/ for less than 20eur(I think I got mine for 10eur).

@madushan1000 I've finally found someone who was willing to ship it to my country. I'm expecting it to arrive later this week. I'll share any insights here!

@jclehner
Copy link
Owner

jclehner commented Aug 8, 2021

Hmm... I've hit the first obstacle unfortunately. The SPI flash on my device uses a TFBGA package, not the SOP I was expecting (and hoping for), so I can't just solder to the pins. @arrobazo, did your device come with the flash in an 8-pin SOP?

The UART ports (J1000, and J1701) are dead, as expected. I'm assuming one is for the ARM and one for the MIPS processor, and they appear to use the same pinout as on earlier BCM33xx boards (VCC - GND - TX - RX, with the notch at the bottom).

There's another 4-pin header I'm not sure about (J1601), and a potential EJTAG header (J1600).

@madushan1000 the MIBs you posted don't work on my device, unfortunately. Also, would you mind sharing how you were able to access the CM console (via email if you don't wanna share publicly)?

@arrobazo
Copy link

arrobazo commented Aug 8, 2021

@jclehner If they are bga both NAND & SPI, I could say where the through holes are located to simply scratch the pcb and you can solder but I must look at the modem again .... about the method I revealed @madushan1000 , it can be said that it is an exploit at the hw level that I discovered in 2017 with the first d3.1 eCos modem that I had ... no problems I can tell you internally it is an extreme measure of obtaining control of the modem ... xD

@jclehner
Copy link
Owner

jclehner commented Aug 8, 2021

@jclehner If they are bga both NAND & SPI, I could say where the through holes are located to simply scratch the pcb and you can solder but I must look at the modem again

That would be much appreciated!

@arrobazo
Copy link

arrobazo commented Aug 8, 2021

@jclehner I opened the modem and I see that it has tracks directly to the cpu without through holes, I leave you photos the only way that I see possible would be to scrape these tracks.

photo1628454250
sss

Well i think cga4233-sto and cga4233de have the same pcb
photo1628454932

to show you uart data connect vcc
uart j1000 = RG
uart j1701 = eCos
uart j1601 = BBS, reference tc4400

@jclehner
Copy link
Owner

jclehner commented Aug 9, 2021

@jclehner I opened the modem and I see that it has tracks directly to the cpu without through holes, I leave you photos the only way that I see possible would be to scrape these tracks.

Thanks a ton, that confirms my suspicion, but I didn't have the means to desolder the chip. Wish me luck soldering to those tiny traces ;)

to show you uart data connect vcc

Not sure what you mean by this exactly!?

uart j1601 = BBS, reference tc4400

What's BBS?

@arrobazo
Copy link

arrobazo commented Aug 9, 2021

@jclehner I opened the modem and I see that it has tracks directly to the cpu without through holes, I leave you photos the only way that I see possible would be to scrape these tracks.

Well, if you have experience, it is not difficult, just use some enameled wire as thin as possible 0.1mm at least, there are 4 tracks wp, si, so, clk if I'm not mistaken :P

Thanks a ton, that confirms my suspicion, but I didn't have the means to desolder the chip. Wish me luck soldering to those tiny traces ;)

to show you uart data connect vcc

Not sure what you mean by this exactly!?

connect not only tx rx gnd, also connect from your ttl-usb vcc3.3v to uart ports. When I use ttl-usb cp2102, if I don't connect the vcc pin I don't get any information

uart j1601 = BBS, reference tc4400

What's BBS?

BBS I think it is an i2c bus, in other modems it is labeled with those acronyms ... there are also other broadcom cpu devices that have that labeling

@jclehner
Copy link
Owner

Well, if you have experience, it is not difficult, just use some enameled wire as thin as possible 0.1mm at least, there are 4 tracks wp, si, so, clk if I'm not mistaken :P

Turns out I don't have experience, and I hardware-bricked my device in the process. I've found a new one, but I won't be able to work on this until the end of August!

@arrobazo
Copy link

arrobazo commented Aug 20, 2021

Well, if you have experience, it is not difficult, just use some enameled wire as thin as possible 0.1mm at least, there are 4 tracks wp, si, so, clk if I'm not mistaken :P

Turns out I don't have experience, and I hardware-bricked my device in the process. I've found a new one, but I won't be able to work on this until the end of August!

if they are thin tracks (never so much) did you break them? Well, I hope you can do it next time. I would weld for you but I am on another continent I think very far I guess hehe luck! ... if madushan1000 still hasn't told you what I did to access factory mode on these d3.1 eCos modems, you can talk to me on discord and I'll give you details (arrobazo #5038) greetings

@jclehner
Copy link
Owner

jclehner commented Sep 6, 2021

I've finally gotten around to working on this again a little bit. Didn't break the router this time, and I've now got SPI access to the flash.

@arrobazo, while @madushan1000 has given me a general idea, I'd still like to hear the details from you. I'd prefer via email, as I don't wanna setup yet another account (discord in this case). My email is [email protected].

@arrobazo
Copy link

arrobazo commented Sep 6, 2021

@jclehner excellent, well there I just sent you an email

@jclehner
Copy link
Owner

jclehner commented Dec 1, 2021

So I've been quiet on this topic the past months, but I've made some, albeit slow, progress. I've managed to trash the PCB tracks on my first CGA4233 before I even had the chance to to anything meaningful.

I had more success with the second device, and I had SPI access to the flash for quite some time. I managed to enable the SNMP engineering MIBs, but apart from that, I found that there wasn't that much you could do, at least at first glance:

  • The whole ARM bootloader stuff appears to use secure boot, as any attempt to modify the code led to the device not booting.

  • The bootloader on the CGA4233DE is even more locked down, than on the CGA4233, as the serial console is completely disabled before even printing a single character. I managed to get some output by flashing the bootloader from a CGA4233 to my CGA4233DE device, but it stops booting because of a "Market ID" mismatch. Since you can't modify the bootloader (see above), I haven't yet found a way around this.

  • Despite your detailed instructions, I couldn't access the CM serial console. I've tried a few OIDs, which seemed to work, but the console is still dead. I'm assuming it too is being disabled by the (ARM) bootloader, but I haven't found the code yet.

Using the engineering MIB you mentioned, I've added an SNMP backend (still work in progress) to bcm2dump, that allows dumping and writing to CM memory, using

$ bcm2dump dump snmp:192.168.100.1 ram <address>,<length> <outfile>

The memory map is partially documented in the GPL'd sources of various BCM3390 modems, which I've uploaded in this repository. The memory ranges accessible from the CM side all appear to have _PER_ in their names, and must be ORed with 0xd0000000 to get their corresponding MIPS address, i.e. BCHP_UART0_PER_REG_START = 0x03c00640 can be accessed at 0xd3c00640. The GPIO pin mux however can only be accessed from the ARM cores, so you can't re-enable the serial ports from the CM side.

Speaking of enabling the engineering MIBs: eventually, I managed to drop my second CGA4233DE, and sure enough, it ripped out a small portion of one of the flash chip's PCB tracks.

Now having ordered my third, I wanted to try something less invasive, which to my surprise turned out quite well: the chip-select line of the flash chip has an unpopulated pad (see below), that is much easier to solder to, than those tiny PCB tracks (and you could even pull this off without soldering at all). Using one of those cheapo 10 EUR 24MHz logic analyzers, I guesstimated that the ARM bootloader and Linux firmware side was finished accessing the SPI flash after around 7 seconds, and then it took some time before the CM firmware (which is launched by Linux) kicked in. TL;DR: you can enable engineering MIBs by booting the device, and then waiting 10 seconds before shorting the chip-select line to ground (and leaving it shorted). The device will boot (the web interface will show various values, such as the modem's serial number as "FAILURE"), and the MIBs will be accessible. Be warned though, as this also trashes the permanent NVRAM, including MAC addresses and DOCSIS certificates!

Now that I can dump the CM firmware, it should be relatively easy to get serial console or telnet access (to the CM firwmare). Not sure about the Linux part of it yet though. I'll keep you posted.

chip_annotated_small

@arrobazo
Copy link

arrobazo commented Mar 8, 2022

@jclehner were you able to get root credentials for RgLinux console? from eCos_cm (switch_console)
imagen

@jclehner
Copy link
Owner

@jclehner were you able to get root credentials for RgLinux console? from eCos_cm (switch_console)

Not yet. On the firmware I'm currently working on, the switchCpuConsole command seems to be a NOP. I've however managed to get root access to the Linux console on a CGA4233EU. Stay tuned for a detailed writeup!

@jclehner
Copy link
Owner

jclehner commented Sep 1, 2022

I've been busy these past few months, but thanks to a very kind donation of a few non-DE CGA4233, I've now manged to get root access to the modem's Linux console.

Note that this method will not work on the CGA4233DE, as its bootloader doesn't appear to use the STARTUP variable.

As mentioned in my earlier posts, these modems use a per-device unique key, the value of which is determined by 32 bytes located at offset 0x140 on the SPI flash: the data is copied by the bootloader to the address 0xd38fbfe0, where it appears to be transformed (hashed?) in some way, since the data stored in the SPI flash does not match the data that can be read back from the aforementioned RAM address. For example, the key (in SPI flash)

32 ce c9 03 83 ce 29 17 37 d5 fa 20 0b db 40 13 31 77 6f 67 73 4f 27 de ca 96 fe f6 64 1a 68 9c

is transformed to (RAM):

cd 7c 76 03 2e 4c 4d d9 77 78 b3 22 bb 62 74 22 31 1f 2d f8 43 e9 1d 92 c6 3f d6 62 52 72 c4 c8

Note that this key is used by both the RG (ARM, little endian) and CM side (MIPS, big endian), but due to byte swapping of 32-bit integers, the key used by the former is

03 76 7c cd d9 4d 4c 2e 22 b3 78 77 22 74 62 bb f8 2d 1f 31 92 1d e9 43 62 d6 3f c6 c8 c4 72 52

The easiest way to get at this unique key is using the above mentioned engineering MIBs. To enable factory mode, use the method of shorting the SPI's chip-select to ground, as soon as the CM side starts booting (if the CM console is disabled, wait around 8-10 seconds). The important part, if you don't want to loose the NVRAM data (and thus MAC addresses, DOCSIS certificates, serial numbers, and the like), is to keep the CS line shorted until you reboot the device (that way, attempts by the firmware to write to the flash will also be blocked).

Now verify that factory mode has indeed been enabled:

$ snmpget -v 2c -c public 192.168.100.1 1.3.6.1.2.1.1.1.0
iso.3.6.1.2.1.1.1.0 = STRING: "Technicolor CGA4233-EU EuroDocsis 3.1 2-PORT Voice Gateway <<HW_REV: 3.3.2; VENDOR: Technicolor; BOOTR: 2.7.0alpha4; SW_REV: CGA4233EU-1.6H4-E20-20-E1319-c11CA-r1810-190907; MODEL: CGA4233-EU>> FACTORY MODE ENABLED!"

You now have read/write access to the CM firmware's RAM. Using bcm2dump, you can dump the unique key:

$ bcm2dump -P cga4233 dump snmp:192.168.100.1 ram ukey ukey.bin
$ hexdump -C ukey.bin
00000000  cd 7c 76 03 2e 4c 4d d9  77 78 b3 22 bb 62 74 22  |.|v..LM.wx.".bt"|
00000010  31 1f 2d f8 43 e9 1d 92  c6 3f d6 62 52 72 c4 c8  |1.-.C....?.bRr..|
00000020

Now, you'll have to dump the SPI flash.

In order to access the Linux console, we need to modify the ARM bootloader's (aka BOLT) environment variables. These are located in the nvram (or nvram0) and nvram1 partitions, and encrypted using the above mentioned key. We'll assume that spi.bin contains a dump of the SPI flash.

$ dd if=spi.bin of=nvram_enc.bin bs=$((0x10000)) count=2 skip=$((0x22))
$ openssl enc -d -aes-256-ecb -nopad -in nvram_enc.bin -out nvram_dec.bin -K 03767ccdd94d4c2e22b37877227462bbf82d1f31921de94362d63fc6c8c47252

At the moment, bcm2cfg doesn't support modifying the BOLT environment variables. A tool called bcm2boltenv is provided for now, to dump the contents:

$ bcm2boltenv nvram_dec.bin
unknown    : 0x00000000, 0x00000001
write_count: 83
size       : 1035
checksum
   reported: 0x89bf5e59
   expected: 0x89bf5e59
==========================
WD_ENABLE=1
STARTUP=load -nz -raw -addr=$DT_ADDRESS -max=0x10000 flash0.devtree$DT_IDX;boot flash1.kernel$KL_IDX "ubi.mtd=flash1.rg$RG_IDX rootfstype=ubifs root=ubi0:rootfs platformboot ubifs_apps jffs2_data coherent_pool=1M $RG_NO_CONSOLE "
RG_NO_CONSOLE=noconsole console=null
ROOTFSBANK0=STARTUPUBIFS
FCNT=0
DT_IDX=1
KL_IDX=1
RG_IDX=1
CM_IDX=1
SPRINGEVENT=192513
STARTUPUBIFS=load -nz -raw -addr=$DT_ADDRESS -max=0x10000 flash0.devtree$DT_IDX;boot flash1.kernel$KL_IDX "ubi.mtd=flash1.rg$RG_IDX rootfstype=ubifs root=ubi0:rootfs platformboot ubifs_apps jffs2_data coherent_pool=1M $RG_NO_CONSOLE"
@000000000000026e: 354 bytes
ROOTFS_ADDRESS=0x16000000
ROOTFSBANK1=STARTUPUBIFS

The Linux console is disabled by the noconsole console=null line in RG_NO_CONSOLE. Using a hex editor, we can modify this value to init=/bin/sh (making sure to pad the remaining length with spaces). Re-running bcm2boltenv will tell us the new checksum:

$ bcm2boltenv nvram_dec_modified.bin
unknown    : 0x00000000, 0x00000001
write_count: 83
size       : 1035
checksum
   reported: 0x89bf5e59
   expected: 0x7148a2b6
==========================
WD_ENABLE=1
STARTUP=load -nz -raw -addr=$DT_ADDRESS -max=0x10000 flash0.devtree$DT_IDX;boot flash1.kernel$KL_IDX "ubi.mtd=flash1.rg$RG_IDX rootfstype=ubifs root=ubi0:rootfs platformboot ubifs_apps jffs2_data coherent_pool=1M $RG_NO_CONSOLE "
RG_NO_CONSOLE=init=/bin/sh
ROOTFSBANK0=STARTUPUBIFS
FCNT=0
DT_IDX=1
KL_IDX=1
RG_IDX=1
CM_IDX=1
SPRINGEVENT=192513
STARTUPUBIFS=load -nz -raw -addr=$DT_ADDRESS -max=0x10000 flash0.devtree$DT_IDX;boot flash1.kernel$KL_IDX "ubi.mtd=flash1.rg$RG_IDX rootfstype=ubifs root=ubi0:rootfs platformboot ubifs_apps jffs2_data coherent_pool=1M $RG_NO_CONSOLE"
@000000000000026e: 354 bytes
ROOTFS_ADDRESS=0x16000000
ROOTFSBANK1=STARTUPUBIFS

Now re-encrypt the partition using openssl, before writing it back to the flash chip.

$ openssl enc -e -aes-256-ecb -nopad -in nvram_dec.bin -out nvram_enc.bin -K 03767ccdd94d4c2e22b37877227462bbf82d1f31921de94362d63fc6c8c47252

Make sure to write the partition to both nvram0 and nvram1 partitions (i.e. offsets 0x220000 and 0x240000).

You should now have access to a root shell. Note that the router will reboot after ~60 seconds unless you kick the watchdogs:

# /sbin/watchdog /dev/watchdog0
# /sbin/watchdog /dev/watchdog1

The busybox version on the router doesn't have the telnetd or nc applets, so the easiest option to get these to the router is downloading a static busybox-armv7l and putting it on a USB flash drive, which you can then mount from the root shell.

# mount /dev/sda1 /tmp/
# cp /tmp/busybox-armv7l /bin/busybox-static
# umount /tmp
# /bin/busybox-static telnetd -l /bin/sh -p 2323

To continue the normal boot process, run

# exec /sbin/init

More detailed documentation about the BOLT environment variable storage format, and the bcm2boltenv utility coming soon.

jclehner added a commit that referenced this issue Sep 6, 2022
As mentioned in #34.
@jclehner
Copy link
Owner

jclehner commented Sep 14, 2022

Here's a link to the NOR and NAND flash dumps of a CGA4233EU:

https://github.com/jclehner/bcm2-dumps/tree/master/cga4233/eu

@inklit
Copy link

inklit commented Sep 14, 2022

As mentioned in my earlier posts, these modems use a per-device unique key, the value of which is determined by 32 bytes located at offset 0x140 on the SPI flash

Hi, is this the same key used to validate the firmware image (Secureboot)? or is this key just used for nvram?
In other words, if we have the key, can we make modifications to the firmware image?

@jclehner
Copy link
Owner

No. The bootloader images are signed using SHA-256 with 2048-bit RSA. The flash offsets of the public key modulus, signatures and image data are:

image key signature
SSBL 0x240 0x23000
MEMSYS-STD 0x340 0x23100
MEMSYS-ALT 0x440 0x23200

SSBL is the second-stage bootloader (BOLT), and MEMSYS-* is the first-stage bootloader, which in turn is booted by an initial bootloader.

As mentioned in my earlier posts, these modems use a per-device unique key, the value of which is determined by 32 bytes located at offset 0x140 on the SPI flash.

I'm starting do doubt this earlier assumption of mine. Since there are 256 bytes between 0x140 and the SSBL key offset, and a 256-bit AES key is only 32 bytes long.

Maybe this blob is another signature that's verified by the CPU itself? It might then copy its unique key to RAM address 0xffff0140, which is then used by the bootloader.

I'll try flashing a NOR flash image from another device to see if the unique key changes at all...

@inklit
Copy link

inklit commented Sep 19, 2022

The flash offsets of the public key modulus, signatures and image data are:

is it possible to override this with our own key + signatures? secureboot is not secure unless the key used to validate the signature meets the following condition

  1. is stored securely
  2. is not possible to change

it seems like if they store it on the flash, then it may be possible to change. for reference, the Puma7 Intel cable modem chipset stores the public key on the CPU via fuses, which are blown in the factory and cannot be changed after it is fused by the manufacturer with their public key. this meets both conditions (except if you can swap the entire CPU with one which is not fused, then you can violate condition 2)

@jclehner
Copy link
Owner

Any attempt to modify these keys leads to the device refusing to boot. So, as mentioned, I'm assuming that there's a public key stored in the CPU itself, which is used to validate the initial bootloader stage (including the other keys).

@jclehner
Copy link
Owner

jclehner commented Sep 21, 2022

Having said all that, I forgot to mention that the root filesystem isn't verified or encrypted at all, only the bootloader and Linux kernel (at least on the device I'm currently working with). There are however different security levels apparently. The CGA4233DE was much more locked down than the EU variant I'm currently working with.

On the EU variant, once you have the device's unique AES-256 key (or root access to Linux), you can modify the bootloader environment variables to change the STARTUP command. That way you can access BOLT's command-line interface, and while the boot command does perform signature checking of the kernel, you could modify the code in-place using the e command to change memory contents.

This doesn't work on the DE variant, as its STARTUP command is baked into the bootloader itself, and the environment isn't used for that purpose. However, it too used an unencrypted, writable root filesystem.

@soxrok2212
Copy link

I recently made a backup of a CGM4331COM bcm3390 (xb7-t) in case you want to review it https://mega.nz/file/5Uo2RIhA#3KODzQG09iz6xuqhlrjSAv4HcS-gWAWJhJKN09xZFYQ

Does anyone still happen to have this dump?

@inklit
Copy link

inklit commented Sep 22, 2022

I forgot to mention that the root filesystem isn't verified or encrypted at all

LOL. for both CM (eCos core, maybe not a rootfs..?) and RG?

@jclehner
Copy link
Owner

Small update for anyone interested:

The device-unique key can be dumped from the CM bootloader. Its command-line interface can be accessed by pressing p:

BCM339060
BCM3390G0 Bootloader version 2.7.0alpha4, Built by jenkins on Sep  7 2019 at 07:03:41
RAM Windows size 63 mb


r hexAddr [width] - Display memory location
w hexAddr hexVal [width] - Write memory location
d hexAddr length [width] - Dump memory
rc regNum [select] - Read CP register
wc - regNum hexVal [select] - Write CP register
c [iterations] - Run cache test
m hexAddr hexSize [iterations] - Run memory test
t - Run next command on TP1
x - Exit
z - Cause exception
1 - Boot image 1 on exit
p - Power down non-essential blocks

> 

The key can be dumped using the following command:

> d 0xd384bfe0 0x20
d384bfe0: cd 7c 76 03 2e 4c 4d d9 77 78 b3 22 bb 62 74 22
d384bff0: 31 1f 2d f8 43 e9 1d 92 c6 3f d6 62 52 72 c4 c8

Note that, even without the 0x prefix, both address and length are interpreted as hexadecimal, so d 0xd384bfe0 32 will not produce the expected result (and crashes the device in the process).

Also, regarding secure boot, and my earlier assumptions regarding the data at flash offset 0x140:

I'm starting do doubt this earlier assumption of mine. Since there are 256 bytes between 0x140 and the SSBL key offset, and a 256-bit AES key is only 32 bytes long.

Maybe this blob is another signature that's verified by the CPU itself? It might then copy its unique key to RAM address
0xffff0140, which is then used by the bootloader.

I'll try flashing a NOR flash image from another device to see if the unique key changes at all...

This must indeed be another signature. The contents at this offset do not affect the device key, but the key is apparently copied to 0xffff0140 by a boot ROM that runs before the actual bootloader. The BCM3390 memory map mentions a BCHP_BOOTROM_REG_START at 0x20500000 | 0xd0000000 = 0xf0500000, but reading from this address from the BOLT command line returns all-zeroes...

@madushan1000
Copy link
Author

I don't remember the details anymore. Is bootloader uart enabled by default for EU version of the router? I need to dig out my DE version and check.

@jclehner
Copy link
Owner

I don't remember the details anymore. Is bootloader uart enabled by default for EU version of the router? I need to dig out my DE version and check.

It is on my EU devices. Not sure about the DE version, since I haven't got any anymore.

@jclehner
Copy link
Owner

jclehner commented Feb 16, 2024

Another (possibly) interesting detail, regarding the BOLT bootloader: this appears to be based on CFE, or if it isn't it does share quite a bit of code. For example, compare this function from bcm63xx-cfe

static int ui_cmd_setenv(ui_cmdline_t *cmd,int argc,char *argv[])
{
    char *varname;
    char *value;
    int roflag = ENV_FLG_NORMAL;
    int res;

    varname = cmd_getarg(cmd,0);

    if (!varname) {
	return ui_showusage(cmd);
	}

    value = cmd_getarg(cmd,1);
    if (!value) {
	return ui_showusage(cmd);
	}

    if (!cmd_sw_isset(cmd,"-p")) {
	roflag = ENV_FLG_BUILTIN;	/* just in memory, not NVRAM */
	}

    if (cmd_sw_isset(cmd,"-ro")) {
	roflag = ENV_FLG_READONLY;
	}

    if ((res = env_setenv(varname,value,roflag)) == 0) {
	if (roflag != ENV_FLG_BUILTIN) env_save();
	}
    else {
	return ui_showerror(res,"Could not set environment variable '%s'",
			    varname);
	}

    return 0;
}

with this BOLT function (decompiled using Ghidra):

undefined4 FUN_1361d68c(int *param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4)

{
  int iVar1;
  int iVar2;
  undefined4 uVar3;
  int iVar4;
  uint uVar5;
  
  iVar1 = FUN_1361ca1a(param_1,0);
  if ((iVar1 == 0) || (iVar2 = FUN_1361ca1a(param_1,1), iVar2 == 0)) {
    uVar3 = FUN_1361c35e();
    return uVar3;
  }
  iVar4 = FUN_1361c9ec(param_1,"-p");
  uVar5 = (uint)(iVar4 == 0);
  iVar4 = FUN_1361c9ec(param_1,"-ro");
  if (iVar4 != 0) {
    uVar5 = uVar5 | 2;
  }
  iVar4 = FUN_1361c9ec(param_1,"-h");
  if (iVar4 != 0) {
    uVar5 = uVar5 & 0xfffffffe | 4;
  }
  iVar2 = s_setenv(iVar1,iVar2,uVar5);
  if (iVar2 != 0) {
    uVar3 = FUN_1361c2c0(iVar2,"Could not set environment variable \'%s\'",iVar1,param_4);
    return uVar3;
  }
  if (-1 < (int)(uVar5 << 0x1f)) {
    FUN_13617d90();
  }
  return 0;
}

Also checkout this newer CFE version, which also includes ARM code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants