Introduction️

GSM (Global System for Mobile Communications) (2G) is a communication standard developed for the transmission of voice and data in mobile networks. Originally created in Europe in the 80s by the European Telecommunications Standards Institute (ETSI), it became the most popular mobile phone system worldwide, used by most mobile network operators around the world. The GSM technology allows users from different operators to communicate with each other and use services like SMS (text messages) or calls. With the arrival of 4G and 5G, the use of GSM networks has decreased and some operators are gradually removing support for these networks.️

The radio frequency (RF) used in GSM is located in the ultra-high frequency (UHF) range, specifically between 850 MHz and 1900 MHz. Today the most commonly used is the GSM-900 band (880–960 MHz). It is possible to capture these emissions from base stations and decode them. Communications between base stations and mobile devices are usually encrypted so only public emissions will be decodable, such as those including network identification or a list of nearby base stations. We can decrypt our communications if we have the encryption key, which is stored in a file on the SIM card (Subscriber Identity Module).️

The software used will be GNURadio in its version 3.10 along with the library gr-gsm. This library is compatible up to version 3.8 of GNURadio, so it will be necessary to use an adaptation created by bkerler and patch certain files to achieve complete compatibility with the latest versions of GNURadio. As a system operating system we will use Kali Linux, although this article is valid for any Debian-based distribution.️

Like any software-defined radio (SDR) capable of receiving emissions in the 900 MHz band, such as the RTL-SDR.

Installation of gr-gsm and its dependencies️

We can install the package gr-gsm from the default package manager:

sudo apt install gr-gsm

In this option, functions related to file saving and loading bursts do not work correctly with GNURadio 3.10 and the library gr-gsm, so it is necessary to apply a patch by compiling and installing the program from source code. We install its dependencies.️

sudo apt install -y cmake autoconf libtool pkg-config build-essential python3-docutils libcppunit-dev swig doxygen liblog4cpp5-dev python3-scipy gnuradio-dev gr-osmosdr libosmocore-dev

We clone the repository and move to the project directory.️

git clone https://github.com/bkerler/gr-gsm/
cd gr-gsm

Now we move to the lib/misc_utils directory which contains the files to download and modify.️

cd lib/misc_utils

We modified the file burst_file_source_impl.cc by adding a header including the library to modify pmt_serialize.cc. We added #include "pmt_serialize.cc" below the line #include "stdio.h".️

vi burst_file_source_impl.cc

We download the files pmt_serialize.cc and pmt_int.h from the GNURadio repository. This library is responsible for encoding data from bursts to save them in a file through serialization, and loading them through deserialization.️

wget https://github.com/gnuradio/gnuradio/raw/refs/heads/maint-3.10/gnuradio-runtime/lib/pmt/pmt_serialize.cc
wget https://github.com/gnuradio/gnuradio/raw/refs/heads/maint-3.10/gnuradio-runtime/lib/pmt/pmt_int.h

Then modify the file pmt_serialize.cc with two changes.️

vi pmt_serialize.cc

Replace the code for the function deserialize_untagged_u32 on line 183 with the following code (the previous code is commented out).️

/*
uint8_t buf[sizeof(uint32_t)];
std::streambuf::traits_type::int_type t;
t = sb.sgetn((char*)buf, sizeof(buf));
sb.pubseekoff(sizeof(uint32_t), std::ios_base::cur);
*ip = big_to_native_u32(buf);

return t != std::streambuf::traits_type::eof();
*/

std::streambuf::traits_type::int_type t;
int i;

t = sb.sbumpc();
i = t & 0xff;

t = sb.sbumpc();
i = (i << 8) | (t & 0xff);
t = sb.sbumpc();
i = (i << 8) | (t & 0xff);
t = sb.sbumpc();
i = (i << 8) | (t & 0xff);

*ip = i;
return t != std::streambuf::traits_type::eof();

Secondly, we replace the code within the switch (utag) and the case UVI_U8 on line 681 with the following code (the previous code is commented).

/*
deserialize_untagged_u8_vector(u8v, nitems, sb);
pmt_t vec = init_u8vector(nitems, &u8v[0]);
return vec;
*/

pmt_t vec = make_u8vector(nitems, 0);
for (uint32_t i = 0; i < nitems; i++) {
	deserialize_untagged_u8(&u8, sb);
	u8vector_set(vec, i, u8);
}
return vec;

