· 6 min read ·

The Blob Was Just 100 Lines of Protocol: What Lenovo's WWAN Lock Actually Hides

Source: lobsters

When a vendor-supplied binary turns out to be replaceable by 100 lines of bash, the most revealing thing is not the script. It is what the script’s existence says about why the blob existed at all.

Hofstede’s writeup documents replacing Lenovo’s WWAN unlock binary with a clean-room shell script on a ThinkPad. The blob in question is a small executable that runs as root via udev when a WWAN modem is attached, sends a specific command over the modem’s USB control interface, and exits. Without it, the modem enumerates fine, responds to standard capability queries, but refuses to register on any cellular network.

Replacing it required reverse engineering the exact bytes that binary sends. The bash script does the same thing. The only thing proprietary about the original was that nobody had documented what it did.

Two Layers of Hardware Lock

To understand what the script is unlocking, you need Lenovo’s two-generation history of keeping WWAN hardware under control.

The first generation was a BIOS whitelist enforced on older ThinkPads. During POST, the UEFI would enumerate PCIe and USB devices and halt with an 1802 error if it found any wireless card whose vendor and device ID was not in a hardcoded list. This was entirely hardware-enforced. The community response was to patch the BIOS binary, and tools like no-1802 and custom BIOS images circulated on ThinkPad forums for years. Lenovo never officially acknowledged these patches.

Starting around 2016, newer ThinkPads moved to a different mechanism. The BIOS whitelist largely disappeared, replaced by a software lock inside the modem itself. A Sierra Wireless EM7455, a Fibocom L850-GL, or a Quectel variant would enumerate on USB, respond to standard capability queries, and report a valid IMEI and SIM. Then it would decline to register on any network. The lock was not in the BIOS. It was in the modem firmware, controlled via the host-side USB interface, and Lenovo’s blob was the key.

The MBIM Protocol and Vendor Extensions

Modern cellular modems on Linux communicate over MBIM, the Mobile Broadband Interface Model. MBIM runs over USB as a control channel, sending structured messages that identify a service by a 128-bit UUID and a command ID within that service. The standard MBIM services cover device capabilities (UUID a289cc33-bcbb-8b4f-b6b0-133ec2aae6df), SMS, network registration, bearer management, and firmware updates.

The protocol also allows vendor-defined services, where an OEM registers a proprietary UUID and defines their own command IDs and payload formats. This is a legitimate mechanism, described in the MBIM specification, intended for OEM customization. Lenovo uses it for the unlock.

A simplified MBIM command message on the wire looks like this:

MBIM_COMMAND_MSG {
  MessageType:             0x00000003
  TotalLength:             (variable)
  TransactionId:           (sequence number)
  ServiceId:               {Lenovo-proprietary UUID, 16 bytes}
  CID:                     0x0F  (vendor-defined)
  CommandType:             0x01  (SET)
  InformationBufferLength: (payload length)
  InformationBuffer:       (IMEI-derived token, ~20 bytes)
}

The payload is derived from the modem’s IMEI. A static key embedded in the blob is combined with the IMEI via a simple transform. The modem verifies the result and transitions from locked to operational. The transform is not cryptographically meaningful; it is obscurity, not security. Once extracted from the blob through instrumentation, it fits in a few lines of Python.

How the Reverse Engineering Works

The method used here follows a standard playbook the community has applied to many blobs.

First, strace on the running binary shows what files it opens, what device nodes it accesses, and the raw bytes written to them. For a WWAN blob, this reveals the character device path (/dev/cdc-wdm0 typically) and the raw MBIM command bytes sent to it.

Second, traffic capture via usbmon or Wireshark with USBPcap captures the USB control messages at a lower level, confirming the MBIM framing and showing the complete byte sequence including header fields that strace might truncate.

Third, cross-referencing the captured bytes against the MBIM specification identifies the service UUID and CID. For Lenovo’s case, the UUID is not in the public MBIM spec, but the message framing is standard, so the structure is clear and only the payload semantics require further analysis.

Fourth, the payload analysis. If the payload varies per device (and IMEI-based tokens do), running the blob on two or more devices with known IMEIs lets you reverse the derivation function by comparing inputs to outputs. A simple XOR with a static key is immediately obvious from even two data points.

The Replacement Script

The bash script that replaces all of this is three steps:

#!/usr/bin/env bash
set -euo pipefail

