Open-source project
fgsect/scat avatar
fgsect/scat

SCAT reads a baseband diagnostic port and emits a GSMTAP stream

SCAT: Signaling Collection and Analysis Tool

544 stars136 forksPythonGPL-2.0

At a glance

What is it?
SCAT is a Python tool that talks to Qualcomm, Samsung and HiSilicon basebands over USB or serial, and turns the diagnostic messages into a GSMTAP packet stream that Wireshark can dissect, with the 5G messages depending on a Lua plugin that is not yet upstream.
Who is it for?
SCAT fits a reverse engineer or network researcher who needs the control plane of a handset or a cellular module on the wire, and who can supply a device whose diagnostic port is reachable.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

It parses diagnostics and emits GSMTAP

SCAT stands for Signaling Collection and Analysis Tool, and the mechanism is narrow and specific. It parses diagnostic messages from Qualcomm and Samsung basebands through USB and generates a stream of GSMTAP packets containing cellular control plane messages.

The point of the tool is to move data out of a device that has no convenient way to expose it. A handset's baseband knows what the network is saying, and the diagnostic port is a window into that conversation. SCAT opens that window, and translates what comes out into a format that a general purpose protocol analyser understands, so the control plane traffic can be read next to everything else on the network.

The output is sent to 127.0.0.1 by default, with control plane packets going to UDP port 4729 as GSMTAP and user plane packets to UDP port 47290 as IP. That default is convenient, since the capture lands on a local port that Wireshark can open.

Three baseband families, one of them experimental

The baseband type is selected with the -t option, and the documented values are qc for Qualcomm, sec for Samsung and hisi for HiSilicon, which is marked experimental and supports only the baseband dump path.

The Samsung handling shows how the tool has moved on. Versions up to 1.1.0 required the Samsung baseband type to be specified by hand with the -m option, because the tool could not identify it. From 1.2.0 the baseband type is autodetected, and -m is only needed when analysing a raw SDM file without a start response.

That history is worth knowing because it tells you the tool is version sensitive in a way that the option list does not. A capture workflow written against an old version may need a different invocation today, and the one case where -m still matters is a raw file rather than a live session, which is exactly the case where you have no start response to infer the type from.

The application exits on Ctrl+C, and the advanced options are documented on the project wiki rather than in the README, which is where to look once the basic invocations work.

USB access means naming the address and the interface

For a smartphone the diagnostic port is reached over USB directly, and the invocation names both the device and the interface:

bash
$ scat -t qc -u -a 001:010 -i 2
$ scat -t sec -u -a 001:010 -i 2

The -a value is the USB address in the same syntax the lsusb command shows, and -i is the interface number of the diagnostics node, which is device specific. There is a heuristic that tries to determine the connected device, but the README recommends stating both explicitly, which is the safer habit when a capture has to be reproducible.

One more requirement is specific to Samsung. Those devices need a correct magic number supplied to start the diagnostic session over USB, and the details are in a linked issue comment rather than in the README.

The kernel modules qcserial and option do not carry the diagnostic port information for all Qualcomm based phones and modules, and no equivalent module exists for Samsung based phones. That is why SCAT talks to the USB device itself for smartphones, and uses serial mode for discrete cellular modules, which is the same reason the two access paths are separate commands rather than one autodetecting mode.

Serial for modules, dump mode for files

Discrete cellular modules are read over a serial port, where the device path is given directly:

bash
$ scat -t qc -s /dev/ttyUSB0

The path is the only thing to change, since it has to match your actual diagnostic device.

The third mode parses a dump file that was collected earlier, and the file extension follows the vendor:

bash
$ scat -t qc -d test.qmdl
$ scat -t sec -d test.sdm
$ scat -t hisi -d test.lpd

This matters because collecting the dump does not always require the port to be open. The README notes that if a phone does not expose the diagnostic port over USB, some smartphones have baseband dump features you can use instead, and the project wiki covers the details. The dump path also sidesteps the live-session requirements, including the Samsung magic number, since there is no session to start.

The tested device list and the device specific quirks live on the project wiki, and the README is clear that exposing the diagnostic port is largely device dependent with no generic solution, pointing to community resources for instructions.

5G messages need a Wireshark plugin that is not upstream

Decoding what SCAT produces depends on the Wireshark version and on the GSMTAP format. GSMTAPv2 packets from SCAT decode properly in Wireshark 2.6.0 or above. GSMTAPv3 packets, which cover 2G through 5G, need Wireshark 3.0.0 or above plus the Wireshark Lua plugin, and the recommended version is 4.2.5 or above. The plugin lives in the repository under wireshark/scat.lua and has to be installed into the Wireshark plugin path, following the instructions in the Wireshark manual. The plugin is required to dissect LTE MAC and PDCP packets from SCAT 1.3.0 and later.

The 5G messages are the sharper edge. NR RRC and NAS-5GS messages are only available through GSMTAPv3, and GSMTAPv3 support is not yet merged into mainline Wireshark, which is why the plugin is not optional for that traffic.

The format also drifted once. PCAPs generated by SCAT 1.4.0 and above use a slightly different GSMTAPv3 definition, so a capture made with an older release has to be regenerated if you still have the QMDL or SDM file, or converted with convert_prerelease_gsmtapv3.py using the -1 option when you do not. Files from before 1.3.0 need the same script to reach the final GSMTAPv3 layout.

