The big GSM write-up – how to capture, analyze and crack GSM? – 4.

So. I had some requests asking me about how I did what I did with GSM. What tools did I use, what hardware and what options?
Since I believe strongly that GSM needs to be “out in the hands of the people” meaning everybody should have access to cheap hardware and free, opensource software that helps understanding GSM in practice I thought I will create a series of write-ups describing the whole process from the beginning.
Enjoy! :-)

I don’t take responsibility for how you use the konwledge you gained here.

Fourth step: Capture data with RTL-SDR, decode it with airprobe

As it could be read on (I modified the original text with some enhancements):

Receive a Live Channel

First of all we need to find the frequency of the channel we are going to decode. There are a lot of both online and offline tools to convert an ARFCN number to actual frequency. Here I am going to use an offline tool called arfcncalc:

./arfcncalc -d -a ARFCN

Naturally instead of ARFCN you need to specify the ARFCN number, the -d switch tells the program to give us the downlink frequency (-u would give us the uplink).

To decode a live channel using RTL-SDR type in terminal

./ -s 1e6 -f FREQUENCY

A new window will pop up, click in the middle of the GSM channel in the Wideband Spectrum window. Within a few seconds some GSM data should begin to show constantly in wireshark. Type ./ -h for information on more options. The -s flag is used here to set the sample rate to 1.0 MSPS, which seems to work much better than the default of 1.8 MSPS as it seems that there should be only one GSM peak in the wideband spectrum window.

GSM Decoding with Airprobe and Wireshark and RTL-SDR Software Defined Radio

If you have trouble getting data, but receive many errors like

sch.c:260 ERR: conv_decode 12

then you should calibrate your RTL-SDR stick using the kalibrate-rtl program, described here.

After you determined the offset of your RTL-SDR calculate average of the different offset values. You will get something like this for example: +24.7 kHz. This actually is 24700 Hz, the plus means that the RTL-SDR tunes itself generally around 24700 Hz ABOVE the frequency you set it on, so you need to SUBTRACT this frequency from the result you got with ARFCNcalc. If your average offset is negative then naturally you need to ADD the average offset to the result of ARFCNcalc instead of subtracting it.

Use the new frequency to fire up RTL-SDR again, and let it warm up for some minutes. You should see some improvement compared to the first, uncalibrated test.

Capturing a cfile with the RTL-SDR (Added: 13/06/13)

I wasn’t able to find a way to use airprobe to capture my own cfile. I did find a way to capture one using ./rtl_sdr and GNU Radio however.

First save a rtl_sdr .bin data file using where -s is the sample rate, -f is the GSM signal frequency and -g is the gain setting. (rtl_sdr is stored in ‘gnuradio-src/rtl-sdr/src’)

./rtl_sdr /tmp/rtl_sdr_capture.bin -s 1.0e6 -f 936.6e6 -g 44.5

Next, download this GNU Radio Companion (GRC) flow graph (scroll all the way down for the link), which will convert the rtl_sdr .bin file into a .cfile. Set the file source to the capture.bin file, and set the file output for a file called capture.cfile which should be located in the ‘airprobe/gsm-receiver/src/python’ folder. Also, make sure that ‘Repeat’ in the File Source block is set to ‘No’.

Now execute the GRC flow graph by clicking on the icon that looks like grey cogs. This will create the capture.cfile. The flow chart will not stop by itself when it’s done, so once the file has been written press the red X icon in GRC to stop the flow chart running.

After we have the cfile we can actually decode it just like as it was captured using a USRP, so you need to fire-up Wireshark listening on lo (localhost) and say:

./ capture.cfile 64 0B

It will probably work for you just fine, data will flow into Wireshark as expected. The 64 is the decimation rate of the RTL-SDR, 0b is the configuration is going to use: 0 means Timeslot 0 (beacon channel), b is the configuration the cell uses on the beacon channel (see the ‘Signaling Channel Mapping’ in this chapter of ‘Introduction to GSM’ to see what this means).

Here are all the available configurations that are supported by airprobe:

     0C : TimeSlot0  "Combined configuration", with SDCCH/4
          (FCCH + SCH + BCCH + CCCH + SDCCH/4)
     0B : TS0  "FCCH + SCH + BCCH + CCCH"
     1S : TS1  SDCCH/8
     2T : TS2  (Full Rate) Traffic
     1TE: TS1  Enhanced Full Rate Traffic

If you look at the traffic in Wireshark but it doesn’t seem to be right (for example you made a call or sent a text message while capturing but the Ciphering Mode Command is missing) it is pretty sure that you are using the wrong configuration (0b instead of 0c or vise versa). It is important to try both and figure out which one is correct for the cell you are observing.

I will assume you sent a text message to yourself while capturing data.

