Skip to content

Franz Franz

goFranz // personal journal all writing
Tools · guix

Reviving a BlackBerry KEY2

I put LineageOS on an old BlackBerry KEY2 from a Guix machine

I’ve had a BlackBerry KEY2 sitting in a drawer since it stopped getting updates. Physical keyboard, small screen. The hardware was fine, the software had been dead for years. This week I finally put LineageOS on it.

There’s a small community keeping this device alive (Lineage-BBKey2, unofficial, actively maintained), and the recipe is well documented:

  1. Unlock the bootloader with kibo, which exploits a fastboot buffer overflow
  2. Reflash BlackBerry’s own signed firmware through their autoloader
  3. Sideload LineageOS and GApps through recovery

None of that is new. The twist: I did it from a Guix machine, and Guix doesn’t play along with anything that expects a normal Linux filesystem.

Guix has no /lib64/ld-linux-x86-64.so.2

Google’s platform-tools and kibo’s prebuilt binary both expect /lib64/ld-linux-x86-64.so.2 and a handful of libraries at fixed paths. None of that exists on Guix. patchelf fixes it:

$ patchelf --set-interpreter $GLIBC/lib/ld-linux-x86-64.so.2 \
           --set-rpath "$GLIBC/lib:$LIBUSB/lib" kibo

Point the interpreter and rpath at the right store paths and the binary runs natively; no container, full USB access. Guix does package adb and fastboot, but they’re stuck at 7.1.2 from 2016. Google’s current 37.0.1 splits sparse images properly, which matters when you push a 3.2GB system.img against a 512MB per-transfer limit.

kibo’s device check was wrong

The unlock guide says to flash BlackBerry’s firmware twice (their A/B implementation is that broken). I did, and kibo still reported one of the two boot chains as INVALID and refused to unlock.

I wrote a small USB probe with pyusb to dump the raw response to the info query. Turns out kibo reads fixed-size buffers off the wire and never null-terminates them, so its strcmp() calls sometimes read past the real bytes into whatever is left on the stack. One buffer happened to sit next to a zero; the other didn’t.

kibo is GPL and three source files. Three lines to null-terminate each response at its actual length, then rebuild:

$ guix shell cmake make gcc-toolchain pkg-config libusb-next -- \
    cmake -B build && cmake --build build

Second run: Your device is vulnerable.

The result

The unlock went through, LineageOS 22.2 and MindTheGapps sideloaded without trouble, and the KEY2 booted Android 15 on a Snapdragon 660 from 2018. Gboard doesn’t reliably hide itself for the hardware keyboard on this build; K12KB, which the ROM ships for exactly that reason, does.

It’s a 2018 phone on an unofficial port. Dual SIM has a known bug (I only use one). But the keyboard clicks like new, and the phone that sat in a drawer for two years is back in my pocket. Good luck :)