Installation needs pip, udev rules and a stopped ModemManager

SCAT has to be installed explicitly, because running the main script from a git checkout will not work. The install comes in two variants, and the difference is the CRC calculation:

bash
$ pip install "signalcat[fastcrc]"

or, if you would rather not or cannot build libscrc:

bash
$ pip install signalcat

The fastcrc extra pulls libscrc, and the README notes it gives fast CRC calculation for Qualcomm and HiSilicon. For development work on a checkout, the project asks for pip install -e .[fastcrc] or pip install -e .

Two Linux specifics follow. You need the udev rules from the referenced android-udev-rules repository installed if SCAT cannot open the USB device as a normal user, and if you cannot open a serial device even as root you should stop ModemManager, which competes for those devices.

The Python side is modest: Python 3.10 is the minimum, and the dependencies are pyusb, pyserial, bitstring, packaging and zstandard for Python versions below 3.14. The distribution name on PyPI is signalcat, while the command it installs is scat.

The failures the project documents instead of hiding

The Known Bugs section is short and specific, which is the mark of a tool that has been used against real hardware.

On some Qualcomm devices, exiting and relaunching the application more than once eventually leaves initialization hanging with no messages appearing. The root cause is still under investigation and the documented workaround is to reboot the smartphone, which tells you the failure is in the device's diagnostic stack rather than in the parser.

On other Qualcomm devices you will see Secure log messages, which means the baseband is encrypting the diagnostic log packet. SCAT cannot decrypt it without a proper RSA key, obtaining that key is out of scope, and the README asks that issues about it not be filed.

There is a third limit that is a scope decision rather than a bug. Issues relating to exposing the diagnostic port over USB are out of scope, and there is no companion app for rooted Android devices, with no plan to add one. Since exposing that port is the hardest part of the whole workflow, the project is explicitly not going to solve the part you are most likely to hit.

Packaging, licence and release pace

The package is built with hatchling and hatch-vcs, and the version comes from the version control system rather than being written into the metadata, which is why the version tracked in the project metadata is 2.1.2. The console entry point is scat, mapped to the main function, and the wheel packages the src/scat directory. The URLs are generated by a metadata hook, so the homepage, issue tracker and source archive links follow the commit hash.

The licence is GPL-2.0-or-later, and the COPYING file sits at the root of the repository. For a tool that talks to devices over USB, a copyleft licence is a reasonable choice and it does mean that if you distribute a modified version you have obligations.

The release history shows v2.1.2 on 2026-10-15, v2.1.1 on 2026-09-11 and v2.0.0 on 2025-12-03, and the last push was on 2026-10-15. The project is not archived. The support channel is a Matrix room, with a Telegram bridge kept only for convenience, and the README notes that the magic number related discussion is not to be held in public.

Editorial conclusion

SCAT fits a reverse engineer or network researcher who needs the control plane of a handset or a cellular module on the wire, and who can supply a device whose diagnostic port is reachable. It is the wrong tool if your device encrypts its diagnostic log, since the baseband's RSA key is out of scope for the project, and if you need something that works across every handset, because exposing the diagnostic port is device specific and the project's own scope statement puts it outside. Before you install it, check three things: that your Python is 3.10 or newer, that the baseband vendor is one of qc, sec or hisi, that the SCAT version you use matches the GSMTAP header of the captures you already have, since pre-1.3.0 and 1.4.0-era files need converting with convert_prerelease_gsmtapv3.py. The licence is GPL-2.0-or-later, the package version is 2.1.2, and the last push was on 2026-10-15.

Frequently asked questions

What does SCAT do with a phone's baseband?

SCAT parses diagnostic messages from Qualcomm and Samsung basebands through USB and generates a stream of GSMTAP packets carrying cellular control plane messages. Control plane packets go to UDP port 4729 on 127.0.0.1 by default, user plane packets to UDP port 47290 as IP.

How do I install SCAT?

Install it with `pip install "signalcat[fastcrc]"` for fast CRC calculation via libscrc, or `pip install signalcat` if you would rather not build libscrc. Python 3.10 or newer is required, and running the script from a git checkout does not work without installing it.

Which Wireshark version is needed to decode SCAT output?

GSMTAPv2 packets decode in Wireshark 2.6.0 or above. GSMTAPv3 packets need Wireshark 3.0.0 or above with the SCAT Lua plugin installed in the plugin path, and 4.2.5 or above is recommended. The plugin is required to dissect LTE MAC and PDCP packets from SCAT 1.3.0 and later.

Can SCAT read a device that does not expose the diagnostic port over USB?

Yes, some smartphones have baseband dump features that can be used instead, and the dump files are parsed with the -d option, for example `scat -t qc -d test.qmdl` for Qualcomm, `scat -t sec -d test.sdm` for Samsung and `scat -t hisi -d test.lpd` for HiSilicon.

What happens when the baseband encrypts the diagnostic log?

SCAT cannot decrypt it without a proper RSA key, and obtaining that key is out of scope for the project. The device will show Secure log messages, and the README asks that issues about this case are not reported.

Official sources

  1. fgsect/scat on GitHub
  2. Issues
  3. License: GPL-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/fgsect-scat.svg)](https://hysenlabs.com/projects/fgsect-scat)

Was this useful?