In de midst of the Raspberry Pi shortage i came across this project. Someone figured out that a 4G WiFi router could be repurposed as a Single Board Computer (SBC) running Linux or OpenWRT. What piqued my interest was its decent compute power and features like a built-in 4G modem and GPS—something lacking in a comparable Raspberry Pi Zero W2. The goal? Transform this stick into a remote pentesting device accessible over 4G.


The OpenStick project was initiated by Handome Yingyang, who created a custom bootloader to enable running Linux instead of the default Android firmware. Zoltán Mizse of Extrowork subsequently penned an excellent article, detailing the recommended stick and providing instructions on how to get it operational.

Not all 4G sticks are compatible; we specifically need a stick running the Qualcomm MSM8916 chipset. Acquiring such a stick can be challenging, as there are limited compatible models, including:

  • UFI001B
  • UFI001C
  • UF896
  • UZ801
  • SP970

Your best chance of obtaining such a stick at an affordable price is through platforms like AliExpress or Amazon, with prices typically ranging from 12 to 15 dollars. I’ve personally acquired several sticks from different vendors and attempted to inquire about the version being sold, but most sellers were unaware. Consequently, acquiring the desired version can be hit or miss. Look for the keyword “MSM8916” in the product description. Typically, these sticks are black and a clue on the back of the stick is the presence of “SSID 4G-UFI-XX”

I have one UF896 stick and one UZ801 v3.0 stick. Most sticks sold currently are most likely to be the UZ801 v3.0 or v3.2. The v3.0 version is compatible and also the most stable stick i own.

In this tutorial, I’ll focus on the UZ801 v3.0 variant, which I found to be the most stable. If you have a different variant, you’ll need a distinct bootloader, boot image, and kernel. You can either search for these online or build your own.

Now that we have our stick, the first step is to flash the bootloader, boot image, and root filesystem to enable Linux. Our initial task is to enable ADB.


To activate ADB, insert the stick and allow it to fully boot up. Then establish a WiFi connection with the stick using the credentials specified on its back. After successfully logging in, launch a webbrowser and navigate to the stick’s management page at Log in with the username/password combination “admin.”

Once logged in, visit to enable ADB. Reboot the stick (by reinserting the stick into the PC) and verify that ADB is active post-reboot.

adb devices
List of devices attached
0123456789ABCDEF	device

To gain root access execute

adb shell
setprop service.adb.root 1; busybox killall adbd

After obtaining root access, it’s essential to create a comprehensive backup of the factory firmware. This backup serves as a safety net in case of any issues down the line. If you encounter problems later, you can restore any or all partitions using this backup. Unfortunately, I neglected to perform this step with my initial stick, and as a result, I messed up the modem partition, leading to a non-functional 4G connection due to the loss of IMEI information.


Initiate a reboot into EDL mode, which grants direct read and write access to the eMMC storage of the stick. This step is crucial for creating a comprehensive backup of the eMMC storage, providing a safety net for potential issues in the future.

adb reboot edl

Next, retrieve the EDL tool from Bjoern Kerler’s GitHub page and follow the provided instructions to install the necessary dependencies. Once installed, proceed to generate various backups.

Initially, create a full single image backup of the eMMC storage. This results in a large file encompassing all partitions. To restore, the entire file needs to be written back to the stick.

edl rf uz801-stock.bin

Subsequently, perform a full backup of each individual partition. This process produces a separate file for each partition, facilitating selective recovery if needed. For instance, use modem.bin for the modem partition.

edl rl uz801_stock --genxml

Upon completion, securely store all backup files. With the original firmware safeguarded, the software flashing process can commence. Simply unplug and reconnect the device to restore ADB access.


Disconnect and reconnect the stick once again to return to ADB mode. After the stick has fully booted up, execute the following command to access the bootloader. Fastboot will be employed to flash the new OpenStick firmware onto the device.

adb reboot bootloader

Verify if Fastboot recognizes the device by executing:

fastboot devices

A successful recognition should yield a value, confirming that the stick is now in Fastboot mode and prepared to receive the new firmware.


The original firmware by Handsome Yingyang ran Debian Bullseye. I’ve upgraded mine to Debian Bookworm, incorporating several modifications for enhanced versatility. The choice is yours regarding which version to install; the following commands are tailored to my version. If you prefer Handsome Yingyang’s version, download it from his repository here.

Begin by downloading my OpenStick release:


Now, unzip the file and flash the new firmware onto the stick:

cd OpenStick/flash/

Assuming everything proceeded as intended without any errors, the stick should have automatically rebooted. After the reboot, the new software (in this instance, Debian Bookworm) should be up and running, allowing us to log in to the stick.


The stick is currently operating on a basic version of Debian Bookworm, allowing us to install various applications within the constraints of the 3.2GB available storage. Notably, the stick’s kernel is compiled with USB Gadget support, and both the libusbgx library and the gadget tool are installed.


