Verizon Fios G3100 and E3200 Research
#25
The weeks go by quick and it’s time for another update already! This week I didn’t run any scrapes or process any images for passwords, which means we don’t have a database update.

@samer59 shared his wordlists collected from the TMobile KVD21, so I thought I should extract all of the words in my database to their appropriate lists again. I have also included these Fios words in my lists.  These lists are attached below.

Saved 454 unique words to 3_letter_words.txt
Saved 888 unique words to 4_letter_words.txt
Saved 611 unique words to 5_letter_words.txt
Saved 379 unique words to 6_letter_words.txt
Saved 564 unique words to 7_letter_words.txt
Saved 7 unique words to 8_letter_words.txt

Without including samer59’s contrubution, using the dictionary generator I previously posted would create a dictionary of 14,779,552,320 possible combinations for the strict 15-char <word><word><word> SSID passwords. Unfortunately I still haven’t found a way to reduce this list further.

It’s not all bad news this week though, I’ve made a bit of progress with the firmware! I shared the list of firmware links that I've found, and a GitHub user is hosting them for people that can’t download directly from Verizon Wink (https://3to.moe/verizon_fw/). My G3100 device is currently on version 3.4.0.10, which I thought was the latest version. However, I had noticed version 3.6.0.6 was listed on the Verizon firmware page. We already know the URL to find this firmware, so it was easy to find the link. Other devices had newer firmware listed too, so we grabbed those. I updated the fuzzing script with the new info and here’s what we found.

Code:
G3100: https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.6.0.5_loader.bin https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.6.0.6_loader.bin E3200: https://cpe-ems34.verizon.com/firmware/BHRx_Ext/e3200_fw_3.6.0.3_loader.bin CR1000A: https://cpe-ems34.verizon.com/firmware/CHRA/chr2fa_fw_3.6.0.2_BD_loader.bin CR1000B: https://cpe-ems34.verizon.com/firmware/CHRB/chr2fb_fw_3.6.0.2_BD_loader.bin

I was also rereading the huge OpenWRT thread on unlocking the CR1000A again, which this post had a link to firmware that I previously overlooked. These file names would be much harder for me to fuzz since they include a timestamp. However searching for the "cdn3.vzwdm” I came across these links. These files are also able to be directly downloaded by anyone!

Code:
https://cdn3.vzwdm.com/hdm/chr2fa_fw_3.2.0.11_oldsig_1685136655890.bin https://cdn3.vzwdm.com/hdm/chr2fa_fw_3.3.0.11_loader_1715281399811.bin https://cdn3.vzwdm.com/hdm/chr2fa_fw_3.3.1.2_1735849764361.bin

The firmware with the oldsig caught my attention. That is the first time we’ve seen this in the file name, and version 3.2.0.11 is actually one that we didn’t previously have. Unfortunately we don’t get any different outcomes using binwalk on these newly found firmware. However, the G3100/E3200 are Broadcom devices, and I found this script (BRCM-Unpack) that is supposed to unpack their firmware. Sadly it doesn’t correctly extract any of the G1100/G3100/E3200 firmware, but we get the following output for ALL of the CR1000A/B.

