For years, the Icotera i4882 sat on my desk like an impenetrable fortress. Provided by fiber ISPs across Scandinavia, this optical network terminal (ONT) and router was designed to be completely locked down. No open ports, no public firmware downloads, and no straightforward way to see what was running under the hood.
Every attempt at breaking through via standard network attacks hit a dead end. But as anyone passionate about hardware reverse engineering knows, when software walling leaves you stranded, you look at the physical silicon.
I knew that if I could intercede early enough in the boot sequence, I could intercept control before the Operating System locked the door behind itself. The target was the SECOND-stage bootloader: U-Boot.
I attached my probes to the serial lines and located the NAND flash memory chip on the PCB. The plan was Fault Injection (NAND Glitching).
- The Target: The data/control lines between the System-on-Chip (SoC) and the NAND flash memory.
- The Execution: Right as the router powered on and U-Boot attempted to read its environment parameters and boot commands from flash, I momentarily shorted a NAND data pin to ground.
- The Result: The deliberate read corruption triggered a boot failure in U-Boot’s automated script execution (
bootcmd). Instead of launching the locked Linux kernel, the bootloader dropped straight into an interactive command shell:
U-Boot >
We were inside the bootloader.
From the U-Boot shell, I extracted the raw contents of the NAND flash memory to my workstation. Mounting the extracted file system revealed the internal binaries and shared libraries powering the router.
In one shared library file: libcliic.so. This library handled internal command-line interface utilities, firmware validation, and update routines.
I loaded libcliic.so into Ghidra for static reverse engineering. After tracing cryptography-related symbols, I stumbled upon a crucial function:
ict_cli_ssl_decrypt_firmware
Looking closely at the references inside this function, two static data arrays emerged in the data segment, starting at address DAT_0041f648:
DAT_0041f648 XREF[1]: ict_cli_ssl_decrypt_firmware:004
0041f648 10 DF 0C 2A CF FB 9E 22 1E C4 0E 9B D3 A6 70 DB
0041f658 F9 DF 58 BD 55 3D 6C 44 4E D6 B8 10 C7 0A F7 83
...
The raw bytes weren't the plain AES key. The disassembly revealed a custom XOR transformation and bit-shifting loop applied across these arrays to reconstruct the actual decryption key in memory.
To extract the real key without having to execute the code live on the MIPS/ARM architecture, I translated the Ghidra decompiler output into a standalone Python script:
def generate_ict_key():
# DAT_0041f648 (64 bytes)
data_648 = bytes.fromhex("10df0c2acfbf9e221ec40e9bd3a670dbf9df58bd553d6c444ed6b810c70af7833301e728458393a1c2c4aabb3b7d36d7314e8b345ef2fff6d2e3eed22d0011a1")
# DAT_0041f688 (32 bytes)
data_688 = bytes.fromhex("3301e728458393a1c2c4aabb3b7d36d7314e8b345ef2fff6d2e3eed22d0011a1")
local_90 = list(data_648[:64])
local_50 = list(data_688[:32])
uVar5 = 0
for i in range(64):
if uVar5 > 31:
uVar5 = 0
b1 = local_50[uVar5]
b2 = local_90[i]
# XOR and bitwise manipulations derived from Ghidra decompilation
res_xor = b1 ^ b2
uVar2 = (res_xor << 24) & 0xFFFFFFFF
uVar3 = (uVar2 & 0x18ffffff) | ((res_xor << 31) & 0xFFFFFFFF) | ((uVar2 >> 31) << 24) | ((((uVar2 & 0x7effffff) << 6) >> 31) << 30) | ((((uVar2 & 0x7effffff) << 1) >> 31) << 25)
val = (uVar3 >> 24) & 0xe7
val |= ((((uVar2 & 0x3cffffff) << 5) >> 31) << 29) >> 24
val |= ((((uVar2 & 0x3cffffff) << 2) >> 31) << 26) >> 24
val |= (((uVar3 << 4) >> 31) << 28) >> 24
val |= (((uVar3 << 3) >> 31) << 27) >> 24
local_90[i] = val & 0xFF
uVar5 += 1
return bytes(local_90[:32])
key = generate_ict_key()
print(f"AES-256 Key: {key.hex()}")Executing this gave us the master AES-256 decryption key:
c47bd740511eb0c13b00250417db62301389cb91d0f3c94d39ac6a4357506744
With the key in hand, analyzing the structure of an official Icotera .bin firmware file showed:
- Bytes 0–128: Proprietary header and metadata
- Bytes 129–144: The 16-byte Initialization Vector (IV)
- Bytes 150+: The AES-256-CBC encrypted payload
Combining this knowledge into a single Bash pipeline:
tail -c +150 firmware.bin | openssl enc -aes-256-cbc -nosalt -d -K 'c47bd740511eb0c13b00250417db62301389cb91d0f3c94d39ac6a4357506744' -iv $(dd skip=129 count=16 if=firmware.bin bs=1 status=none | hexdump -e '16/1 "%02x"') -nopad -out firmware.tar.gzRunning tar -xzf firmware.tar.gz finally cracked open the encrypted vault that had been sealed for years.
I didn't achieve a full local root shell on the live running router system yet—that remains an active milestone for the future. But unpacking the firmware exposed the raw configuration files, internal scripts, and hidden Web Interface credentials.
Deep inside the default configuration parameters, I discovered the operator-level account credentials used by ISPs to control the Web UI:
Device UserInterface X_GETOUI_Webui Operator Username operator
Device UserInterface X_GETOUI_Webui Operator Password L4ss0tF4ng4ralg3n!
After years of curiosity and endless trial and error, the black box was finally transparent.
This journey started with physical hardware hacking and ended with full firmware decryption and hidden credential extraction.
Through serial interface analysis and firmware extraction, the specific hardware architectures for the Icotera devices were identified:
- Icotera i4882: Powered by a MIPS architecture processor.
- Icotera i3552 / i3552i: Powered by a Synopsys ARC700 processor.
- UART Serial Interface: Both devices expose UART headers operating at 115200 8N1 (115200 baud, 8 data bits, no parity, 1 stop bit).
- FileSystem: Decrypted firmware payloads contain a standard SquashFS file system, which can be extracted using standard tools like
binwalkorunsquashfs.
After extensive testing and dynamic analysis, several core security boundaries were mapped out:
- U-Boot Intercept: Interrupting the early boot process via
CTRL+Xopens a password prompt. However, static reverse engineering in Ghidra revealed that the password check is either non-functional or bypassed—the bootloader drops to a console regardless of the input provided. - Cryptographic Firmware Signing: Flashing custom/modified firmware to the NAND flash is currently impossible. Icotera enforces strict RSA cryptographic signature verification during the flash and boot phases. Without the private vendor key, any modified image will be rejected or brick the device.
- Local Root Shell: Achieving a persistent local root shell on a running unit was not achieved due to signed image constraints and hardened execution environments.
- Primary Achievement: Despite the signed firmware barrier, the complete reverse engineering of the firmware decryption pipeline allows for full offline inspection of the system, extracting hardcoded ISP operator credentials, configuration files, and internal logic.