For SSH access, my Debian version on the stick will automatically create an RNDIS USB gadget device with an IP address of upon boot. We can establish a SSH connection to the stick as follows:

ssh user@

Please note that the default password for the user is: 1


In addition to the RNDIS network connection, a WiFi hotspot is generated during the initial bootup. Connect to the WiFi hotspot using the following credentials:

  • PSK: 1234567890

To establish an SSH connection over WiFi, use the following command:

ssh user@

Please note that the default password for the user is: 1

Connect to Internet

Now that we’re logged in we want to connect to internet for updating and installing software. The stick has te ability to connect to the internet through WiFi or 4G. Since setting up WiFi is easier we’ll start with that one.


As Debian employs NetworkManager, we can leverage nmcli (or nmtui if you prefer) to set up and activate our WiFi connection. Replace SSID and PASSWORD with the appropriate values for connecting to your wireless network.

To begin, delete the hotspot connection:

nmcli connection delete hotspot

Next, connect to an access point:

sudo nmcli dev wifi connect "SSID" password "PASSWORD"

Check if wlan0 is successfully connected and has an assigned IP address:

ip show a wlan0

If the connection is successful, establish an SSH connection to that IP address using the earlier credentials:

ssh user@<ip-address>


One remarkable feature of this stick is its built-in 4G modem, enabling remote access from virtually anywhere in the world.

To configure the connection, we’ll use nmcli and work with a pre-created NetworkManager profile named “lte.”

Begin by editing the SIM card PIN setting. If you don’t have a PIN set, you can skip this step:

sudo nmcli connection modify lte <your_pin>

Next, set the APN for your cellular network provider. Many providers use “internet” as the APN, but it’s essential to verify this information on your provider’s website:

sudo nmcli connection modify lte gsm.apn <your_apn>

Activate the 4G connection:

sudo nmcli connection up lte

Check if the stick has successfully connected to the 4G network:

sudo mmcli -m 0

Verify if an IP address has been assigned:

ip a show wwan0

If the connection is established and an IP address is assigned, you’ve successfully connected the stick to a 4G network. Conduct a speed test to evaluate the connection speed:

sudo apt install speedtest-cli

Here’s an example of the result I obtained:

$ speedtest-cli 
Retrieving configuration...
Testing from KPN (
Retrieving server list...
Selecting best server based on ping...
Hosted by Redhosting (Almere) [29.20 km]: 58.1 ms
Testing download speed................................................................
Download: 36.46 Mbit/s
Testing upload speed..................................................................
Upload: 39.21 Mbit/s

Basic Usage

Now, let’s dive into the interesting part of this tutorial – altering USB function behavior using the USB Gadget library and three distinct command-line tools.

Here’s a summary of some commonly used USB Gadget functions:

    • Remote Network Driver Interface Specification (RNDIS)
    • Creates a Virtual Ethernet link on top of USB CDC (ECM)
  • HID
    • Human Interface Device (HID)
    • Creates a keyboard, mouse or gamecontroller
  • MSD
    • Mass Storage Device (MSD)
    • Create a USB mass storage device
  • FFS
    • Creates a USB FunctionFS device
  • MIDI
    • Creates a USB MIDI audio device
    • Creates a USB printer
  • UVC
    • USB Video Class (UVC)
    • Creates a USB webcam device
  • UAC
    • USB Audio Class (UAC)
    • Creates a USB audio device
  • ECM
    • Ethernet Control Module (ECM)
    • Creates a USB Ethernet device
  • ACM
    • Abstract Control Model (ACM)
    • Create a USB Serial device

As mentioned earlier, my build incorporates three command-line tools for USB Gadget manipulation. The first is the official tool from the creators of the libusbgx library, called GT (gadget tool). I prefer using this tool as it allows loading a gadget from a scheme (file) and supports enabling gadgets through a systemd service.

The second tool is GC (gadget controller), developed by Handsome Yingyang. Gadgets can be easily added using the GC command. For instance, adding an RNDIS gadget:

sudo gc -a rndis
sudo gc -e

Available options in GC include:

Usage : gc [options....] 
-h          Show this help. 
-l          Show active gadget functions. 
-c          Clean all active gadget. 
-e          Enable all active gadget. 
-d          Disable all active gadget. 
-a <function> [configs ...]   Add a gadget function. 
-r <name>      Remove a gadget function by name in list (-l).

The traditional method of adding USB gadgets is to use examples provided by libusbgx. For example, adding an RDNIS gadget:

sudo gadget-rndis-os-desc

Other available commands include:

gadget-acm-ecm         gadget-ffs             gadget-import          gadget-ms              gadget-rndis-os-desc   gadget-uvc             
gadget-export          gadget-hid             gadget-midi            gadget-printer         gadget-uac2            gadget-vid-pid-remove  

For the remainder of this tutorial, the focus will be on GT (Gadget Tool).

GT utilizes scheme files containing device settings for the USB Gadget you want to create. These scheme files are stored in the directory /usr/local/etc/gt/templates and can be loaded either through the gt@ systemd service or by directly issuing the command gt load.


By default, the USB function of the stick is set to RNDIS, turning the USB into an Ethernet device. It is currently configured as a standard 4G dongle, providing an IP address to the connected computer and acting as a router to the 4G network (internet).

To enable RNDIS, execute the following command:

sudo gt load --path /usr/local/etc/gt/templates rndis-os-desc.scheme

To remove it

sudo gt rm -rf rndis-os-desc


The HID functionality presents an intriguing usage scenario where the USB function can be set to HID, allowing the injection of keystrokes into the connected computer, similar to a Rubber Ducky. For now, let’s enable the USB HID gadget with the following command:

sudo gt load --path /usr/local/etc/gt/templates hid.scheme

Mass Storage

The stick can also function as a mass storage device for writing data. To achieve this, create a file on the stick capable of holding the data. For instance, I’ve chosen a 50MB file size using DD:

cd ~/
dd if=/dev/zero of=mass.img count=50 bs=1MB

Next, create a FAT partition on the file using fdisk. Follow these options:

$ sudo fdisk mass.img

Choose the fdisk options as follows:

Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS (MBR) disklabel with disk identifier 0x7151c4a3.

Command (m for help): o
Created a new DOS (MBR) disklabel with disk identifier 0xa758800f.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): 