Code:
Image Processing Started on Thu 26 Jun 08:04:50 EDT 2025 Log: output.log Source: chr2fa_fw_3.2.0.11_oldsig.bin Size: 61219600 Checking Package Version SQFS Offset: 55468552 Saved: root_fs.sqfs Checking for FDT Pattern FDT Offset: 256 Saved: chr2fa_fw_3.2.0.11_oldsig.dtb chr2fa_fw_3.2.0.11_oldsig.dts: Warning (unit_address_vs_reg): /images/script/hash@1: node has a unit name, but no reg property chr2fa_fw_3.2.0.11_oldsig.dts: Warning (unit_address_vs_reg): /images/hlos-199b4e2d5c82b8034f572c5225279453506f03d4/hash@1: node has a unit name, but no reg property chr2fa_fw_3.2.0.11_oldsig.dts: Warning (unit_address_vs_reg): /images/rootfs-38f7ad8fe7922c1367cfac77ce43c6ee879dc450/hash@1: node has a unit name, but no reg property chr2fa_fw_3.2.0.11_oldsig.dts: Warning (unit_address_vs_reg): /images/wififw_v1-45b62ade000c18bfeeb23ae30e5a6811eac05e2f/hash@1: node has a unit name, but no reg property chr2fa_fw_3.2.0.11_oldsig.dts: Warning (unit_address_vs_reg): /images/wififw_v2-d1ec7b26faa44d75a2a40afa9a11c844f2b6ead3/hash@1: node has a unit name, but no reg property Saved: chr2fa_fw_3.2.0.11_oldsig.dts Description: Flashing emmc 200 200 Nodes: images Images: script hlos-199b4e2d5c82b8034f572c5225279453506f03d4 rootfs-38f7ad8fe7922c1367cfac77ce43c6ee879dc450 wififw_v1-45b62ade000c18bfeeb23ae30e5a6811eac05e2f wififw_v2-d1ec7b26faa44d75a2a40afa9a11c844f2b6ead3 Extracting: script   Description:  flash.scr   Created:      Wed May 24 13:38:48 2023   Type:        Script   Compression:  uncompressed Saved: script Extracting: hlos-199b4e2d5c82b8034f572c5225279453506f03d4   Description:  openwrt-ipq-ipq807x_64-qcom-ipq807x-hkxx-fit-uImage.itb.padded   Created:      Wed May 24 13:38:48 2023   Type:        Firmware   Compression:  uncompressed Saved: hlos-199b4e2d5c82b8034f572c5225279453506f03d4 Extracting: rootfs-38f7ad8fe7922c1367cfac77ce43c6ee879dc450   Description:  openwrt-ipq-ipq807x_64-squashfs-root.img   Created:      Wed May 24 13:38:48 2023   Type:        Firmware   Compression:  uncompressed Saved: rootfs-38f7ad8fe7922c1367cfac77ce43c6ee879dc450 Extracting: wififw_v1-45b62ade000c18bfeeb23ae30e5a6811eac05e2f   Description:  wifi_fw_squashfs.img   Created:      Wed May 24 13:38:48 2023   Type:        Firmware   Compression:  uncompressed Saved: wififw_v1-45b62ade000c18bfeeb23ae30e5a6811eac05e2f Extracting: wififw_v2-d1ec7b26faa44d75a2a40afa9a11c844f2b6ead3   Description:  wifi_fw_ipq8074_qcn9000_squashfs_v2.img   Created:      Wed May 24 13:38:48 2023   Type:        Firmware   Compression:  uncompressed Saved: wififw_v2-d1ec7b26faa44d75a2a40afa9a11c844f2b6ead3 Finished Image Processing: Thu 26 Jun 08:05:15 EDT 2025 Started Kernel Processing: Thu 26 Jun 08:05:15 EDT 2025 All Processing Completed on Thu 26 Jun 08:05:15 EDT 2025

The script extracted several images for us! That rootfs looks nice, but its LUKS encrypted.
Code:
rootfs-38f7ad8fe7922c1367cfac77ce43c6ee879dc450: LUKS encrypted file, ver 1 [aes, xts-plain64, sha1] UUID: 4d12098e-44d5-46f4-8dd4-2622485ae277

The file that starts with “hols-“ is actually the U-Boot image (fit-uImage.itb.padded), and is also encrypted. Fortunately the user spol-eff posted a script to decrypt this image. The original script was in Swift code, but I ported it to python.

Code:
import hashlib from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend import os import struct def decrypt_hlos(input_filepath, output_filepath):     """     Decrypts the HLOS image using SHA384 for key derivation and AES-256 CBC.     Args:         input_filepath (str): Path to the input encrypted HLOS file.         output_filepath (str): Path for the decrypted output file.     """     # 1. Key Derivation (SHA384)     # The Swift code uses SHA2(variant: .sha384).calculate(for: ...)     # The input bytes are [0x26, 0x46, 0x35, 0x75, 0x61, 0x23, 0x4f, 0x72, 0x36, 0x56]     key_material = bytes([0x26, 0x46, 0x35, 0x75, 0x61, 0x23, 0x4f, 0x72, 0x36, 0x56])     sha384_hash = hashlib.sha384(key_material).digest()     # The AES key is the first 0x20 (32) bytes of the SHA384 hash.     # SHA384 produces a 48-byte hash, so we take the prefix.     aes_key = sha384_hash[:0x20] # 32 bytes for AES-256     # 2. AES Setup (CBC Mode, No Padding)     # IV is Array(repeating: 0x0, count: 0x10) -> 16 null bytes     aes_iv = bytes([0x0] * 0x10) # 16 bytes for AES block size     # Initialize AES cipher     cipher = Cipher(algorithms.AES(aes_key), modes.CBC(aes_iv), backend=default_backend())     decryptor = cipher.decryptor()     # 3. File Handling and Decryption     try:         # Ensure output directory exists if output_filepath includes one         os.makedirs(os.path.dirname(output_filepath), exist_ok=True)         with open(input_filepath, 'rb') as input_file:             # Read the first 4 bytes (UInt32) for image size (little-endian)             # and then seek back and past the 0x200 offset.             # Swift code reads 4 bytes, then seeks to 0, then seeks to 0x200.             # We can directly seek to 0x200 and read the rest.                         # First, read the full content after the header to calculate size if needed             # For this script, we'll mimic the Swift behavior for imageSize display                         input_file.seek(0)             size_bytes = input_file.read(4)             if len(size_bytes) < 4:                 raise ValueError("Input file too small to read image size header.")                         # The Swift code loads as UInt32 littleEndian.             # struct.unpack('<I', ...) parses 4 bytes as unsigned int, little-endian.             image_size = struct.unpack('<I', size_bytes)[0]             print(f"Image size (from header): {image_size} bytes")             # Seek to the actual start of the encrypted data             input_file.seek(0x200)             image_bytes = input_file.read() # Read the rest of the file             # Decrypt the image bytes             decrypted_bytes = decryptor.update(image_bytes) + decryptor.finalize()         # Write decrypted data to output file         with open(output_filepath, 'wb') as output_file:             output_file.write(decrypted_bytes)         print(f"Done: written {len(decrypted_bytes)} bytes to {output_filepath}")     except FileNotFoundError:         print(f"Error: One of the files was not found.")         print(f"Input: {input_filepath}")         print(f"Output: {output_filepath}")     except Exception as e:         print(f"An error occurred: {e}")