After that, we can move to the project root directory, compile the project and install it.️

cd ../..
mkdir build
cd build
cmake ..
mkdir $HOME/.grc_gnuradio/ $HOME/.gnuradio/
make -j16
sudo make install
sudo ldconfig

Scanning of the GSM-900 frequency range️

With the program installed, we can start scanning for GSM base stations with the software-defined radio. In the case of using some RTL-SDR with low-quality TCXO oscillators, we will need to find the PPM value since in these cases the tuned frequency deviates from the true one by a certain amount. The reception of GSM signals requires synchronizing to the exact frequency. To find this value, we will use the kalibrate tool, which we will install.️

sudo apt install kalibrate-rtl -y

We scanned the GSM-900 band with the option -s and found several base stations.️

kal -s GSM900
Found 1 device(s):
  0:  Generic RTL2832U OEM

Using device 0: Generic RTL2832U OEM
Detached kernel driver
Found Rafael Micro R820T tuner
Exact sample rate is: 270833.002142 Hz
[R82XX] PLL not locked!
kal: Scanning for GSM-900 base stations.
GSM-900:
    chan:  111 (957.2MHz + 3.007kHz)    power:   24399.37
    chan:  113 (957.6MHz + 2.684kHz)    power:   30071.01

We must note the channel with more power, in this case the 113. Now we scan only this channel with the option -c.️

kal -c 113   
Found 1 device(s):
  0:  Generic RTL2832U OEM

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Exact sample rate is: 270833.002142 Hz
[R82XX] PLL not locked!
kal: Calculating clock frequency offset.
Using GSM-900 channel 113 (957.6MHz)
Tuned to 957.600000MHz (reported tuner error: 0Hz)
average         [min, max]      (range, stddev)
+ 2.648kHz              [2600, 2699]    (99, 427.253452)
overruns: 0
not found: 11
average absolute error: 42.765 ppm

We found a value of PPM of 42.765, which we rounded to 43. Now we can scan all base stations using the tool gsgsm_scanner with options -b to specify the band, the PPM value with -p, the maximum receiver gain with -g and the fastest scanning speed --speed 29.️

grgsm_scanner -b GSM900 -p 43 -g 30 --speed 29
...
Scanning: 0.00% done..
Reattached kernel driver
...
ARFCN:  975, Freq:  925.2M, CID:   XXXX, LAC: XXXXX, MCC: 214, MNC:   3, Pwr: -43
ARFCN:  977, Freq:  925.6M, CID:   XXXX, LAC: XXXXX, MCC: 214, MNC:   3, Pwr: -34
ARFCN:  978, Freq:  925.8M, CID:   XXXX, LAC: XXXXX, MCC: 214, MNC:   3, Pwr: -27
ARFCN:  992, Freq:  928.6M, CID:   XXXX, LAC: XXXXX, MCC: 214, MNC:   3, Pwr: -43
ARFCN:  984, Freq:  927.0M, CID:   XXXX, LAC: XXXXX, MCC: 214, MNC:   3, Pwr: -43
...

Between the cells found, we can take the value of the cell with more power, in this case the one for number of channel (ARFCN) 978 and frequency 925.8MHz.️

Channel monitoring C0️

With the tool grgsm_livemon and grgsm_livemon_headless, we can monitor channel C0 of the GSM base station. With the first tool, we have access to a graphical interface where we can change the frequency, and with the second tool, no graphical interface is created. We use the frequency values -f, gain -g and PPM value -p.️

grgsm_livemon -f 925.8M -g 30 -p 43

The messages will be printed if they are decoded. We can decode them using Wireshark, monitoring UDP packets with the filter gsmtap on the interface lo by specifying -f and -Y options.

wireshark -k -f udp -Y gsmtap -i lo

We found messages, such as the System Information that are sent through the BCCH (Broadcast Control Channel) channel, which broadcasts general information of the cell, like the cell identifier and network, and the list of nearby frequencies. Or by CCCH, like the Paging Request Type 1, that notifies the mobile device when there is an incoming call or SMS to respond in the access channel.️

Recording of the baseband of a cell in a file

