External-adapter monitor mode + injection on a phone Kali NetHunter doesn't
support — running on the stock LineageOS kernel, no ROM swap, no custom boot
image, no bootloader risk. It works by building the rt2800usb driver stack from the
phone's exact GKI kernel source and loading it as modules on the running kernel.
Built and verified end-to-end: driver loads → Alfa RT3070 binds →
rt2870.binfirmware loads →mon0in monitor mode →airodump-ngcaptures live 802.11. Full write-up: docs/build-report.md.
This kernel has CONFIG_MODULE_FORCE_LOAD=n + CONFIG_MODVERSIONS=y, so a module
loads only if your uname -r matches exactly what it was built against:
6.1.145-android14-11-gec45f20f38ea-ab15260282
Check yours: adb shell uname -r (or uname -r on the phone).
- Matches? Use the prebuilt modules — Quick start below.
- Doesn't match (different LineageOS/GrapheneOS/stock build)? Rebuild for your
kernel with
scripts/build-modules.sh— same steps, automated. See Build from source.
flowchart TD
A["adb shell uname -r"] --> B{"== 6.1.145-…-ab15260282 ?"}
B -->|yes| C["scripts/install.sh<br/>(uses prebuilt .ko)"]
B -->|no| D["scripts/build-modules.sh<br/>(rebuild for your kernel)"]
D --> E["drop matching .ko in<br/>/data/adb/rt2x00"]
C --> F["reboot → auto-loads<br/>plug Alfa → tegu-mon"]
E --> F
- Google Pixel 9a (
tegu), bootloader unlocked, rooted (Magisk) - Kali NetHunter (or NetHunter Lite) installed — for the terminal + tools
- An external USB Wi-Fi adapter with an
rt2800usbchipset (e.g. Alfa AWUS036NH / AWUS036NHR, RT3070/RT3572) and a USB-C OTG adapter
On the phone as root (NetHunter terminal / Termux), or via adb shell → su:
git clone https://github.com/GPTmadeit/nethunter-pixel9a-rt2800usb
cd nethunter-pixel9a-rt2800usb
su -c 'sh scripts/install.sh'The installer verifies your kernel, stages the modules + rt2870.bin firmware into
/data/adb/rt2x00, installs a Magisk boot service so they auto-load every boot,
drops the tegu-mon helper into your NetHunter chroot, and loads everything now.
Then plug the Alfa into USB-C (via OTG) and, in the NetHunter terminal:
tegu-mon # brings up mon0 in monitor mode
airodump-ng mon0 # see the air
tegu-mon-stop # tear it downThat's it — mon0 is a normal monitor interface for airodump-ng, aireplay-ng,
wireshark, hcxdumptool, kismet, etc.
flowchart LR
subgraph phone["Pixel 9a · stock GKI kernel 6.1.145"]
cfg[cfg80211] --> mac["mac80211 (ours)"]
mac --> lib[rt2x00lib]
lib --> usb[rt2x00usb]
lib --> r28lib[rt2800lib]
usb --> r28[rt2800usb]
r28lib --> r28
bcm[bcmdhd4383<br/>internal Wi-Fi] --> cfg
end
r28 -->|USB-C OTG| alfa["Alfa RT3070<br/>148f:3070"]
alfa -.->|802.11| air(("air"))
air -.->|beacons/frames| alfa
cfg80211/rfkillare the device's own (unchanged).mac80211is ours, swapped in because the stock one had the softmac symbols trimmed. It's safe: the stockmac80211is unused (refcount 0) since the internal chip is fullmac.- The internal Wi-Fi keeps working the entire time.
The six ABI obstacles this had to clear (vermagic, symbol trimming, a cfg80211 CRC
config mismatch, LED + SoC-clock trims) are documented in
docs/build-report.md — worth reading if you're porting to
another adapter or device.
scripts/
install.sh on-device installer (kernel-match gate + auto-load service)
build-modules.sh rebuild the stack from source for YOUR kernel
patch-vermagic.py rewrite .ko vermagic to match your uname -r exactly
rt2x00-load.sh Magisk boot service that loads the stack every boot
tegu-mon bring up mon0 in monitor mode (safe: only touches the adapter's phy)
tegu-mon-stop tear monitor interfaces back down
patches/
0001-tegu-rt2800usb-wifi.patch the exact GKI changes (config + module list + 2 source fixes)
prebuilt/
6.1.145-ec45f20f38ea/*.ko modules for the original target kernel
firmware/rt2870.bin RT3070 firmware (from linux-firmware)
docs/
build-report.md full technical write-up
For any kernel other than the exact one above:
# on a Linux host / WSL2 Ubuntu, phone connected via adb:
sudo apt install -y git curl python3 build-essential bc bison flex libssl-dev \
libelf-dev rsync ccache zip unzip cpio # + Google's `repo`
KREL="$(adb shell uname -r | tr -d '\r')" ./scripts/build-modules.shIt repo-syncs the tegu kernel manifest, checks out the GKI at your kernel's commit,
applies the patch, builds with --lto=none --notrim, and vermagic-patches the output to
your exact release. Needs ~40 GB disk and ≥16 GB RAM. Output lands in prebuilt/.
Any rt2800usb device should just work. For a different mainline driver (e.g.
mt7601u, ath9k_htc, rtl8xxxu) the same recipe applies — enable it in
gki_defconfig, add its .ko to modules.bzl, rebuild. Out-of-tree Realtek drivers
(8812au etc.) need their source added as an external module; not covered here.
- Injection is untested live in this repo (it transmits) — the capability is
present; verify with
aireplay-ng --test mon0against your own AP. - Kernel updates change
uname -r→ you'll need to rebuild. That's inherent to loading modules onto a locked-down GKI kernel. - Uninstall:
rm /data/adb/service.d/rt2x00-load.sh(and reboot).
For authorized security testing, education, and research on networks you own or have explicit permission to test. Monitor mode and frame injection can be illegal to use against networks without authorization. You are responsible for complying with all applicable laws. Provided as-is, no warranty.
Kernel modules are derived from the Linux kernel / Android Common Kernel and are
licensed GPL-2.0 (see LICENSE). rt2870.bin is redistributable firmware
from linux-firmware.
Thanks to the rt2x00/mainline maintainers, the Kali NetHunter team, LineageOS, and the
seemoo-lab folks whose Nexmon work mapped out what's (not) possible on fullmac chips.