WikiSS7 Deep-Dive Reference: GTT / MAP ASN.1 BER / SIGTRAN M3UA
Bố cục bài viết
Trang này
Ngày tạo
26/07/2026
Lượt xem
22
Bản
1
Đọc
19m
SS7 Deep-Dive Reference: GTT / MAP ASN.1 BER / SIGTRAN M3UA
Specs: ITU-T Q.711–Q.716 (SCCP), Q.771–Q.775 (TCAP), 3GPP TS 29.002 (MAP), RFC 4666 (M3UA), RFC 4960 (SCTP)
Part 1 — GTT: Global Title Translation
1.1 SCCP Addressing Overview
SCCP có hai loại address để route message:
| Address type | Dùng khi | Ví dụ |
|---|---|---|
| Point Code (PC) + SSN | Đã biết chính xác node đích | MSC gửi đến HLR cùng mạng |
| Global Title (GT) | Không biết PC — cần STP dịch | SMSC gửi SRI-SM với MSISDN |
SCCP address field (Called/Calling Party Address) chứa:
+---+---+---+---+---+---+---+---+
| AI (Address Indicator) 1 byte |
+---+---+---+---+---+---+---+---+
bit7: Point Code included? (1=yes)
bit6: SSN included? (1=yes)
bit5-4: GT indicator
00 = No GT
01 = GT with Nature of Address only
10 = GT with Translation Type only
11 = GT with TT + NP + ES + NAI <-- phổ biến nhất (ITU)
0100 = GT with TT + NP + ES + NAI (ANSI variant)
bit3: Routing Indicator
0 = Route on GT <-- STP làm GTT
1 = Route on PC+SSN
1.2 Global Title Format (GTI=0011, ITU)
Đây là format chuẩn cho MAP traffic trong mạng GSM/3G:
+------------------+------------------+------------------+------------------+
| Translation Type | Numbering Plan | Encoding Scheme | Nature of Addr |
| (TT) 1 byte | (NP) 4 bits | (ES) 4 bits | (NAI) 1 byte |
+------------------+------------------+------------------+------------------+
| Digits (BCD, semi-octet packed) |
+--------------------------------------------------------------------------+
Translation Type (TT):
0x00= Unknown / not used0x09= MAP Mobile (phổ biến nhất cho HLR/VLR queries)0x0A= ISUP (circuit related)
Numbering Plan (NP):
0001= ISDN/telephony (E.164) — dùng cho MSISDN, GT operator0110= Land Mobile (E.212) — dùng cho IMSI
Encoding Scheme (ES):
0001= BCD odd number of digits0010= BCD even number of digits
NAI (Nature of Address Indicator):
0x04= International number (E.164 với country code)
Ví dụ encode GT cho MSISDN +84901234567:
TT = 0x09
NP+ES = 0x11 (NP=0001 ISDN, ES=0001 odd digits)
NAI = 0x04
Digits BCD packed (semi-octet, little-endian per nibble):
+84901234567 → strip '+' → 84901234567 (11 digits, odd)
Packing (pairs, swapped nibbles):
84 → 0x48
90 → 0x09
12 → 0x21
34 → 0x43
56 → 0x65
7 → 0xF7 (F = filler for odd)
GT bytes: 09 11 04 48 09 21 43 65 F7
1.3 GTT Process tại STP
STP nhận SCCP UDT với Called Party = GT, thực hiện:
Step 1: Đọc Translation Type (TT) → chọn translation table
Step 2: Đọc digits (GT number) → longest prefix match
Step 3: Tra bảng → lấy (DPC, SSN, new GT nếu intermediate)
Step 4: Rewrite Called Party Address:
- Nếu destination là local: set Routing Indicator = PC+SSN, xóa GT
- Nếu cần forward tiếp: giữ GT hoặc replace GT
Step 5: Set DPC trong MTP3 routing label → forward
GTT Table structure (conceptual):
Table ID: TT=0x09 (MAP Mobile)
| GT Prefix | Mask | DPC | SSN | Action | Description |
|---------------|------|--------|-----|---------------|-------------------|
| +84 | /2 | 2-1-1 | 6 | Replace DPC | Viettel HLR range |
| +8490 | /4 | 2-1-2 | 6 | Replace DPC | Viettel HLR-2 |
| +8498 | /4 | 2-1-3 | 6 | Replace DPC | Mobifone HLR |
| +8479 | /4 | 3-2-1 | 6 | Forward+GTT | Roaming, next STP |
| * | /0 | 4-0-1 | 0 | Route to GW | International GW |
Longest prefix match: +8490... matches /4 trước /2.
1.4 Intermediate GTT vs Final GTT
Intermediate GTT (ISTP — Intermediate STP):
- STP A làm GTT → thay DPC = STP B
- Called Party GT giữ nguyên
- STP B làm GTT tiếp (final)
Final GTT:
- STP thay DPC = HLR PC, SSN = 6
- Called Party → Routing Indicator = Route on PC+SSN
- GT có thể bị xóa hoặc giữ lại tùy implementation
1.5 SCCP UDT Frame Layout
SCCP UDT (Class 0, Unitdata):
+--------+--------+
| MsgType=0x09 | 1 byte (UDT = 0x09)
+--------+--------+
| Class=0x00 | 1 byte (Class 0, no sequence)
+-----------------+
| Ptr to CdPA | 1 byte (relative pointer)
| Ptr to CgPA | 1 byte
| Ptr to Data | 1 byte
+-----------------+
| CdPA Length | 1 byte
| CdPA AI | 1 byte (Address Indicator)
| CdPA SSN | 1 byte (if present)
| CdPA GT | variable
+-----------------+
| CgPA Length | 1 byte
| CgPA AI | 1 byte
| CgPA SSN | 1 byte
| CgPA GT | variable
+-----------------+
| Data Length | 1 byte
| TCAP + MAP data | variable
+-----------------+
Hex ví dụ SCCP UDT header:
09 # MsgType = UDT
00 # Protocol Class = 0
03 # Pointer to CdPA (offset 3 from here)
0E # Pointer to CgPA
17 # Pointer to Data
# Called Party Address (CdPA) — HLR GT
09 # Length = 9 bytes
C4 # AI: GT=0011, PC=0, SSN=1, RI=GT
06 # SSN = 6 (HLR)
09 11 04 # TT=09, NP+ES=11, NAI=04
48 09 21 43 65 F7 # GT digits = +84901234567
# Calling Party Address (CgPA) — SMSC GT
07 # Length = 7 bytes
C4 # AI
87 # SSN = 135 (SMSC)
09 11 04
25 16 87 19 F6 # GT = +52618791 (SMSC number)
Part 2 — MAP Message Encoding: ASN.1 BER
2.1 Layering TCAP → MAP
SCCP Data field chứa:
[TCAP]
Begin / End / Continue / Abort
DialoguePortion (optional)
ComponentPortion
[Component]
Invoke / ReturnResult / ReturnError / Reject
operationCode
parameter ← đây là MAP PDU, encoded ASN.1 BER
2.2 TCAP BER Structure
TCAP Begin (cho Invoke):
62 LL # Begin APDU (tag 0x62, constructed)
48 LL # otid (Originating Transaction ID) tag=0x48
XX XX XX XX # 4-byte transaction ID
6C LL # Components (tag 0x6C, constructed)
A1 LL # Invoke component (tag 0xA1)
02 01 NN # invokeID (INTEGER, value=NN)
02 01 OO # operationCode (LOCAL INTEGER)
# OO = operation code (see MAP ops below)
30 LL # parameter (SEQUENCE)
... # MAP-specific encoding
TCAP End (ReturnResult):
64 LL # End APDU (tag 0x64)
49 LL # dtid (Destination Transaction ID)
XX XX XX XX
6C LL # Components
A2 LL # ReturnResult (tag 0xA2)
02 01 NN # invokeID (same as Invoke)
30 LL # result + parameter
02 01 OO # operationCode
30 LL # parameter
... # MAP result encoding
2.3 MAP Operation Codes (Local)
| Code | Operation | Direction |
|---|---|---|
| 22 (0x16) | sendRoutingInfoForSM (SRI-SM) | SMSC → HLR |
| 46 (0x2E) | mt-forwardSM (MT-FSM) | SMSC → MSC |
| 44 (0x2C) | forwardSM (MO-FSM) | MSC → SMSC |
| 2 (0x02) | updateLocation (UL) | VLR → HLR |
| 22 (0x16) | sendRoutingInfo (SRI) | MSC → HLR |
| 71 (0x47) | anyTimeInterrogation (ATI) | attacker → HLR |
| 3 (0x03) | cancelLocation | HLR → VLR |
2.4 SRI-SM Encoding (sendRoutingInfoForSM)
MAP TS 29.002 §10.3.4 — operation code = 0x16 (22)
Request:
MAP-SRI-SM-Arg ::= SEQUENCE {
msisdn [0] ISDN-AddressString, -- victim MSISDN
sm-RP-PRI [1] BOOLEAN, -- Priority flag
serviceCentreAddress [2] AddressString, -- SMSC address
...
}
BER Encoding ví dụ — SRI-SM cho MSISDN +84901234567, SMSC +84900000000:
TCAP Begin:
62 3A
48 04 00 00 00 01 # otid = 0x00000001
6C 32 # Components
A1 30 # Invoke
02 01 01 # invokeID = 1
02 01 16 # opCode = 22 (SRI-SM)
30 28 # MAP-SRI-SM-Arg SEQUENCE
81 07 # [1] msisdn (context 0, IMPLICIT)
# wait — correct tag:
# ISDN-AddressString = OCTET STRING
# [0] IMPLICIT OCTET STRING
80 07 # tag=0x80 (context 0, primitive), len=7
91 # TON/NPI: 0x91 = international E.164
48 09 21 43 65 F7 # +84901234567 BCD
81 01 # [1] sm-RP-PRI BOOLEAN
FF # TRUE
82 07 # [2] serviceCentreAddress
91 # TON/NPI international
48 09 00 00 00 F0 # +84900000000 BCD
SRI-SM Response (ReturnResult):
MAP-SRI-SM-Res ::= SEQUENCE {
imsi [0] IMSI OPTIONAL,
locationInfoWithLMSI [1] LocationInfoWithLMSI,
...
}
LocationInfoWithLMSI ::= SEQUENCE {
networkNodeNumber ISDN-AddressString, -- serving MSC GT
lmsi LMSI OPTIONAL, -- 4 bytes
...
}
BER encoding response:
64 2E # End APDU
49 04 00 00 00 01 # dtid
6C 26
A2 24 # ReturnResult
02 01 01 # invokeID = 1
30 1F
02 01 16 # opCode
30 19 # MAP-SRI-SM-Res
80 08 # [0] IMSI (BCD)
21 43 62 10 32 54 76 F8 # IMSI 124361023456780 BCD
A1 0D # [1] LocationInfoWithLMSI
04 07 # networkNodeNumber OCTET STRING
91 48 09 21 00 00 F0 # MSC GT +84901200000
04 04 # lmsi
AB CD 12 34
2.5 MT-ForwardSM Encoding (mt-forwardSM)
MAP TS 29.002 §10.3.8 — operation code = 0x2E (46)
MAP-MT-Forward-SM-Arg ::= SEQUENCE {
sm-RP-DA SM-RP-DA, -- Destination (IMSI or LMSI)
sm-RP-OA SM-RP-OA, -- Originating (SMSC address)
sm-RP-UI SignalInfo, -- SMS TPDU (TP-Deliver PDU)
...
}
SM-RP-DA ::= CHOICE {
imsi [0] IMSI,
lmsi [1] LMSI,
...
}
SM-RP-OA ::= CHOICE {
msisdn [2] ISDN-AddressString,
serviceCentreAddressOA [4] AddressString,
}
BER Encoding MT-FSM:
TCAP Begin:
62 45
48 04 00 00 00 02 # otid = 0x00000002
6C 3D
A1 3B
02 01 01 # invokeID = 1
02 01 2E # opCode = 46 (mt-forwardSM)
30 33 # MAP-MT-Forward-SM-Arg
# sm-RP-DA: [0] IMSI
A0 09
04 08 # IMSI OCTET STRING
21 43 62 10 32 54 76 F8
# sm-RP-OA: [4] serviceCentreAddress (SMSC)
A4 09
04 07
91 48 09 00 00 00 F0 # SMSC GT
# sm-RP-UI: SignalInfo = OCTET STRING (SMS TPDU)
04 17
# TP-Deliver PDU (GSM 03.40):
04 # MTI=00 (Deliver), MMS=0, RP=1
0B # TP-OA length = 11 digits
91 # TP-OA TON/NPI = international
84 09 01 82 43 F5 # Originating address +48901028345
00 # TP-PID = 0
00 # TP-DCS = 0 (GSM7)
01 80 91 21 32 54 76 # TP-SCTS timestamp
06 # TP-UDL = 6 chars
C8 F7 1D 14 96 97 # TP-UD "Hello!" GSM7 encoded
2.6 ASN.1 BER Quick Reference
| Tag | Type | Notes |
|---|---|---|
| 0x02 | INTEGER | |
| 0x04 | OCTET STRING | dùng cho IMSI, addresses |
| 0x05 | NULL | |
| 0x30 | SEQUENCE (constructed) | |
| 0x31 | SET (constructed) | |
| 0xA0..AF | Context [0]..[15] constructed | CHOICE/OPTIONAL fields |
| 0x80..8F | Context [0]..[15] primitive | IMPLICIT primitive |
Length encoding:
< 128: 1 byte (e.g., 0x07)
>= 128: 0x81 LL (1 extra byte)
>= 256: 0x82 LL LL (2 extra bytes)
BCD/ISDN-AddressString format:
Byte 0: TON/NPI
0x91 = international E.164
0xA1 = national
0x81 = unknown
Bytes 1+: digits BCD swapped nibbles, 0xF filler
+84901234567 → 48 09 21 43 65 F7
2.7 Python Scapy — Build SRI-SM + MT-FSM
from scapy.all import *
from scapy.contrib.sctp import *
# Manual BER builder (Scapy không có MAP dissector built-in)
def encode_isdn_address(number: str) -> bytes:
"""E.164 → ISDN-AddressString BCD bytes"""
digits = number.lstrip('+')
if len(digits) % 2:
digits += 'F'
bcd = bytes(
int(digits[i+1], 16) << 4 | int(digits[i], 16)
for i in range(0, len(digits), 2)
)
return bytes([0x91]) + bcd # TON/NPI=0x91
def encode_imsi(imsi: str) -> bytes:
"""IMSI → BCD bytes"""
if len(imsi) % 2:
imsi += 'F'
return bytes(
int(imsi[i+1], 16) << 4 | int(imsi[i], 16)
for i in range(0, len(imsi), 2)
)
def tlv(tag: int, value: bytes) -> bytes:
"""Simple BER TLV encoder (short form only)"""
l = len(value)
if l < 128:
return bytes([tag, l]) + value
elif l < 256:
return bytes([tag, 0x81, l]) + value
else:
return bytes([tag, 0x82, (l >> 8) & 0xFF, l & 0xFF]) + value
def build_sri_sm(msisdn: str, smsc: str, invoke_id: int = 1,
otid: bytes = b'\x00\x00\x00\x01') -> bytes:
msisdn_bytes = encode_isdn_address(msisdn)
smsc_bytes = encode_isdn_address(smsc)
# MAP SRI-SM Arg
map_arg = (
tlv(0x80, msisdn_bytes) + # [0] msisdn
tlv(0x81, b'\xFF') + # [1] sm-RP-PRI = TRUE
tlv(0x82, smsc_bytes) # [2] serviceCentreAddress
)
map_seq = tlv(0x30, map_arg)
# TCAP Component: Invoke
component = (
tlv(0x02, bytes([invoke_id])) + # invokeID
tlv(0x02, bytes([0x16])) + # opCode = 22
map_seq
)
invoke = tlv(0xA1, component)
components = tlv(0x6C, invoke)
# TCAP Begin
tcap = tlv(0x48, otid) + components
return tlv(0x62, tcap)
# Test
pdu = build_sri_sm("+84901234567", "+84900000000")
print(pdu.hex())
Part 3 — SIGTRAN M3UA Association Setup
3.1 SIGTRAN Stack Recap
Application (MAP/ISUP)
↓
SCCP
↓
M3UA ← MTP3 User Adaptation Layer (RFC 4666)
↓
SCTP ← Stream Control Transmission Protocol (RFC 4960)
↓
IP
Roles:
| Role | Abbrev | Mô tả |
|---|---|---|
| Signaling Gateway | SGP | STP phía mạng SS7 legacy |
| Application Server Process | ASP | Application phía IP (ss7-sms-generator) |
| Application Server | AS | Logical entity gom nhiều ASP |
| Signaling Gateway Process | SGP | Phía STP |
3.2 M3UA Message Types
| Class | Messages |
|---|---|
| Transfer | DATA (payload) |
| SSNM (SS7 Signaling Network Mgmt) | DUNA, DAVA, DAUD, SCON, DUPU, DRST |
| ASPSM (ASP State Mgmt) | ASPUP, ASPUP-ACK, ASPDN, ASPDN-ACK, BEAT, BEAT-ACK |
| ASPTM (ASP Traffic Mgmt) | ASPAC, ASPAC-ACK, ASPIA, ASPIA-ACK |
| MGMT | ERR, NTFY |
| RKM (Routing Key Mgmt) | REG-REQ, REG-RSP, DEREG-REQ, DEREG-RSP |
3.3 Association Bring-Up Sequence
ASP (ss7-sms-generator) SGP (STP/SG)
| |
|---[SCTP INIT]---------------->| SCTP 4-way handshake
|<--[SCTP INIT-ACK]-------------|
|---[SCTP COOKIE-ECHO]--------->|
|<--[SCTP COOKIE-ACK]-----------|
| |
|---[ASPUP]-------------------->| M3UA layer
|<--[ASPUP-ACK]-----------------|
| |
|---[ASPAC (Active)]----------->| Request traffic
|<--[ASPAC-ACK]-----------------|
| |
|<--[DAVA (Dest Available)]-----| DPC reachable notify
| |
|---[DATA (SCCP/TCAP/MAP)]----->| Actual SS7 payload
|<--[DATA (response)]-----------|
3.4 M3UA Packet Format
Common Header (8 bytes, mọi M3UA message):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version | Reserved | Message Class | Message Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Parameters ... |
- Version = 0x01
- Message Class / Type:
| Class | Type | Name |
|---|---|---|
| 0x01 | 0x01 | ASPUP |
| 0x01 | 0x02 | ASPDN |
| 0x01 | 0x03 | BEAT |
| 0x01 | 0x04 | BEAT-ACK |
| 0x01 | 0x05 | ASPUP-ACK |
| 0x01 | 0x06 | ASPDN-ACK |
| 0x02 | 0x01 | ASPAC |
| 0x02 | 0x02 | ASPIA |
| 0x02 | 0x03 | ASPAC-ACK |
| 0x02 | 0x04 | ASPIA-ACK |
| 0x03 | 0x01 | ERR |
| 0x03 | 0x02 | NTFY |
| 0x04 | 0x01 | DUNA |
| 0x04 | 0x02 | DAVA |
| 0x04 | 0x03 | DAUD |
| 0x06 | 0x01 | DATA |
M3UA Parameters (Tag-Length-Value):
| Tag | Parameter | Used in |
|---|---|---|
| 0x0006 | Traffic Mode Type | ASPAC |
| 0x0007 | Error Code | ERR |
| 0x0008 | Status | NTFY |
| 0x000B | ASP Identifier | ASPUP |
| 0x000C | Affected Point Code | DUNA/DAVA |
| 0x0200 | Network Appearance | DATA, DUNA/DAVA |
| 0x0201 | Routing Context | DATA, ASPAC |
| 0x0202 | Protocol Data | DATA (chứa MTP3+SCCP payload) |
| 0x0203 | Correlation ID | REG-REQ |
| 0x0204 | Registration Result | REG-RSP |
| 0x0205 | Deregistration Result | DEREG-RSP |
3.5 M3UA DATA Message — Protocol Data Parameter
DATA message = M3UA header + Routing Context + Protocol Data:
M3UA Header:
01 00 06 01 # Version=1, Rsvd=0, Class=Transfer(6), Type=DATA(1)
00 00 00 34 # Length = 52 bytes total
Parameters:
02 01 00 08 # Tag=0x0201 (Routing Context), Len=8
00 00 00 01 # RC = 1
02 02 00 25 # Tag=0x0202 (Protocol Data), Len=37
# MTP3 Routing Label (ITU 32-bit):
00 02 01 02 # OPC=2-1-2 (DPC=2-1-1 OPC=sender) packed
# ITU: bits[0-13]=DPC, [14-27]=OPC, [28-31]=SLS
# Actually layout:
# [31-28]=SLS(4) [27-14]=OPC(14) [13-0]=DPC(14)
# DPC=2-1-1: zone=2(2b), area=1(8b), id=1(4b) = 0b10_00000001_0001
# OPC=2-1-2: = 0b10_00000001_0010
# SLS=0
03 # Service Indicator = 0x03 (SCCP)
83 # Network Indicator = 0x83 (ITU national + spare)
# SCCP UDT payload follows:
09 00 03 0E 17 ... (SCCP UDT as shown in Part 1)
MTP3 Routing Label bit layout (ITU, 32-bit):
Bit: 31-28 27-14 13-0
[SLS] [OPC 14b] [DPC 14b]
ITU Point Code x-y-z → 14 bits:
zone(2b) | area(8b) | id(4b)
PC 2-1-5: 10 | 00000001 | 0101 = 0b10_00000001_0101 = 0x0815
PC 2-1-1: 10 | 00000001 | 0001 = 0b10_00000001_0001 = 0x0811
3.6 ASPUP / ASPAC Hex Detail
ASPUP:
01 00 01 01 # Class=ASPSM(1), Type=ASPUP(1)
00 00 00 10 # Length = 16
00 0B 00 08 # Tag=ASP Identifier(0x000B), Len=8
00 00 00 2A # ASP ID = 42 (arbitrary)
ASPAC (Traffic Mode = Override):
01 00 02 01 # Class=ASPTM(2), Type=ASPAC(1)
00 00 00 18 # Length = 24
00 06 00 08 # Tag=Traffic Mode Type(0x0006), Len=8
00 00 00 01 # Override (1) — only this ASP active
02 01 00 08 # Tag=Routing Context(0x0201), Len=8
00 00 00 01 # RC=1
ASPAC-ACK:
01 00 02 03 # Class=ASPTM(2), Type=ASPAC-ACK(3)
00 00 00 18
00 06 00 08
00 00 00 01
02 01 00 08
00 00 00 01
3.7 SCTP Details (RFC 4960)
M3UA chạy trên SCTP. Các điểm quan trọng:
SCTP vs TCP:
- Multi-stream: tránh head-of-line blocking
- Multi-homing: failover IP tự động
- Message boundaries preserved (không stream-based như TCP)
- Built-in heartbeat (HEARTBEAT chunk)
SCTP Port cho SIGTRAN:
- M3UA: port 2905
- SUA (SCCP User Adaptation): port 14001
- IUA (ISDN Q.921 User Adaptation): port 9900
SCTP Chunk types:
0x00 = DATA
0x01 = INIT
0x02 = INIT-ACK
0x03 = SACK
0x04 = HEARTBEAT
0x05 = HEARTBEAT-ACK
0x06 = ABORT
0x07 = SHUTDOWN
0x08 = SHUTDOWN-ACK
0x0A = COOKIE-ECHO
0x0B = COOKIE-ACK
0x0E = SHUTDOWN-COMPLETE
Linux SCTP socket (Java JNA context):
// SCTP one-to-one socket
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
// Multi-homing: bind multiple IPs
struct sockaddr_in addrs[2];
sctp_bindx(fd, addrs, 2, SCTP_BINDX_ADD_ADDR);
// Stream count
struct sctp_initmsg init = {
.sinit_num_ostreams = 2,
.sinit_max_instreams = 2,
.sinit_max_attempts = 3,
.sinit_max_init_timeo = 1000
};
setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init));
// Send on stream 0 (M3UA uses stream 0 typically)
struct sctp_sndrcvinfo sinfo = { .sinfo_stream = 0 };
sctp_send(fd, m3ua_buf, m3ua_len, &sinfo, 0);
3.8 Java Implementation (JNA + SCTP cho ss7-sms-generator)
// M3UA frame builder
public class M3UABuilder {
// M3UA Common Header
public static byte[] header(int msgClass, int msgType, int bodyLen) {
ByteBuffer buf = ByteBuffer.allocate(8);
buf.put((byte) 0x01); // version
buf.put((byte) 0x00); // reserved
buf.put((byte) msgClass);
buf.put((byte) msgType);
buf.putInt(8 + bodyLen); // total length
return buf.array();
}
// TLV parameter
public static byte[] param(int tag, byte[] value) {
int len = 4 + value.length;
int padded = (len + 3) & ~3; // 4-byte aligned
ByteBuffer buf = ByteBuffer.allocate(padded);
buf.putShort((short) tag);
buf.putShort((short) len);
buf.put(value);
// padding bytes already zero
return buf.array();
}
// ASPUP message
public static byte[] aspup(int aspId) {
byte[] aspIdParam = param(0x000B,
ByteBuffer.allocate(4).putInt(aspId).array());
byte[] body = aspIdParam;
return concat(header(0x01, 0x01, body.length), body);
}
// ASPAC message (Override mode, RC=1)
public static byte[] aspac(int routingContext) {
byte[] tmParam = param(0x0006,
ByteBuffer.allocate(4).putInt(1).array()); // Override
byte[] rcParam = param(0x0201,
ByteBuffer.allocate(4).putInt(routingContext).array());
byte[] body = concat(tmParam, rcParam);
return concat(header(0x02, 0x01, body.length), body);
}
// DATA message wrapping SCCP payload
public static byte[] data(int routingContext,
int opc, int dpc, int sls,
byte sio,
byte[] sccpPayload) {
// MTP3 Routing Label (ITU 32-bit, little-endian in M3UA)
// M3UA Protocol Data: OPC, DPC as 32-bit big-endian each
ByteBuffer protData = ByteBuffer.allocate(8 + sccpPayload.length);
protData.putInt(opc); // OPC 32-bit (upper 18 bits unused for ITU)
protData.putInt(dpc); // DPC 32-bit
protData.put((byte) sls); // SLS
protData.put(sio); // Service Indicator + NI
protData.put((byte) 0x00); // spare
protData.put((byte) 0x00); // spare
protData.put(sccpPayload);
byte[] pdParam = param(0x0202, protData.array());
byte[] rcParam = param(0x0201,
ByteBuffer.allocate(4).putInt(routingContext).array());
byte[] body = concat(rcParam, pdParam);
return concat(header(0x06, 0x01, body.length), body);
}
private static byte[] concat(byte[]... arrays) {
int total = 0;
for (byte[] a : arrays) total += a.length;
byte[] result = new byte[total];
int pos = 0;
for (byte[] a : arrays) {
System.arraycopy(a, 0, result, pos, a.length);
pos += a.length;
}
return result;
}
}
Usage trong ss7-sms-generator:
// 1. Bring up M3UA association (via SCTP)
SctpChannel channel = SctpChannel.open();
channel.connect(new InetSocketAddress("stp.lab.local", 2905));
byte[] aspupMsg = M3UABuilder.aspup(42);
channel.send(ByteBuffer.wrap(aspupMsg), null);
// Wait for ASPUP-ACK...
byte[] aspac = M3UABuilder.aspac(1);
channel.send(ByteBuffer.wrap(aspac), null);
// Wait for ASPAC-ACK...
// 2. Build SCCP+MAP payload
byte[] sriSmPdu = SriSmBuilder.build("+84901234567", "+84900000000");
byte[] sccpUdt = SccpBuilder.buildUDT(
sriSmPdu,
new SccpAddr(GT_INDICATOR, "+84901234567", SSN_HLR), // CdPA
new SccpAddr(GT_INDICATOR, "+84900000000", SSN_SMSC) // CgPA
);
// 3. Wrap in M3UA DATA
byte[] m3uaData = M3UABuilder.data(
1, // routing context
0x0812, // OPC (2-1-2 = SMSC)
0x0811, // DPC (2-1-1 = STP/HLR)
0, // SLS
(byte)0x03, // SIO: SI=3 (SCCP), NI=0
sccpUdt
);
channel.send(ByteBuffer.wrap(m3uaData), null);
3.9 Wireshark Filter Quick Reference
# Tất cả SCTP traffic
sctp
# M3UA layer
m3ua
# SCCP
sccp
# TCAP
tcap
# MAP
gsm_map
# Filter SRI-SM operation
gsm_map.opr.code == 22
# Filter MT-ForwardSM
gsm_map.opr.code == 46
# Filter by MSISDN in Called Party
sccp.called.digits == "84901234567"
# M3UA ASPUP messages
m3ua.message_class == 1 && m3ua.message_type == 1
# M3UA DATA messages only
m3ua.message_class == 6 && m3ua.message_type == 1
Part 4 — Tích hợp: Flow đầy đủ cho ss7-sms-generator
ss7-sms-generator
(Quarkus + JNA / SCTP)
|
| SCTP port 2905
v
+------------------+
| STP (SGP) | ← có thể là Osmocom STP lab hoặc inject thẳng
| GTT Table | vào Suricata bắt interface
+------------------+
|
| SS7 (SCCP UDT)
v
+------------------+
| HLR / SMSC sim | ← Open5GS HSS hoặc SigPloit listener
+------------------+
Suricata bắt trên:
- SCTP port 2905 (M3UA)
- hoặc raw AF_PACKET (nếu inject thẳng Ethernet)
Rule ví dụ detect SRI-SM burst (location tracking via SMS):
alert sctp any any -> any 2905 (
msg:"SS7 SRI-SM burst - possible SMS interception";
content:"|62|"; # TCAP Begin
content:"|02 01 16|"; # opCode = 22 (SRI-SM)
threshold: type threshold, track by_src, count 10, seconds 60;
sid:9000001; rev:1;
)
Rule detect MT-ForwardSM từ GT không trong whitelist:
alert sctp any any -> any 2905 (
msg:"SS7 MT-ForwardSM from unknown SMSC GT";
content:"|02 01 2E|"; # opCode = 46
sid:9000002; rev:1;
)
References
| Spec | Coverage |
|---|---|
| ITU-T Q.711–Q.716 | SCCP |
| ITU-T Q.771–Q.775 | TCAP |
| 3GPP TS 29.002 | MAP |
| RFC 4666 | M3UA |
| RFC 4960 | SCTP |
| GSMA FS.11 | SS7 security categories |
| 3GPP TS 23.040 | SMS (TP layer) |