Getting the BCM4389 in Pixel 6 into monitor mode for tcpdump/Wireshark WIFI sniffing
A little side project to debug a WIFI 6E TP-Link mesh network in my house, went from "This sounds easy!" to "This is impossible!" to "It can't be this easy, can it?" Anyway: since I couldn't find any online instructions to sniff WIFI packets on my Pixel 6 Pro, I figured I should do a quick writeup for others to follow. I feel sure that the firmware and binaries used here could be leveraged in a custom ROM for Pixel 6 and maybe even pilfered for monitor mode on other devices that use BCM4389.
* daemon not running; starting now at tcp:5037
* daemon started successfully
restarting adbd as root
C:\...\platform-tools_r33.0.2-windows\platform-tools> adb shell
Now, you have a root shell on your phone (Notice, the prompt ends with #).
raven:/ # setprop persist.vendor.wifi.sniffer.bandwidth 160
# Set 5GHz band
Notice, these two properties are persistent and the values will survive a reboot. (They're stored to disk in /data/property/persistent_properties.)
Also notice, for the 5 GHz band, only "5180" works. If you set an adjacent channel it'll capture 2.4 GHz instead (2412 MHz). I was able to capture on multiple other channels like 2432, 6135 (WIFI 6E), etc., so I'm not sure why I struggled with other 5GHz frequencies earlier.
Last, the exciting part! Reload your BCM4389 with firmware that enables monitor mode. When it works, it looks like this:
raven:/ # wifi_sniffer start
11-30 16:21:03.761 26583 26583 I WIFI_SNIFFER: Starting monitor on frequence 2412 <- from persist.vendor.wifi.sniffer.freq
11-30 16:21:03.761 26583 26583 D WIFI_SNIFFER: update_sys_param: /sys/wifi/firmware_path fw_bcmdhd_monitor.bin
Here's how I got my Pixel 6 Pro (raven) to sniff WIFI packets, specifically beacons coming from my AP. The same directions will work on Pixel 6, and probably Bluejay (6a). It seems likely to work on Pixel 7 but I don't have one to try.
Prerequisites: Platform Tools from Android, for ADB, installed on your PC. You might also want to install Wireshark, but you don't strictly need it.
Step 1: Enable bootloader unlocking, then unlock the bootloader.
(Yes, this erases userdata! Also, be careful!)
You can find instructions on the web for doing this.
Step 2: Flash an aosp_raven-userdebug (or aosp_oriole-userdebug for Pixel 6) build
This build worked for me:
Android/aosp_raven/raven:UpsideDownCake/AOSP.MASTER/9344440:userdebug/test-keys
Here's a direct link to flash.android.com for that build, just pick the right device and target.
If the flash tool can't see your phone, try "adb kill-server", make sure to enable ADB in developer options, or put the phone into fastboot by rebooting with volume-down key held.
The flash tool (Thanks Google for the awesome flash tool!) will prompt you to complete unlocking the bootloader if needed.
When you're done, you can return your Pixel 6 to its original state with flash.android.com/back-to-public
If you just want to see network traffic to your phone, stop here, and use ADB to run "tcpdump" with your favorite options. "-w" can store it to a .pcap file and then you can pull it to open with Wireshark. There's also an androiddump external input on Wireshark, that can supposedly use tcpdump, but I didn't figure it out in the short time I tried to make it work.
Step 3: Configure and enable monitor mode
(step 3.1: How did I figure this out: separate blog post)
Hopefully ADB is already in your path, but if not, just navigate to the path where you unzipped it, adb root and adb shell.
C:\...\platform-tools_r33.0.2-windows\platform-tools> adb root* daemon not running; starting now at tcp:5037
* daemon started successfully
restarting adbd as root
C:\...\platform-tools_r33.0.2-windows\platform-tools> adb shell
raven:/ #
Now, you have a root shell on your phone (Notice, the prompt ends with #).
Configure frequency and bandwidth
Next, you're going to configure the options for frequency and bandwidth with these two system properties. Here's one example for 5 GHz. (For 2.4 GHz, try 2412 as the frequency)
# Set bandwidth to 160 MHz for sniffing on 5 GHzraven:/ # setprop persist.vendor.wifi.sniffer.bandwidth 160
# Set 5GHz band
raven:/ # setprop persist.vendor.wifi.sniffer.freq 5180
Notice, these two properties are persistent and the values will survive a reboot. (They're stored to disk in /data/property/persistent_properties.)
Enable Monitor Mode
Let's watch the output of our helper utility called "wifi_sniffer", by running this logcat in the background: (You could run it in a second ADB shell window if you want, too)
raven:/ # logcat | grep SNIFFER &
Last, the exciting part! Reload your BCM4389 with firmware that enables monitor mode. When it works, it looks like this:
11-30 16:21:03.761 26583 26583 I WIFI_SNIFFER: Starting monitor on frequence 2412 <- from persist.vendor.wifi.sniffer.freq
11-30 16:21:03.761 26583 26583 D WIFI_SNIFFER: update_sys_param: /sys/wifi/firmware_path fw_bcmdhd_monitor.bin
raven:/ #
Really? That's it? Thanks Google! You can see the logcat logs with tag WIFI_SNIFFER mixed into my console here, which makes it easy to see if it worked.
Errors you might see in logcat:
11-30 15:57:15.462 4779 4779 E WIFI_SNIFFER: frequency is empty
11-30 15:59:50.231 9527 9527 E WIFI_SNIFFER: ERROR: freq is zero
Make sure you have set persist.vendor.wifi.sniffer.bandwidth to a number in megahertz. Check it with this command: getprop persist.vendor.wifi.sniffer.bandwidth 11-30 16:00:06.113 10026 10026 E WIFI_SNIFFER: Failed to up radiotap0
# Stream some sniffed packets to stdio to see what it's capturing, make sure you have the right frequency and the bandwidth makes sense
raven:/ # tcpdump -i radiotap0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on radiotap0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), snapshot length 262144 bytes
16:03:43.048182 18833711us tsft 1.0 Mb/s 2412 MHz 11g -72dBm signal -89dBm noise antenna 0 Beacon () [1.0* 2.0* 5.5* 11.0* 18.0 24.0 36.0 54.0 Mbit] ESS CH: 2, PRIVACY
# Save beacon packets to a .pcap file for Wireshark to open later
raven:/ # tcpdump -i radiotap0 type mgt subtype beacon -w /data/beacon-capture.pcap
tcpdump: listening on radiotap0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), snapshot length 262144 bytes
^C120 packets captured
144 packets received by filter
# Pull the pcap file using ADB, from the phone to your host.
C:\...\platform-tools_r33.0.2-windows\platform-tools\> adb pull /data/beacon-capture.pcap
I hope you found this useful!
Android, or wpa_supplicant etc., has interfered with what you're doing to the wifi driver. The small hammer fix: Forget any WIFI networks, turn off WIFI via the UI, maybe turn off location, and try "wifi_sniffer start" again, it will eventually work. The big hammer fix: Stop android altogether, and try "wifi_sniffer start" again. C:\> adb shell stop
(you can use "adb shell start" or failsafe "adb reboot" to restart android.)
Step 4: Run tcpdump
At last, you can run tcpdump on interface radiotap0, with your favorite options.
raven:/ # tcpdump -i radiotap0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on radiotap0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), snapshot length 262144 bytes
16:03:43.048182 18833711us tsft 1.0 Mb/s 2412 MHz 11g -72dBm signal -89dBm noise antenna 0 Beacon () [1.0* 2.0* 5.5* 11.0* 18.0 24.0 36.0 54.0 Mbit] ESS CH: 2, PRIVACY
...
raven:/ # tcpdump -i radiotap0 type mgt subtype beacon -w /data/beacon-capture.pcap
tcpdump: listening on radiotap0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), snapshot length 262144 bytes
^C120 packets captured
144 packets received by filter
0 packets dropped by kernel
C:\...\platform-tools_r33.0.2-windows\platform-tools\> adb pull /data/beacon-capture.pcap
/data/beacon-capture.pcap: 1 file pulled, 0 skipped. 4.7 MB/s (48779 bytes in 0.010s)
# now open the .pcap file with Wireshark
I hope you found this useful!
Comments
Post a Comment