With the tool grgsm_capture we can save the baseband signal for later analysis. We will specify the frequency -f, gain -g, sampling rate -s, in this case 250k since we are only capturing one cell, PPM value -p, and finally the file name.️

grgsm_capture -f 925.8M -g 30 -s 250k -p 30 -T 5 9258_recording

Recorded baseband of several cells in a file

Also it is possible to capture with the tool grgsm_capture a wider area of the spectrum, with a sampling rate -s 2.0M to capture several cells that are nearby. Then you can use the tool grgsm_channelize to divide the file into each individual cell. We will specify with the parameter -i the file with the capture and with the parameter -f the central frequency, in this case 925.6MHz, together with the output sampling rate -o. Finally we will specify the channel numbers (ARFCNs) of the desired cells, in this case the one at the frequency 925.2MHz (975), 925.6MHz (977) and 925.8MHz (978).️

grgsm_capture -f 925.8M -g 30 -s 2.0M -p 30 9258_recording.bin
grgsm_channelize -s 2.0M -f 925.8M -o 250k -i 9258_recording.bin 975 977 978

We obtain the files out_975.cfile, outfile_977.cfile and outfile_978.cfile in the 9258_recording folder.

ls -1 9258_recording
out_975.cfile
out_977.cfile
out_978.cfile

Decoding of the captures

With the tool grgsm_decode, we can decode and decrypt baseband captures and bursts. The bursts files are another type of capture that only captures demodulated bursts with undecoded data from the base station, not the entire baseband. In this case, we will specify the channel with -m. We can decode the control channels BCCH (signaling), BCCH_SDCCH4, or SDCCH8, or the traffic channels TCHF or TCHH.️

Also, we will specify the time interval with -t (from 0 to 7, since GSM uses TDMA, which allows multiple users to share the same frequency channel by dividing the transmission time into intervals). We will specify the file with the capture with -c along with its ARFCN with -a and its sampling rate -s. The packets can be observed with Wireshark as previously.

grgsm_decode -m BCCH_SDCCH4 -t 0 -c 9258_recording/out_975.cfile -a 975 -s 250k
grgsm_decode -m SDCCH8 -t 0 -c 9258_recording/out_975.cfile -a 975 -s 250k

We found packages without identification, as they are encrypted and destined for a specific mobile device. In the case that calls are not encrypted we can search all intervals on channel TCHF or TCHH to save the call in an audio file with GSM codec using option -o.️

grgsm_decode -m TCHF -t {0..7} -c 9258_recording/out_975.cfile -a 975 -s 250k -o output.gsm
grgsm_decode -m TCHH -t {0..7} -c 9258_recording/out_975.cfile -a 975 -s 250k -o output.gsm

GSM messages reference

The packages such as System Information, Paging Request, and Location Update are fundamental to the operation of the GSM network, allowing for communication of control information and signaling between the network and mobile devices.️

  • System Information: packages sent by the base station to all mobile devices in its coverage area. These messages contain essential information about the network and the cell in which the device is registered.️
  • Paging Request: used by the GSM network to notify a mobile device that it has an incoming call, a text message (SMS), or some other pending communication.️
  • Location Update: this is used to notify the network when a mobile device changes location area (LA) or registers for the first time on the GSM network. This allows the network to always know the approximate location of the device.️
  • Channel Request: when a mobile device requests access to the network, for example, to initiate a call or send an SMS message.️
  • Immediate Assignment: this message is in response to a channel request and assigns a specific control channel to the mobile device for continued communication. This ensures that the device can start transmitting data or voice on a dedicated channel.️
  • Authentication Request: this is used to verify the identity of the mobile device before it can access the GSM network. When a device attempts to register on the network, the network sends this message, and the device must respond with an answer based on its authentication key.️
  • Ciphering Mode Command: establish a cipher in the communication between the device and the base station, protecting the privacy of the data being transmitted.️
  • Assignment Command: it is sent over the network to indicate that the mobile device should switch to a traffic channel (TCH) when setting up a voice call or data connection.️
  • Handover Command: this is used when the network decides to change the mobile device’s connection to a new cell during an active call or data session. This command tells the device to switch to the new frequency and channel in order to maintain signal quality as it moves.️

Conclusion️

The tools contained in gr-gsm are useful for analysis, research, and even to improve knowledge about the structure of GSM networks.️