So now you can see all the messages of the beacon channel, but what are you looking for in the Wireshark log? It is quite simple: first a “Paging Request” for the TMSI of the target phone, then a “Ciphering Mode Command”. These are the messages which indicate that a transaction actually happened.

Now to continue with the flow it is best to try to decode the same cfile but now giving the key too to

./ capture.cfile 64 0C KEY

How to get the key? I already posted about that. Since we are testing using our own equipment we have access to the SIM card, so we can extract the key. It is best to extract the key immediately after you did a capture with RTL-SDR because depending on the network configuration the key could change.

What are we looking for now? Well, it depends on the network: either there is an “Immediate Assignment” telling the phone to move to different timeslot (so they are not using the busy beacon channel to do their business) or you will actually be able to see the text message (easy to recognize: its protocol in Wireshark is ‘GSM SMS’), it will look like this:

If instead of the SMS you find an “Immediate Assignment” message you need to open it and see which timeslot the phone is being commanded to and then you need to decode that timeslot using So, for example if it says that the phone needs to go to Timeslot 2 then your command would be:

./ capture.cfile 64 2S KEY

Notice that I did not only change the Timeslot number from 0 to 2, but also the configuration from C to S, because the target phone is now on a Standalone Dedicated Control Channel (SDCCH), not on the beacon channel so we need to decode it differently.

Also worth noting that SMS messages are almost always sent on the Control Channel not on the Traffic Channel.

Here is a flowchart of the whole process to make it easier to understand (naturally since we can only see the downlink this shows only what happens on the downlink):

gsm_sms_flowchartNow that we were able to decode an SMS let’s get to something a little bit harder: decoding a voice call!

Well the first step is the same as it was when we decoded a text message: we look at the beacon channel, Timeslot 0:

./ capture.cfile 64 0C

What do we expect to see? Nothing besides the “Cipher Mode Command” because we didn’t provide the key, so let’s do that:

./ capture.cfile 64 0C KEY

All right, what should we see now? Logically there needs to be an “Immediate Assignment” command, because the phone NEEDS to change at least once to a different timeslot to receive voice data (to a Traffic Channel, Timeslot 1-7).  What we saw when decoding the SMS is correct here too: depending on the network configuration we can see some messages about the call setup (if it is an incoming call we can even see the caller ID – the phone number calling our target) then an “Immediate Assignment” (configuration ‘C’ – combined) or we can only see an “Immediate Assignment” directing the phone to a Control Channel (just like it happened when receiving an SMS, configuration ‘B’).
Of course if you follow the phone to the Control Channel you will see the call setup messages (in case of an incoming call) then another “Immediate Assignment” command, this time directing the phone to a Traffic Channel.

Here is again a flow chart showing the process:


Now there is only one question left: how do we decode the traffic channel to actually get the voice data?
Again, it is something that depends on the network: if the network uses simply Full Rate Speech then you can do the same what has been written in Srlabs’s tutorial:

./ capture.cfile 64 1T KEY

What does this command do? It decodes Timeslot 1 as a Traffic Channel. We know what timeslot to decode from the “Immediate Assignment” command message, T means Full Rate Speech. The command results in a file called “”, which needs to be converted to .au file using ‘toast’:

toast -d

The resulting .au file could be played back using any player, e.g. cvlc (Command Line VLC):


If you can not hear anything but beeps and other weird noises then there is a pretty good chance that the cell is using Enhanced Full Rate Speech instead of simple Full Rate Speech. To decode the channel as an Enhanced Full Rate Speech Traffic Channel:

./ capture.cfile 64 1TE KEY

This results in a file called “speech.amr” which could be played back without any more modifications using for example Commandline VLC:

clvc speech.amr

If you have one hour to see everything in more detail, explained by a professional I would encourage you to watch this video:

UPDATE: I also uploaded my slides from Hacktivity.

This entry was posted in Ethical Hacking, Publikációk and tagged , , , , . Bookmark the permalink.