Using default response p.
Partition number (1-4, default 1): 
First sector (2048-102399, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-102399, default 102399): 

Created a new partition 1 of type 'Linux' and of size 49 MiB.

Command (m for help): t
Selected partition 1
Hex code or alias (type L to list all): c
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.

Command (m for help): w
The partition table has been altered.
Syncing disks.

Create the FAT32 filesystem:

sudo mkfs.vfat mass.img

Then, create the mass storage device:

sudo gt load --path /usr/local/etc/gt/templates mass.scheme

I’ve included a few other schemes i found online. These include

acm-ecm.scheme    cdc-ecm.scheme  ffs.scheme  mass.scheme   midi.scheme     uac1.scheme       uvc.scheme      acm.scheme  bmc.scheme    ecm.scheme      hid.scheme        midi2.scheme    rndis-os-desc.scheme      uac2.scheme

It’s also possible to create your own GT schemes. Visit for part 1 and part 2 of their excellent tutorials on how to write your own GT schemes.

Advanced Usage

Now that we’ve covered the basics, let’s explore some more advanced examples, such as loading gadgets at startup using Systemd, creating your own USB gadgets using GT and some common traffic sniffing techniques using USB a ethernet gadget.


GT offers the ability to load USB Gadgets at startup using their provided systemd service file called gt@. This file is located in /etc/systemd/system and can be used to enable USB gadgets at startup. By default i’ve enabled the rndis-os-desc scheme to be loaded on startup this way. It relies on the GT config file (located in /usr/local/etc/gt/gt.conf) to tell it where it can find the scheme files. When that is set, you can simply create or export a gadget in the templates directory and load it on startup by issueing

sudo systemctl gt@<usb gadget>

Please note that the USB gadgets are loaded without the .scheme extension. So hid.scheme would be loaded as gt@hid

Create your own gadget

Previously i’ve showed how to load USB gadgets using GT scheme files. These files are merely just a collection of command which can just as easily be entered in sequence using the GT tool. This way you have total control on which gadget you create and when you’re finished export it to a scheme files for easy loading in the future.

Using GT let’s create a USB gadget called g1 and assign it an ECM function and config.

gt create g1
gt func create g1 ecm usb0
gt config create g1 c 1
gt config add g1 c 1 ecm usb0

We can also assign gadget attributes like vendor and product id

gt set g1 idVendor=0x1d6b idProduct=0x0104

Than we can enable the gadget by issueing

gt enable g1

That should have enabled the ECM gadget and make it show up on the host PC as an ethernet device. If you’d like to save your custom configuration just simply export it like so

gt save g1 ecm.scheme


To enhance anonymity, we’ll install Tor, allowing us to SSH into the system over Tor without revealing our actual IP address. If the stick is connected to the internet via WiFi or 4G, it automatically connects to the Tor network. To display your onion link, execute the following:

sudo cat /var/lib/tor/ssh/hostname

Copy the onion URL and log in from another PC. For instance, if the hostname is: 903jfbuvf5uxa27o3efkf6hpyugbrr5efvayycslris822lueejlkg81a, you can log in over Tor on a PC by issuing:

