0

I am working on a project to detect hand gestures using Wi-Fi Channel State Information (CSI) captured on a phone.

I'm looking for a way to get a live network capture taken using Nexmon CSI on a Nexus 5 to a PC that is attached to the phone over USB.

I'm currently using tcpdump to capture the packages into a file as seen below (not live), and I use a Python package called csiread to extract CSI magnitude and phase information into Numpy for visualization using Matplotlib.

adb shell "su -c 'tcpdump -i wlan0 -v dst port 5500 -c 50 -w /sdcard/capture.pcap'"

Quick note: Since Wireshark is able to read Nexmon captures in addition to any tcpdump capture, I'll be using that to demonstrate compatibility. The file generated with the above command can be opened using Wireshark.

My plan was to use adb shell "su -c 'tcpdump -i wlan0 -v dst port 5500 -c 50 -w -'" > wireshark -k -i - to test if the live packages are readable, but I receive this error: "Unrecognized libpcap format or not libpcap data."

Here are the things that work:

# tcpdump live feed on local maching piped to Wireshark
# '-w -' writes the captures to the standard output
sudo tcpdump -i any -w - | wireshark -k -i -
# (mentioned above) Nexmon tcpdump capture on phone through ADB to a file on phone
# file can be opened by wireshark and csiread
adb shell "su -c 'tcpdump -i wlan0 -vv dst port 5500 -w /sdcard/capture.pcap -c 50'"
adb pull /sdcard/capture.pcap ~/Desktop/capture.pcap

And here are the things that DON'T work:

The following code was inspired by this tutorial on how to get a live tcpdump feed from an SSH server.

# (fail) attempted to pipe live capture from phone tcpdump to wireshark
adb shell "su -c 'tcpdump -i wlan0 -v dst port 5500 -w -'" | wireshark -k -i -
# (fail) attemped to write live feed directly to a file on pc
# works with neither Wireshark nor csiread
# -c is the package count
adb shell "su -c 'tcpdump -i wlan0 -v dst port 5500 -c 2 -w -'" > ~/Desktop/adb_direct_capture.pcap

Here's Nexmon CSI's documentation. It doesn't seem to cover such cases.

What's curious is that upon inspecting the data piped directly over ADB, tcpdump's normal outputs such as "tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes" are also passed over. I tried removing such lines but the resulting file was still invalid. I get errors such as "Not a pcap capture file (bad magic: b'\xef\xbf\xbd\xc3')". When I inspected both "valid" and "invalid" files using a hex editor, the "valid" fiels seems to be much shorter even though they look the same length in a normal editor. My guess is that all the standard output data get messed up during their trip through ADB??

1 Answers1

0

I simply had to use adb exec-out instead of adb shell, while dumping the stderr:

adb exec-out "su -c 'tcpdump --flags-go-here -w - 2>/dev/null'" > path/filename.pcap

Let me explain starting from the beginning of the line:

  • adb exec-out "" directly transmits the binary output of any command passed to it, so it doesn't corrupt such files (which was my issue).
  • su -c '' runs the command as root.
  • tcpdump simply captures packets.
  • The -w - flag tells tcpdump to write directly to the standard output.
  • 2>/dev/null discards the standard error (stderr), which includes messages such as "captured xx packages.".
  • > filename simply writes the output to a file on the receiving computer.

I hope this helps someone!