|
|
# How to encode and decode mobile NAS messages
|
|
|
TODO |
|
|
|
|
|
## modules for handling NAS messages
|
|
|
All the NAS-related messages are available in the
|
|
|
[pycrate_mobile](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/) directory.
|
|
|
|
|
|
The following modules provide structures for dealing with 2G and 3G NAS messages:
|
|
|
- [TS24008_MM](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24008_MM.py):
|
|
|
contains all structures for Mobility Management messages
|
|
|
- [TS24008_CC](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24008_CC.py):
|
|
|
for Call Control
|
|
|
- [TS24008_GMM](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24008_GMM.py):
|
|
|
for GPRS Mobility Management
|
|
|
- [TS24008_SM](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24008_SM.py):
|
|
|
for GPRS Session Management
|
|
|
|
|
|
All those structures are corresponding mostly to the descriptions from section 9
|
|
|
of the 3GPP TS 24.008 specification. They are themselves using IEs (Information
|
|
|
Elements) defined in section 10 of the specification, and available in the module
|
|
|
[TS24008_IE](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24008_IE.py), with
|
|
|
the exception of IEs for GPRS using CSN.1, which are defined in the
|
|
|
[pycrate_csn1dir](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/)
|
|
|
directory.
|
|
|
|
|
|
For SMS and Supplementary Services, other modules are available:
|
|
|
- [TS24011_PPSMS](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/):
|
|
|
for Point-to-Point Short Message Service, which itself calls
|
|
|
- [TS23040_SMS](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/):
|
|
|
for SMS itself
|
|
|
- [TS24080_SS](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/):
|
|
|
for Supplementary Service, which wraps some ASN.1-defined objects from the
|
|
|
[pycrate_asn1dir/SS.py](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_asn1dir/)
|
|
|
module.
|
|
|
|
|
|
For LTE NAS, two main modules are available:
|
|
|
- [TS24301_EMM](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24301_EMM.py):
|
|
|
for EPS Mobility Management
|
|
|
- [TS24301_ESM](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24301_ESM.py):
|
|
|
for EPS Session Management
|
|
|
Those structures are corresponding to the descriptions from section 8 of the 3GPP
|
|
|
TS 24.301 specification. IEs defined in section 9 are available in the module
|
|
|
[TS24301_IE](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24301_IE.py).
|
|
|
Moreover, in case the [CryptoMobile](https://github.com/mitshell/CryptoMobile)
|
|
|
library is installed and can be imported, the EMMSecProtNASMessage and EMMServiceRequest classes
|
|
|
have methods dedicated to the LTE NAS cryptographic operations.
|
|
|
|
|
|
All classes representing NAS messages and information elements are deriving from few
|
|
|
base classes defined in the
|
|
|
[TS24007](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/TS24007.py)
|
|
|
module, which implements some specific aspects of cellular layer 3 message structures
|
|
|
as defined in the TS 24.007 3GPP specification.
|
|
|
|
|
|
Finally, two _top-level_ modules are enabling the import of most of those NAS messages'
|
|
|
structures and providing custom functions for decoding any cellular NAS messages:
|
|
|
- [NASLTE](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/NASLTE.py):
|
|
|
for LTE-only EMM and ESM NAS messages,
|
|
|
- [NAS](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/NAS.py):
|
|
|
for all 2G-3G and LTE NAS messages.
|
|
|
|
|
|
## What is missing
|
|
|
Currently (december 2017), the 2G RRM module (in TS44018_RR.py) is almost empty. Some
|
|
|
work is needed to implement all 2G RRM messages and extend the support of the CSN.1 translater
|
|
|
for supporting specific padding patterns (used e.g. in 2G system information messages).
|
|
|
|
|
|
Some more esoteric (understand much less used) mostly 2G-oriented protocols are not
|
|
|
implemented (i.e. Group and Broadcast Call Control, GTTP and LCS).
|
|
|
|
|
|
## Decoding NAS messages
|
|
|
In order to decode NAS messages, the simplest way is to used one of the two functions
|
|
|
used in the [NAS](https://github.com/ANSSI-FR/pycrate/blob/master/pycrate_mobile/NAS.py) module:
|
|
|
- parse_NAS_MO(buf) -> (element, err), for parsing Mobile Originating message (i.e. uplink)
|
|
|
- parse_NAS_MT(buf) -> (element, err), for parsing Mobile Terminating message (i.e. downlink)
|
|
|
|
|
|
In case there is an error during the decoding of the buffer, this will be returned in
|
|
|
the `err` code, with a code corresponding to standard 3GPP NAS error code (e.g. which can be
|
|
|
used in a Status NAS message in return).
|
|
|
The `element` contains an Element's instance (or None, if the whole decoding failed), with
|
|
|
the while message header and information elements.
|
|
|
|
|
|
Let's see some examples from the test directory:
|
|
|
|
|
|
>>> from pycrate_mobile.NAS import *
|
|
|
>>> Msg, err = parse_NAS_MO(unhexlify('05080200f11040005705f44c6a94c033035758a6'))
|
|
|
>>> err
|
|
|
0
|
|
|
>>> show(Msg)
|
|
|
### MMLocationUpdatingRequest ###
|
|
|
<SkipInd : 0>
|
|
|
<ProtDisc : 5 (MM)>
|
|
|
<Seqn : 0>
|
|
|
<Type : 8 (Registration - LOCATION UPDATING REQUEST)>
|
|
|
<CKSN : 0>
|
|
|
### LocUpdateType ###
|
|
|
<FollowOnReq : 0>
|
|
|
<spare : 0>
|
|
|
<Type : 2 (IMSI attach)>
|
|
|
### LAI ###
|
|
|
<PLMN : 00101>
|
|
|
<LAC : 0x4000>
|
|
|
### MSCm1 ###
|
|
|
<spare : 0>
|
|
|
<RevLevel : 2 (MS supporting R99 or later)>
|
|
|
<EarlyCmCap : 1>
|
|
|
<NoA51 : 0>
|
|
|
<RFClass : 7>
|
|
|
### ID ###
|
|
|
<L : 5>
|
|
|
### ID ###
|
|
|
<Digit1 : 0xf>
|
|
|
<Odd : 0>
|
|
|
<Type : 4 (TMSI)>
|
|
|
<TMSI : 0x4c6a94c0>
|
|
|
### MSCm2 ###
|
|
|
<T : 51>
|
|
|
<L : 3>
|
|
|
### MSCm2 ###
|
|
|
<spare : 0>
|
|
|
<RevLevel : 2 (MS supporting R99 or later)>
|
|
|
<EarlyCmCap : 1>
|
|
|
<NoA51 : 0>
|
|
|
<RFClass : 7>
|
|
|
<spare : 0>
|
|
|
<PSCap : 1>
|
|
|
<SSScreeningCap : 1 (capability of handling of ellipsis notation and phase 2 error handling)>
|
|
|
<MTSMSCap : 1>
|
|
|
<VBSNotifCap : 0>
|
|
|
<VGCSNotifCap : 0>
|
|
|
<FCFreqCap : 0>
|
|
|
<MSCm3Cap : 1>
|
|
|
<spare : 0>
|
|
|
<LCSVACap : 1>
|
|
|
<UCS2 : 0>
|
|
|
<SoLSACap : 0>
|
|
|
<CMServPrompt : 1>
|
|
|
<A53 : 1>
|
|
|
<A52 : 0>
|
|
|
>>> Msg['LAI'].get_val()
|
|
|
['\x00\xf1\x10', 16384]
|
|
|
>>> Msg['LAI'].decode() # some IEs have a specific .decode() method, like the LAI / PLMN, or the ID here
|
|
|
('00101', 16384)
|
|
|
>>> Msg['ID'][1]
|
|
|
<ID [TMSI] : 0x4c6a94c0>
|
|
|
>>> Msg['ID'][1].get_val()
|
|
|
[15, 0, 4, 1282053312]
|
|
|
>>> Msg['ID'][1].decode()
|
|
|
(4, 1282053312)
|
|
|
>>>
|
|
|
>>> Msg, err = parse_NAS_MO(unhexlify('034504066004020005815e068160000000001502010040080402600400021f00'))
|
|
|
>>> err
|
|
|
0
|
|
|
>>> show(Msg)
|
|
|
### CCSetupMO ###
|
|
|
<TIFlag : 0 (initiator)>
|
|
|
<TIO : 0>
|
|
|
<ProtDisc : 3 (CC)>
|
|
|
<Seqn : 1>
|
|
|
<Type : 5 (Call establishment - SETUP)>
|
|
|
### BearerCap1 ###
|
|
|
<T : 4>
|
|
|
<L : 6>
|
|
|
### BearerCap ###
|
|
|
<Ext : 0>
|
|
|
<RadioChanReq : 3 (dual rate support MS/full rate preferred)>
|
|
|
<CodingStd : 0 (GSM standardized coding)>
|
|
|
<TransferMode : 0 (circuit)>
|
|
|
<InfoTransferCap : 0 (speech)>
|
|
|
### Ext3a ###
|
|
|
<Ext : 0>
|
|
|
<Coding : 0 (octet used for extension of information transfer capability)>
|
|
|
<CTM : 0 (CTM text telephony is not supported)>
|
|
|
<spare : 0>
|
|
|
<SpeechVersionInd : 4 (GSM FR v3 (FR AMR))>
|
|
|
### Ext3b ###
|
|
|
### _BearerCapExt3bRec ###
|
|
|
<Ext : 0>
|
|
|
<Coding : 0 (octet used for extension of information transfer capability)>
|
|
|
<spare : 0>
|
|
|
<SpeechVersionInd : 2 (GSM FR v2 (GSM EFR))>
|
|
|
### _BearerCapExt3bRec ###
|
|
|
<Ext : 0>
|
|
|
<Coding : 0 (octet used for extension of information transfer capability)>
|
|
|
<spare : 0>
|
|
|
<SpeechVersionInd : 0 (GSM FR v1 (GSM FR))>
|
|
|
### _BearerCapExt3bRec ###
|
|
|
<Ext : 0>
|
|
|
<Coding : 0 (octet used for extension of information transfer capability)>
|
|
|
<spare : 0>
|
|
|
<SpeechVersionInd : 5 (GSM HR v3 (HR AMR))>
|
|
|
### _BearerCapExt3bRec ###
|
|
|
<Ext : 1>
|
|
|
<Coding : 0 (octet used for extension of information transfer capability)>
|
|
|
<spare : 0>
|
|
|
<SpeechVersionInd : 1 (GSM HR v1 (GSM HR))>
|
|
|
### CalledPartyBCDNumber ###
|
|
|
<T : 94>
|
|
|
<L : 6>
|
|
|
### CalledPartyBCDNumber ###
|
|
|
<Ext : 1>
|
|
|
<Type : 0 (unknown)>
|
|
|
<NumberingPlan : 1 (ISDN / telephony numbering plan (E.164 / E.163))>
|
|
|
<Num : 0600000000>
|
|
|
### CCCap ###
|
|
|
<T : 21>
|
|
|
<L : 2>
|
|
|
### CCCap ###
|
|
|
<MaxNumSupportedBearers : 0>
|
|
|
<MultimediaCAT : 0>
|
|
|
<ENICM : 0>
|
|
|
<PCP : 0>
|
|
|
<DTMF : 1>
|
|
|
<spare : 0>
|
|
|
<MaxNumSpeechBearers : 0>
|
|
|
### SupportedCodecs ###
|
|
|
<T : 64>
|
|
|
<L : 8>
|
|
|
### SupportedCodecs ###
|
|
|
### CodecSysID ###
|
|
|
<SysID : 4 (UMTS)>
|
|
|
<BMLen : 2>
|
|
|
### CodecBM ###
|
|
|
<TDMA_EFR : 0>
|
|
|
<UMTS_AMR2 : 1>
|
|
|
<UMTS_AMR : 1>
|
|
|
<HR_AMR : 0>
|
|
|
<FR_AMR : 0>
|
|
|
<GSM_EFR : 0>
|
|
|
<GSM_HR : 0>
|
|
|
<GSM_FR : 0>
|
|
|
<reserved : 0>
|
|
|
<reserved : 0>
|
|
|
<OHR_AMR-WB : 0>
|
|
|
<OFR_AMR-WB : 0>
|
|
|
<OHR_AMR : 0>
|
|
|
<UMTS_AMR-WB : 1>
|
|
|
<FR_AMR-WB : 0>
|
|
|
<PDC_EFR : 0>
|
|
|
<spare : ''>
|
|
|
### CodecSysID ###
|
|
|
<SysID : 0 (GSM)>
|
|
|
<BMLen : 2>
|
|
|
### CodecBM ###
|
|
|
<TDMA_EFR : 0>
|
|
|
<UMTS_AMR2 : 0>
|
|
|
<UMTS_AMR : 0>
|
|
|
<HR_AMR : 1>
|
|
|
<FR_AMR : 1>
|
|
|
<GSM_EFR : 1>
|
|
|
<GSM_HR : 1>
|
|
|
<GSM_FR : 1>
|
|
|
<reserved : 0>
|
|
|
<reserved : 0>
|
|
|
<OHR_AMR-WB : 0>
|
|
|
<OFR_AMR-WB : 0>
|
|
|
<OHR_AMR : 0>
|
|
|
<UMTS_AMR-WB : 0>
|
|
|
<FR_AMR-WB : 0>
|
|
|
<PDC_EFR : 0>
|
|
|
<spare : ''>
|
|
|
>>> show(Msg['CalledPartyBCDNumber'][2])
|
|
|
### CalledPartyBCDNumber ###
|
|
|
<Ext : 1>
|
|
|
<Type : 0 (unknown)>
|
|
|
<NumberingPlan : 1 (ISDN / telephony numbering plan (E.164 / E.163))>
|
|
|
<Num : 0600000000>
|
|
|
>>> Msg['CalledPartyBCDNumber'][2].get_val()
|
|
|
[1, 0, 1, '`\x00\x00\x00\x00']
|
|
|
>>> Msg['CalledPartyBCDNumber'][2]['Num'].decode()
|
|
|
'0600000000' |