DEVICE="${1:-/dev/cdc-wdm0}"

# 1. Read the IMEI via standard MBIM
IMEI=$(mbimcli -d "$DEVICE" --query-device-caps \
  | grep -oP 'DeviceId:\s*\K[0-9]+')

# 2. Derive the unlock token from the IMEI
TOKEN=$(python3 -c "
import sys
key = bytes.fromhex('EXTRACTED_STATIC_KEY')
imei = '$IMEI'.encode('ascii')
token = bytes(a ^ b for a, b in zip(imei[:len(key)], key))
print(token.hex())
")

# 3. Send the vendor MBIM command
mbimcli -d "$DEVICE" \
  --ms-set-device-service-command \
  --service-uuid="EXTRACTED-LENOVO-UUID" \
  --cid=0x0F \
  --payload-hex="$TOKEN"

A udev rule triggers the script whenever the modem attaches:

ACTION=="add", SUBSYSTEM=="usb", \
  ATTRS{idVendor}=="1199", ATTRS{idProduct}=="9079", \
  RUN+="/usr/local/bin/lenovo-wwan-unlock"

The mbimcli tool comes from libmbim, the same library that ModemManager uses internally. It is a standard part of the Linux mobile broadband stack, available in every major distribution’s package repositories.

Why Vendors Ship Blobs Instead of Scripts

The obvious question is why Lenovo ships a compiled binary to do something a bash script handles. The cynical read is that the blob makes the mechanism opaque, discouraging users from understanding the lock or modifying it. The more charitable read involves the support matrix.

Lenovo supports specific distributions. Ubuntu and RHEL get official packages. Users running Arch, Gentoo, NixOS, or any other distribution are outside the support boundary. A compiled binary per architecture means Lenovo can ship one artifact without maintaining shell scripts across varied environments. Convenient for them.

The FCC provides additional context. A 2015 ruling on 5GHz UNII devices required manufacturers to prevent modification of RF parameters by end users. Many OEMs used this as rationale to lock wireless hardware more aggressively, including WWAN modems, even though the ruling specifically targeted unlicensed spectrum channels and transmit power, not operation in licensed cellular bands. The lock acquires a compliance-flavored justification, even when the technical necessity is debatable.

Hardware tiering is a third factor. OEMs sell WWAN modems as an optional paid add-on. Keeping the activation mechanism proprietary discourages gray-market modem upgrades and maintains the upsell.

The Security Case Against Opaque Blobs

Running any binary as root via udev means trusting the vendor with complete system access on every device attach. The blob has no source to audit. It runs on hardware events, meaning a compromised distribution channel delivers arbitrary root code to every machine with the matching USB hardware ID.

Vendors do not update blobs when models fall out of support. If the blob has a vulnerability after EOL, it stays. The bash script is auditable, patchable, and does not become a persistent security liability when Lenovo’s attention moves to newer hardware.

This is the same argument driving the linux-firmware repository’s WHENCE file, which tracks provenance and redistribution rights for every blob. Blobs are accepted there because the hardware requires them and open alternatives do not exist. When an open alternative exists, as Hofstede’s script demonstrates, the blob’s presence becomes harder to justify on principle.

A Pattern With Precedent

This is not an isolated case. Intel’s IPU6 image processing unit, used for cameras on recent ThinkPad models, required multiple binary blobs that the community spent roughly two years reverse-engineering. The resulting ivsc-driver was eventually merged into the Linux kernel in 6.2. The Atheros ath9k-htc USB wireless firmware is fully open source, hosted at open-ath9k-htc-firmware, demonstrating that open firmware for complex radio hardware is achievable when the vendor decides to allow it.

HP applied essentially the same WWAN soft-lock mechanism to EliteBook hardware, and the community response was identical: strace, usbmon, reconstruction, replacement script. The pattern repeats across OEMs because the underlying incentives are the same.

The replacement of Lenovo’s WWAN blob follows the same arc in compressed time: undocumented proprietary mechanism, community reverse engineers it, clean-room replacement ships. The only variable is how long the arc takes. In this case, the mechanism was simple enough that a single developer could close the loop in a weekend.

A 100-line bash script replacing a vendor binary is not a curiosity. It is a measurement of how much of the blob’s complexity was genuine and how much was chosen opacity. When the answer is “almost none was genuine,” the blob was never about technical necessity.

Was this interesting?