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: 55)
.png   SquasFS_root.png (Size: 366.02 KB / Downloads: 59)
.txt   3_letter_words.txt (Size: 1.77 KB / Downloads: 0)
.txt   4_letter_words.txt (Size: 4.33 KB / Downloads: 0)
.txt   5_letter_words.txt (Size: 3.58 KB / Downloads: 0)
Reply


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