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
(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.
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!
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.
The script extracted several images for us! That rootfs looks nice, but its LUKS encrypted.
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.
Once the hlos- file is decrypted, the image unpacks cleanly with unblob! The U-Boot image contains /etc/keyfile
![[Image: attachment.php?aid=1331]](https://hashcat.net/forum/attachment.php?aid=1331)
On a Linux system with cryptsetup installed, we can use this keyfile to decrypt and open the LUKS encrypted rootfs.
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
Which gives us the full, decrypted rootfs
![[Image: attachment.php?aid=1332]](https://hashcat.net/forum/attachment.php?aid=1332)
The keyfiles themselves aren’t in plain text, but we can view/share them using the command
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!
I haven’t had much of a chance to poke around, but please let me know if anything catches your eye.
@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

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
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

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.