Once the hlos- file is decrypted, the image unpacks cleanly with unblob! The U-Boot image contains /etc/keyfile

[Image: attachment.php?aid=1331]

On a Linux system with cryptsetup installed, we can use this keyfile to decrypt and open the LUKS encrypted rootfs.

Code:
#sudo cryptsetup --key-file=keyfile luksOpen <file_path> <mapping_name> -v sudo cryptsetup --key-file=keyfile luksOpen rootfs-38f7ad8fe7922c1367cfac77ce43c6ee879dc450 CR1000A_rootfs -v

This command has -v for verbose output, and should display:
Key slot 0 unlocked.
Command successful.

The decrypted SquashFS image will be located at /dev/mapper/<mapping_name>, so we can extract the image with

Code:
#sudo unsquashfs /dev/mapper/<mapping_name> sudo unsquashfs /dev/mapper/CR1000A_rootfs

Which gives us the full, decrypted rootfs Smile

[Image: attachment.php?aid=1332]

The keyfiles themselves aren’t in plain text, but we can view/share them using the command

Code:
cryptsetup luksDump —dump-master-key —key-file <keyfile path> <rootfs path> WARNING! ======== The header dump with volume key is sensitive information that allows access to encrypted partition without a passphrase. This dump should be stored encrypted in a safe place. Are you sure? (Type 'yes' in capital letters): YES LUKS header information for rootfs-38f7ad8fe7922c1367cfac77ce43c6ee879dc450 Cipher name:      aes Cipher mode:      xts-plain64 Payload offset:    4096 UUID:              4d12098e-44d5-46f4-8dd4-2622485ae277 MK bits:          256 MK dump:    30 c8 8e 47 a9 a0 d2 90 bb 3c 22 27 3f c7 53 a6         71 e7 29 80 53 1f 43 67 e1 dd ca d4 5c c9 3a f4

I tried all of the above steps on the latest CR1000A firmware (chr2fa_fw_3.6.0.2_BD_loader.bin), everything works as expected!

Code:
LUKS header information for rootfs-d616347925ecd1d9eb4366fd0013d30798e505f5 Cipher name:      aes Cipher mode:      xts-plain64 Payload offset:    4096 UUID:              36281f72-7198-49fb-aa70-70b1557b8b1b MK bits:          256 MK dump:    82 29 97 83 3e 52 25 92 6b c5 c8 10 4c 32 a8 ea         be 99 f1 68 ae 08 6a c8 c7 86 fe 3d 31 aa 27 39


I haven’t had much of a chance to poke around, but please let me know if anything catches your eye.


Attached Files
.png   hlos_image.png (Size: 142.24 KB / Downloads: 116)
.png   SquasFS_root.png (Size: 366.02 KB / Downloads: 122)
.txt   3_letter_words.txt (Size: 1.77 KB / Downloads: 8)
.txt   4_letter_words.txt (Size: 4.33 KB / Downloads: 6)
.txt   5_letter_words.txt (Size: 3.58 KB / Downloads: 6)
Reply


Messages In This Thread
RE: Verizon Fios G3100 and E3200 Research - by FiosFiend - 06-30-2025, 04:20 AM