Decrypting GSM SMS traffic

Posted on Feb 14, 2021

In this post, I’ll go over how to decrypt your own 2G GSM SMS messages by pulling encryption keys off your SIM card and processing the data with gr-gsm.

In a previous post, I looked at how to decode and start analyzing GSM traffic. If you haven’t read that yet, I suggest you start there. I’m going to assume you have your environment set up to that point.

GSM encryption

Before you take your capture, it’s helpful to know a bit about how GSM encryption works. There are two important keys to be aware of:

  • Ki (Subscriber key) - Essentially a “master key” that’s stored in your SIM card and never leaves. The key is set during SIM production and doesn’t change.
  • Kc (Cipher key) - The key used to encrypt traffic over the air. Kc is a derivative of the Ki and rotated at regular intervals.

Before a call or text, the mobile network sends an Authentication Request message to the phone. Inside this message is a 16-byte random value (RAND). RAND is sent to the SIM card and combined with Ki to make Kc. The SIM then exposes Kc to the modem so the session can be encrypted.

It’s important to remember that the Kc will change before each call or text. So if we want to decrypt our traffic, we need to get the key after a particular session has occurred.

Getting the Kc

You essentially have two ways to get the Kc off the SIM. Either by interfacing with the modem or by talking to the SIM directly with a card reader. Both methods work, but I find using a card reader less complicated.

The process for getting access to the modem is highly dependent on what type of phone you have. You have to find the modem’s serial interface and send it raw AT commands. Sometimes the serial interface is exposed over USB, or if you have root access, you might be able to find it in the /dev/ directory. If you do get access to the modem, I have had luck with the following AT command: AT+CRSM=176,20256,0,0,9.

If you use a card reader, tools like Cardpeek or SIMspy II can help you read the Kc from the SIM.

HID OMNIKEY 6121 and some adapters

Using Cardpeek is reasonably straightforward. After you perform your capture insert the SIM card into the reader, plug the reader into the computer, and select Analyzer > GSM SIM.

The last byte (03 in the screenshot) is a sequence number and is not part of the key.

Channel assignment procedure

As discussed in the previous post, the first step to decoding traffic is to figure out what channel the communication takes place on. The phone and base station (BTS) make this decision over the BCCH channel.

This is what happens when you receive something:

  1. The BTS sends a Paging Request to the phone
  2. The phone sends a Channel Request to the BTS
  3. The BTS sends an Immediate Assignment to the phone
  4. Communication continues on a dedicated channel

(You skip the first step when sending)

For this test, we’re only capturing downlink traffic from the BTS. Because of this, we only see one side of the assignment procedure, and it’s not possible to determine which Immediate Assignment messages are our own. However, if you keep your capture time short, it’s easy enough to figure out. There usually aren’t too many different channel configurations sent out within a limited time window.

Use this display filter to show relevant Immediate Assignment messages: gsm_a.rr.dedicated_mode_or_tbf == 0

Under Channel Description make a note of:

  • Timeslot
  • Hopping Channel
  • MAIO
  • HSN


I’ll assume you’ve already read the de-hopping section in the previous post. However, a key difference here is that we’ll export the raw bursts to a file after de-hopping them in GRC. Exporting the bursts allows us to keep things simple and use the grgsm_decode utility for decryption.

De-hopping traffic and exporting the bursts

You’ll need to configure the blocks to match the data found in the Immediate Assignment packet, as well as a few other parameters discussed in the last post. You can download my GRC bursts example here.

After executing the flow graph, you should have a burst file to use with grgsm_decode:

grgsm_decode -b /tmp/bursts -t 1 -m SDCCH8

If you see a Ciphering Mode Command message you’ve successfully de-hopped the traffic.


At this point, decrypting traffic is easy. All you need to do is add the -e flag with the mode from the Cipher Mode Command message, and the -k flag with the Kc key from the SIM.

grgsm_decode -b /tmp/bursts -t 1 -m SDCCH8 -e 3 -k AB8CE2B5B7F7477B

Decrypted SMS