Ed
banner
deinonychus.bsky.social
Ed
@deinonychus.bsky.social
chicken appreciator // breaking computers for fun and profit // 20s
Thanks for reading! Hopefully you had fun and learned a bit along the way. Always remember - you can understand anything around you with just a bit of perseverance. After all, it was built by someone human, too.
December 4, 2025 at 3:12 AM
Finally, we obtain a DHCP lease and get ourselves on the internet. What a journey, eh?
December 4, 2025 at 3:12 AM
I also make sure to spoof the MAC address from the old equipment. I'm not sure if it was the MAC change or unplugging the fiber too many times, but while testing I got the fiber line disabled. I had to hop on AT&T live chat and get my port reset. Oops.
December 4, 2025 at 3:12 AM
We then setup a vlan on the ethernet port. The vlan ID AT&T is using appears to be 2762, but you can figure out what it should be by looking in wireshark or inspecting the vtfd MIB. The modem doesn't strip vlan encapsulation, so we need this setup to get rid of it.
December 4, 2025 at 3:12 AM
We got O5! We also see here that the OLT has set dot1x (MIB 290) to enable port security and given us VLAN id 2762. Our fancy new firmware is going to ignore all this security nastiness and let us on anyway, though.
December 4, 2025 at 3:12 AM
Reboot the ONT, plug it into the fiber line, and check that it gets O5 (operational) status on the network. We can inspect /tmp/omci.log or use omcli parser getonustatus.
December 4, 2025 at 3:12 AM
We also need to set the serials and hardware version. The hardware version sent to the OLT is really the ritool HardwareVersion variable with the ICS appended on the end.
December 4, 2025 at 3:12 AM
We now set the rest of the values we need to spoof in the RI store. These values are set to mimic the BGW320 terminal AT&T installed. The clei code and mnemonic together (without dashes) form the equipment ID checked by the OLT.
December 4, 2025 at 3:12 AM
Now we flash the new firmware slot from our TFTP server. Nerve-wracking, but if we screw up we should be able to recover with the flash dump we took earlier. If we *really* screw up though, we'll have to break out the hot air gun and pull off the flash. So let's try not to do that.
December 4, 2025 at 3:12 AM
We can now build firmware packages to flash to the device. We invoke the modified image builder with the IDs we found earlier, the dumped kernel image, and critically - the patched squashfs we built earlier. We now have a modified firmware package we can flash!
December 4, 2025 at 3:12 AM
Now that we understand the header, we can also pull the kernel from the flash. We take kernelAddress from the firmware slot header, subtract 0xbfc00000 from it (the flash base) to get a flash offset of 0xCE6100. Then we read kernelLen bytes at that location. We save that off as kernel.img.
December 4, 2025 at 3:12 AM
I also forced the fs/kernel base address to 0xC0350000 and image sequence to 5 so it'd build an identical image when supplied with the same kernel and squashfs.
December 4, 2025 at 3:12 AM
bcmImageBuilder needed to be modified to match the slightly older format on this device. Notably, tagVersion had to be changed from 7 to 6 and the mData and dtb fields had to be zeroed since they aren't in use.
December 4, 2025 at 3:12 AM
Broadcom has a tool called bcmImageBuilder to build these packages. There's even a version available in the CFE source distribution.
December 4, 2025 at 3:12 AM
The header thankfully has no cryptographic signatures. Just some CRC32s. Then some board and chip IDs, some magic strings, and the memory mapped flash addresses and sizes of the squashfs and kernel images. These addresses were encoded as ascii decimal, which is a choice.. for sure.
December 4, 2025 at 3:12 AM
I looked at the public CFE source, cross referencing with the CFE RAM payload we dumped earlier to fill in the gaps. ImHex and its pattern editor came in handy to get a sense of how the header was built.
December 4, 2025 at 3:12 AM
Each firmware slot starts with a 256-byte header. Then the squashfs file system follows, and finally the kernel image.
December 4, 2025 at 3:12 AM
We can also just use binwalk on the full flash dump and it picks up on the CFE payload immediately. It also catches one of the firmware slots at 0x20000 and a second firmware slot at 0x750000. CFE looks at both of these slots and boots the one with the higher sequence number.
December 4, 2025 at 3:12 AM
The 2nd stage starts at flash address 0x6A60 and spans 0x175FE bytes. The first word of the second stage is the address where it should be decompressed and control transferred to. In this case it'll be 0x80601000. We can strip off that first word and use xz to decompress it.
December 4, 2025 at 3:12 AM
Eventually we find the routine responsible for loading and decompressing the second stage of CFE from SPI flash. Doesn't look like it's authenticated, which is a good sign. This routine gives us important context about how the second stage is stored on flash.
December 4, 2025 at 3:12 AM
Interleaved in the middle of this bootrom is the NVRAM region at 0x930A0580 (flash offset 0x580). Then more code starting right after the NVRAM at offset 0x984.
December 4, 2025 at 3:12 AM
Any memory access gets offset by $s6. It uses a 'reloc table' for function calls, probably because it makes it convenient to do the offsetting. Halfway though the bootrom, cache is initialized and it swaps $s6 for the KSEG0 view of the same memory, relocating itself into cache. Fun stuff.
December 4, 2025 at 3:12 AM
The bootrom is weird. It resides at flash offset 0 but is linked at 930A0000. In memory it technically executes at 0xbfc00000 while in KSEG1. It makes itself position independent by storing the difference between the linked base addr and its actual location (found with jalr and reading $ra) in $s6.
December 4, 2025 at 3:12 AM
Finally, we run the dump command and wait for those last sectors to transfer. So now our flash is backed up and we have a copy of the kernel and the actual version of CFE running on the device. We can now begin to look into how firmware might be loaded by CFE. Let's start with the bootrom.
December 4, 2025 at 3:12 AM