torify ssh user@903jfbuvf5uxa27o3efkf6hpyugbrr5efvayycslris822lueejlkg81a.onion


When logged in remotely, either via Tor or SSH directly we are presented with a regular Linux terminal and we can enable any of the USB gadgets we desire. To start off i’ll enable a USB ECM ethernet device. This will show up on the host PC as a regular ethernet adapter from which we can redirect some traffic to. So let’s remove the RNDIS gadget that is created on startup and add a ECM gadget.

sudo systemctl stop gt@rndis-os-desc
sudo gt load --path /usr/local/etc/gt/templates ecm.scheme


This will activate the ECM gadget and an IP address will be assigned to the host through dnsmasq. Then we want to redirect that traffic through our stick so that we can analyse the IP traffic. For that we need to do ARP spoofing and we need a tool called Bettercap for that.


I’ve compiled and installed the latest version of Bettercap on my version of OpenStick. Before using it, we need to update the caplets (predefined attacks) and the user interface:

sudo bettercap -eval "caplets.update; ui.update; q"

Launch Bettercap. This command will start Bettercap on interface usb0 and will also launch a web GUI on port 443. Either connect to it directly using the WAN or WiFi connection or use Tor if you want to be more anonymous

sudo bettercap -iface usb0 -caplet https-ui

Start the network sniffer

net.sniff on

Feel free to explore advanced features and configurations within Bettercap for a variety of network-related tasks.


If the stick is put into RNDIS gadget mode all traffic is routed through the stick by default. This is the whole idea behind RNDIS meaning that it will act as a router to the internet in this mode. When this mode is enabled the host PC will recognize it as a RNDIS adapter and will add it to the routing table with a lower metric than all the other router. Resulting in the default route going through the stick

In this configuration we don’t need to use ARP spoofing but we can simply listen on a specific interface (usb0 in out case) and see the traffic being sent and received. First disable the ECM gadget and enable the RNDIS gadget

sudo systemctl stop gt@ecm
sudo systemctl start gt@rndis-os-desc

Then launch tcpdump on usb0

sudo tcpdump -i usb0 -w - | socat - TCP-LISTEN:8000,reuseaddr

Or if you prefer to use Tshark to capture traffic. Launch Tshark on usb0 like so

sudo tshark -i usb0 -w - | socat - TCP-LISTEN:8000,reuseaddr

When either you launched Tcpdump or Tshark we can then launch Wireshark on the receiving end to inspect the network traffic that is routed through the stick. Launch Wireshark like so

socat TCP:<ip-address>:8000 - | wireshark -k -i -

All of the prior command require a direct IP connection to the stick itself, either through WiFi or the 4G connection. In most cases you aren’t in range of the WiFi connection of the stick and most cellular providers use NAT inside their 4G network. So there is no way to connect to the stick directly. We then have two option, the first one would be a reverse SSH connection to a host which is accessible from the internet. Or, like i’ve explained earlier, incorporate the anonymity of the Tor network.

torify socat TCP:903jfbuvf5uxa27o3efkf6hpyugbrr5efvayycslris822lueejlkg81a.onion:80 - | wireshark -k -i -

Rubber Ducky

Another great use case for the stick is the ability to insert keystrokes as if it we’re remotely controlled keyboard over the internet. This involves using the USB HID gadget. When the HID gadget is enabled (can support keyboard, mouse and joystick) a device is create called hidg0 in the directory /dev. Using that device we can use a script called DroidDucky to run pre defined Rubber Ducky payloads. These payload range from simple Notepad examples to full on Reverse Shell enablers. Choose one that suits your need and place it in the payloads directory.

For example purposes i’ve included a classic Rick Roll example. What this does is open up the Windows run prompt, enters a website url and goes full screen.

cd ~/ducky
sudo ./ payloads/rickroll.txt
Sir Rick

Creating your own payload is also possible. Refer to the Hak5 website to see a list of available commands

Or refer to this payload repository to download a Rubber Ducky payload


Fastboot button

When you’ve encountered a problem either by locking yourself out of the stick or by reflashing some or all of the partitions we need to go back into EDL mode and flash the partitions we want. The current bootloader supports entering Fastboot mode by pressing the reset button on the stick. While plugging in the stick hold this button for 5 seconds

If you’ve entered Fastboot mode succesfully then you can easily enter EDL mode by issuing the following command

fastboot oem reboot-edl

After that the stick reboots to EDL mode and we can start the recovery process from there

EDL pins

But what if that didn’t work, and the bootloader is non responsive. That we need to open up the stick and find these two headers on the PCB.

Short these two headers while plugging in the stick to a PC. EDL mode is forced and the stick can be recovered using the EDL image you created previously.


A few good resources I’ve found and based my build of OpenStick on, are:


If you like my work, please consider supporting.