5.6 Attaching, calling, and the services around them
These are the procedures a phone runs in its first two minutes on a network, and the services an operator runs on top of them. All of it is offline work: parse a capture, build a message, read what a network claims about itself.
5.6.1 Attach and the GUTI
Need: a capture, or nothing for the codec. A GUTI is the temporary identity a network hands out so the permanent one need not cross the air — which is exactly why binding a GUTI to an IMSI is the goal of half the passive work in §5.1.5.
modules/09_lte_attach.sh --decode-nas <hex> # an EMM message and its IEs
modules/09_lte_attach.sh --setup-complete <nas_hex> # what an ATTACH COMPLETE contained
modules/09_lte_attach.sh --guti-decode 080BF600F110123456DEADBEEF
# identity_type GUTI / plmn 001-01 / mme_group 4660 / mme_code 86 / m_tmsi 3735928559
modules/09_lte_attach.sh --guti-map <guti_hex> 001010000000001 # bind it, with evidence
modules/09_lte_attach.sh --guti-tsv # the bindings, attached count included
modules/09_lte_attach.sh --realloc-command <hex> # a GUTI REALLOCATION COMMAND
modules/09_lte_attach.sh --nas-responder <file> # hold attach state across a dialogue
--guti-map is the store write: one row per GUTI, with an attach count that
increments rather than appending a duplicate, so a GUTI seen five times is one
binding seen five times. --realloc-command matters because the network is
allowed to change the GUTI mid-session, and a mapping that ignores reallocation
silently pairs the wrong subscriber with the wrong temporary identity.
What you read: the PLMN, the MME group and code (which locate the subscriber at network granularity before any timing analysis), the M-TMSI, and the binding's evidence.
When it refuses: a hex string that is not an EPS mobile identity carrying a GUTI is refused with the identity type it actually found — the commonest error is passing the bare M-TMSI, which has no type octet.
Read next: §5.1.5 to turn a binding into a persistent identifier, and §5.7.1 for what the same attach tells you about location.
5.6.2 VoLTE, VoWiFi and the SIP edge
Need: a capture for the parsing verbs; a target for the sending verbs. Voice over LTE carries SIP inside the user plane, and the SIP is protected by the same cipher as everything else — except when it is not, and except when the operator reuses a keystream.
modules/30_volte_ims.sh --sip-parse <hex> # a SIP request or response
modules/30_volte_ims.sh --sip-build register # build one
modules/30_volte_ims.sh --revolte-demo <pt1> <pt2> # same-keystream XOR demonstration
modules/30_volte_ims.sh --keystream-recover <ct> <known> # recover the keystream, decrypt
modules/30_volte_ims.sh --imp4gt-model # the IMP4GT sequence and preconditions
modules/30_volte_ims.sh --sip-flood register 100 512 512 # flood / amplification model
modules/36_vowifi.sh --epdg 310 260 # epdg.epc.mnc260.mcc310.pub.3gppnetwork.org
modules/36_vowifi.sh --eap-privacy # what a NAI reveals before auth
modules/36_vowifi.sh --dh <n> # is this key exchange acceptable
modules/36_vowifi.sh --transform <n> # IKEv2 transform names
--revolte-demo and --keystream-recover are the honest version of the ReVoLTE
finding: two calls that reuse a keystream XOR to a known value, and the module
demonstrates it on chosen inputs so you can see the mechanism rather than take
the paper's word for it. --imp4gt-model does the same for the identity-
pointer attack and, like §5.3.2, states its preconditions up front.
VoWiFi is the same voice service over a different transport, and --epdg shows
the one thing worth knowing before reading anything else: the ePDG name is
derivable from the PLMN alone, which is why the tunnel endpoint is not a secret.
What you read: for SIP, the method, headers and SDP (the SDP is where the
media endpoints are); for the ePDG, the FQDN and, via --validate-cert, whether
the certificate that answers it is the one that name should present.
When it refuses: --dh on a group RFC 8247 forbids reports the verdict rather
than the number; --validate-cert with no trust anchor says so instead of
returning "valid".
Read next: §5.4.4 for the plaintext lever underneath, and §5.9.4 for the integrity gap both techniques depend on.
5.6.3 Shared RAN and PLMN leaks
Need: nothing for the codec; a capture for the leak check. A network built by one operator and shared with another still broadcasts a PLMN list, and the interesting question is whether the list is the whole story.
modules/43_ran_share.sh --plmn-encode 310 260 # 130062
modules/43_ran_share.sh --plmn-decode 130062
modules/43_ran_share.sh --eplmn '310-260,310-410' # equivalent-PLMN list, cap 15
modules/43_ran_share.sh --mode mocn # sharing-mode classification
modules/43_ran_share.sh --leak-check <tsv> # PLMN outside the broadcast set
modules/43_ran_share.sh --plan # two-core lab handoff plan
--leak-check is the whole point: it compares the PLMNs seen in signalling
against the PLMNs the cell broadcasts, and any PLMN in the first set that is not
in the second is a leak — either a misconfiguration or an interface nobody
documented. --mode classifies MOCN, MORAN and GWCN, which matters because the
three share different things and only one of them shares the cell identity.
What you read: the encoded PLMN, the effective list and its length limit, and the leak findings with the message they came from.
When it refuses: a fifthteen-plus-one PLMN list, i.e. more than the 15 the specification allows; a PLMN that is not 5 or 6 digits.
Read next: §5.1.1 for where the broadcast set comes from.
5.6.4 A carrier's API surface
Need: the API's own specification or a capture; nothing for the analysis verbs. Every carrier now ships a self-service API, and the security review of one is a checklist rather than an exploit.
modules/44_carrier_api.sh --openapi spec.json # paths, servers, schemes
modules/44_carrier_api.sh --authz-matrix spec.json # four-case test plan per operation
modules/44_carrier_api.sh --jwt-audit <token> # alg=none, expiry, audience
modules/44_carrier_api.sh --token-bucket 10 20 100 60 # is the rate limit real
modules/44_carrier_api.sh --diff a.json b.json # response differential between captures
modules/44_carrier_api.sh --stuffing conf.json # credential-stuffing resistance controls
modules/44_carrier_api.sh --report # assessment skeleton
--authz-matrix is the valuable one: for each operation it lays out the four
cases that must all be tested — owner, other user, no token, expired token — and
the matrix is the finding when any cell behaves like the owner. --jwt-audit
checks the three failures that account for most real breaks: unsigned tokens
accepted, expiry not enforced, audience not checked.
What you read: the surface (paths, servers, security schemes) and per-operation the authorisation cases with what a pass looks like.
When it refuses: a document that is not OpenAPI 3; a token that is not a JWT.
Read next: §5.9.3, since an API is one of the lawful-intercept surfaces the same operator exposes.