46 Responses to The big GSM write-up – how to capture, analyze and crack GSM? – 4.

  1. Pingback: Receiving, Decoding and Decrypting GSM Signals with the RTL-SDR -

  2. Testing on my girlfriend mobile phone now ;). Great write-up! Excellent work!

    • domi007 says:

      If she knows about and approved it then good luck. Otherwise expect law enforcement to show up pretty soon.

  3. cr0w says:

    Evaluating GSM hopping
    I think this should work in RLT-SDR

    • domi007 says:

      It could be possible, but the RTL-SDR’s bandwidth is quite limited, it’s around 3.5 MHz so I don’t think it is wide enough for this. But for sure this is a really cool research, respect to Bogdan!

      One other way of defeating hopping is that since RTL-SDRs are really cheap you can use more of them making it possible to listen on every single ARFCN the phone could be hopping on (however bringing the data together from all these files needs to be researched it shouldn’t be that hard as far as I can see now).

  4. gat3way says:

    “I wasn’t able to find a way to use airprobe to capture my own cfile. I did find a way to capture one using ./rtl_sdr and GNU Radio however.”

    This is easy to fix in, problem is that there is no output from the decoder gnuradio module that would go to the file sink. I can send you the fixed script if you wish.

    • domi007 says:

      I actually kind of figured that out already but I quoted word-by-word. It doesn’t really matter which tool is used to capture the data, it just needs to be captured and then fed into airprobe.
      Thank you!

  5. Gratulálok a munkádhoz, csak így tovább!

  6. njx says:

    Hey will you release your patched osmocom files ? or even write Step 5 capturing/decoding calls with osmocom software ?

    • domi007 says:

      I haven’t done any work on decoding calls with Osmocom, so don’t expect any releases.
      I just did some modifications based some other patches so I can monitor all pagings in a cell which makes it possible to link a TMSI to a phone number.
      This code I am going to release soon.

  7. njx says:

    maybe this looks interessting for you,
    seems like he scripted some easy tool for doing the work.

    • domi007 says:

      I saw that, but still it is not on my roadmap yet. Also I am not sure who is behind this video, and if it is fake or not, so I would not like to draw any conclusions based on it.

  8. adolful says:

    I am using usrp1 et rtlsdr to capture traffic gsm connect notebook number 1
    Number 2 notebook connected to motorola c115 and osmocom-bb project tools (osmocon,imobile,telnet).
    I know my TMSI-channel arfncalc and Kc and run calls and sms.
    I look at the captured traffic with Wireshark with command ./ capture_traffic.cfile 64 -0C et ./ capture_traffic.cfile 64 -0B
    because I can not find my TMSI in the captured traffic ?
    same problem to added my key Kc

    • adolful says:

      This test on the cell 1005 = 931.2 MHz

      • domi007 says:

        Do you see any traffic that looks valid?
        It might be that beacuse of the inaccuracies of RTL-SDR you simple didn’t get much data.
        Calibrating it and letting it warm up a little bit helps sometimes.

        I struggle also quite a lot with it :(.
        Also the command you run seems wrong: there should be no “-” in it.

  9. jdw says:

    What will be better ?
    some C139 motorla or SDR ?

  10. adolful says:

    no ……ok I was wrong to transcribe …
    Iam good signal channel arfn ……
    my test works like this:
    1° notebook – osmocom-bb look at my channel arfn et TMSI and Kc
    2° notebook connect usrp1 start capture on the channel bed arfn notebook 1
    5-10 minutes to capture traffic and try to call the phone motorola c115 connected osmocm-bb or sms sent (notebook 1) to generating traffic …………… ok?
    Stop capture and watch the traffic on wireshark
    I run ./ 112 0C
    I look if I see my TMSI
    . / / tmp / prova.cfile 112 0C + my Kc
    . / / tmp / prova.cfile 112 0B + my Kc
    . / / tmp / prova.cfile 112 1S + my Kc
    . / / tmp / prova.cfile 112 1T + my Kc

    Do not decode anything
    What I’m wrong?

    • domi007 says:

      I am not really sure, could you try using and see if you can receive any GSM data with your stick?

  11. adolful says:

    I have the same problem … I see the captured traffic with usrp is that rtlsdr
    I see other TMSI, but I do not find that I have to try TMSI,
    AirProbe it takes the additional patches?
    my test with the phone to copy TMSI:
    osmocom-bb + c115 + sim phone operator = telnet show = 1 ms = arfn example (1005) ……………………….. OK
    telnet show my subscriber = kc ……………………… OK
    1 sms number …..hello hello hello ….test message ..
    call number 1 et speak …….. bla bla bla bla ……….. OK
    The whole procedure was captured with usrp or rtlsdr on the copied channel example (1005)
    AirProbe/gsm_receiver/src/python/./ 112 0C + Kc for my usrp
    AirProbe/gsm_receiver/src/python/./ 64 0C + Kc for my rtlsdr
    I can not find my sms decoded on wireshark

    What’s wrong?

  12. adolful says:

    I see you captured traffic on wireshark to other other TMSI:
    captured with this example. / / tmp / prova.cfile 64 0C
    captured with this example. / / tmp / prova.cfile 64 0B

    • domi007 says:

      0C seems to be better to me because it has the periodicity that I usually look for , however it is still not looking 100% right to me.
      It is possible, that your carrier uses a different setup, maybe one that is not implemented in airprobe.
      If you look into the GSM for dummies PDF you can see that there are at least 4-5 different combinations of layouts for the beacon channel.

  13. Andrew says:

    Domi, any news so far about the stage of linking TMSI and phone number (part 3) via paging?
    It’s very interesting indeed.


  14. katrina says:

    First of all, thank you very much for your effort! You’ve done a great job exposing GSM insecurity and I hope I’ll buy you a beer some time!
    I’m a security enthusiast and I’m recently engaged in mobile security. This is my first day on GSM cracking and I’m currently trying to fit the pieces together.
    Regarding the KC key, you’re poiting us out at, which implies physical access to the terminal, but I quote, from their “Airprobe How-To” paper(
    “Choose a burst where the content of the frame is known and use it to find Kc. Use the Kraken tool to find Kc:“. So, you just need the air captured bursts and the kraken tool to find out KC. Kraken is fed up with rainbow tables, right? Sorry if I’m mistaking anything.
    Thank yiu and best regards!

    • domi007 says:

      Correct, but finding the correct bursts requires deep knowledge of the network’s setup and GSM, definitely something a beginner will have trouble with.
      However, again, you are correct to say that, I was able to crack a key using Kraken and the bursts I captured feom the air.

      • katrina says:

        Hello Domi!
        Thank you for your reply! I’ve sent you an encrypted e-mail. My key ID is 0xC3B0D621.
        Please don’t approve this comment.

  15. dsound says:

    I have Airprobe and Wireshark working in Kali. The part I can’t seem to figure out is Kraken. I downloaded from

    When I run ./ I get the following error:

    a5cpu_test.cpp: In function ‘int main(int, char**)’:
    a5cpu_test.cpp:44:16: error: ‘sleep’ was not declared in this scope
    Kraken.cpp: In function ‘int main(int, char**)’:
    Kraken.cpp:415:19: error: ‘usleep’ was not declared in this scope

    ServerCore.cpp: In constructor ‘ServerCore::ServerCore(int, dispatch)’:
    ServerCore.cpp:41:24: error: ‘close’ was not declared in this scope
    ServerCore.cpp:49:24: error: ‘close’ was not declared in this scope
    ServerCore.cpp: In destructor ‘ServerCore::~ServerCore()’:

    ServerCore.cpp:72:24: error: ‘close’ was not declared in this scope
    ServerCore.cpp: In member function ‘void ServerCore::Serve()’:
    ServerCore.cpp:132:31: error: ‘close’ was not declared in this scope
    ServerCore.cpp:149:46: error: ‘close’ was not declared in this scope

    ServerCore.cpp: In destructor ‘ClientConnection::~ClientConnection()’:
    ServerCore.cpp:218:14: error: ‘close’ was not declared in this scope
    ServerCore.cpp: In member function ‘int ClientConnection::Write(std::string)’:

    ServerCore.cpp:226:56: error: ‘write’ was not declared in this scope
    ServerCore.cpp: In member function ‘int ClientConnection::Read(std::string&)’:
    ServerCore.cpp:240:41: error: ‘read’ was not declared in this scope

    Also, how do you point Kraken to the Tables on an external HD?


    • domi007 says:

      Have you just downloaded the tables or you have already created the index files?

      About your build error: I’m not sure but shouldn’t Kraken be built using make?

    • xy says:

      Dsound: please post next time if you figure out a solution :)
      #include in all cases worked well for me.

      Domi: could you please copy the A51 tables to a drive (that I take to you) during my visit to Budapest? (~18.04.14)

      Thank you for publishing this description I am planning for long to try this out.

      • xy says:


      • domi007 says:

        Yes, that could be arranged, but please don’t forget that copying takes about 24 hours. Also it is very important that your HDD has 512 byte sectors, not 4096. You can check this with fdisk -l /dev/sdX

        • xy says:

          I have checked, it is 512 bytes. If it is not too much effort I want to ask you to do it. Please write an email, if you think that you have time for this at the weekend.

          Thank you!

  16. Sant says:

    Hi Domi, this is great stuff ! I was wondering if you were able to get Airprobe to work with half rate traffic channels (TCH/H) ?


    • domi007 says:


      To do that you can simply follow the srlabs tutorial and use toast as far as I know.

      • Sant says:

        Hi Domi,
        I’ve been trying to get speech out of an unencrypted non-hopping cfile without any success. I was able to get speech out of the srlabs tutorial cfile ( which is TCH/F) but all I get when I try to extract speech from my TCH/H cfile are conv_decode errors. I also see that airprobe has no input parameter for specifying which subslot to decode in a TCH/H timeslot. You need specify a subslot to differentiate between the two users sharing the timeslot. I can send you my cfile if you want to take a shot at it, but I’m pretty sure now that airprobe does not support half-rate traffic channels.


        • domi007 says:

          I am really sorry, I didn’t read your comment attentively enough. You are absolutely right (sadly), airprobe doesn’t support half-rate channels, only full rate and full rate enhanced.

  17. dsound says:

    I’m a rather new Linux user. How do I configure Kraken to work with the tables on a HD? Is there a config file to point to the tables?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>