Для решения начать техническую дискуссию по этой теме меня сподвигло несколько причин. Одна из них это просто моя недостаточная квадратность головы для решения таких задач по сути з нуля. Но не будем говорить о грустном, а сделаем небольшой introduction для нашей основной темы ради которой и создается это обсуждение.
Вы когда то получали на телефон сообщения рода "Внимание! угроза урагана, землетрясения,отключение Xhamster" и тому подобные? Некоторые еще даже орут резким звуком и вибрируют. Так вот, все эти сообщения попадают под PWS ака "Public Warning Service". Раньше, в стареньком GSM и 3G, подобные сообщения передавались через CBS (Cell Broadcasting Service), а вот с приходом LTE и 5G для аналогичных целей был введен новый стандарт, известный как CMAS (Commercial Mobile Alert System). Зачем же это нам, обычным смертным?
По сути, CMAS – это отличный механизм для распространения фишинга. Задумайтесь, вывод текстовой информации на дисплеи смартфонов в радиусе нескольких сотен метров, с минимальными затратами и без сложных MITM атак, даунгрейдов с LTE на 2G и другой сложной технической мастурбацией, которая требует дорогостоящего оборудования. В отличие от многих других протоколов передачи данных, которые фокусируются на приватности и безопасности, CMAS проектировался с другой целью: доставить важные уведомления быстро и с минимальными трудностями, как для операторов, так и для пользователей. Этот стандарт фактически является уязвимым по дизайну: так как не требуется никакой аутентификации с устройствами, так что кто угодно, кто сможет сгенерировать правильный сигнал, передать сообщение в эфир и оно сработает. Ни про какой rnti там даже речи нет.
В конце я озвучу те трудности, с которыми я столкнулся, пытаясь реализовать этот код.
ASN.1 – это вообще отдельная головная боль. Мы ведь все привыкли к JSON или XML, где всё более-менее понятно. Но когда начинаешь работать с Abstract Syntax Notation One, понимаешь, что это как целый мир, где каждое сообщение требует железного понимания как оно работает, что бы было можно вносить хоть какие то модификации. Пытаться получить правильное бинарное представление сообщения, когда я работал з инструментами вроде asn1c было довольно поучитально, но в то же время голова у меня буквально гудела после 3х суток безвылазного изучения этой темы.
Давайте пройдемся по тех. части.
Сообщение CMAS состоит из трех частей:
Вот сам код:
На данный момент у меня встали несколько вопросов.
Как правильно внедрить схемы ASN1 в код в матлабе что бы их можно было правильно кодировать?
Где взять полноценные файлы .asn кроме текстовых вставок из спецификаций 3GGP?
Имеет ли смысл работать в TDD если для реализации сигнала не важно какой режим выбран?
В моей голове самый оптимальный вариант это скомпилировать ASN1 структуры в бинарный формат а потом его вплетать в LTE фрейм. Возможно я выбрал не тот подход и всю эту задачу можно гораздо проще осуществить, буду рад любым коментариям и любому техническому обсуждению.
Вы когда то получали на телефон сообщения рода "Внимание! угроза урагана, землетрясения,
По сути, CMAS – это отличный механизм для распространения фишинга. Задумайтесь, вывод текстовой информации на дисплеи смартфонов в радиусе нескольких сотен метров, с минимальными затратами и без сложных MITM атак, даунгрейдов с LTE на 2G и другой сложной технической мастурбацией, которая требует дорогостоящего оборудования. В отличие от многих других протоколов передачи данных, которые фокусируются на приватности и безопасности, CMAS проектировался с другой целью: доставить важные уведомления быстро и с минимальными трудностями, как для операторов, так и для пользователей. Этот стандарт фактически является уязвимым по дизайну: так как не требуется никакой аутентификации с устройствами, так что кто угодно, кто сможет сгенерировать правильный сигнал, передать сообщение в эфир и оно сработает. Ни про какой rnti там даже речи нет.
В конце я озвучу те трудности, с которыми я столкнулся, пытаясь реализовать этот код.
Понимание стандартов и спецификаций
CMAS – это не просто простое уведомление, а целая система с сотнями страниц документации. Понимание всех этих тонкостей заняло приличное количество времени. Стандарты для передачи сообщений, например, такие как 3GPP TS 36.331 или 3GPP TS 23.041, действительно являются сложными. И если у вас не чешутся руки что бы погрузиться в мир ASN.1 и проприетарной буржуйской документации, то будет довольно трудно вникнуть и разобраться что к чему.ASN.1 – это вообще отдельная головная боль. Мы ведь все привыкли к JSON или XML, где всё более-менее понятно. Но когда начинаешь работать с Abstract Syntax Notation One, понимаешь, что это как целый мир, где каждое сообщение требует железного понимания как оно работает, что бы было можно вносить хоть какие то модификации. Пытаться получить правильное бинарное представление сообщения, когда я работал з инструментами вроде asn1c было довольно поучитально, но в то же время голова у меня буквально гудела после 3х суток безвылазного изучения этой темы.
Давайте пройдемся по тех. части.
Сообщение CMAS состоит из трех частей:
Код:
Шаг 1 : SIB 1
BCCH-DL-SCH-Message
message: c1 (0) // Сообщение c1, значение 0
c1: systemInformationBlockType1 (1) // Тип сообщения SIB1
systemInformationBlockType1 // Основной блок SIB1
cellAccessRelatedInfo // Информация, связанная с доступом к ячейке
plmn-IdentityList: 1 item // Список идентификаторов PLMN (1 элемент)
Item 0
PLMN-IdentityInfo // Информация об идентификаторе PLMN
plmn-Identity // Идентификатор PLMN
mcc: 3 items // Код страны (MCC), 3 элемента
Item 0
MCC-MNC-Digit: 0 // Цифра MCC, 0
Item 1
MCC-MNC-Digit: 0 // Цифра MCC, 0
Item 2
MCC-MNC-Digit: 1 // Цифра MCC, 1
mnc: 2 items // Код сети (MNC), 2 элемента
Item 0
MCC-MNC-Digit: 0 // Цифра MNC, 0
Item 1
MCC-MNC-Digit: 1 // Цифра MNC, 1
cellReservedForOperatorUse: notReserved (1) // Ячейка не зарезервирована для использования оператором
trackingAreaCode: 0000 [bit length 16, 0000 0000 0000 0000 decimal value 0] // Код области отслеживания (TA)
cellIdentity: 00000000 // Идентификатор ячейки
cellBarred: notBarred (1) // Ячейка не запрещена
intraFreqReselection: notAllowed (1) // Переход между частотами на той же ячейке не разрешен
.... ..0. csg-Indication: False // Индикатор CSG (не используется)
cellSelectionInfo // Информация о выборе ячейки
q-RxLevMin: -110dBm (-55) // Минимальное значение уровня сигнала
p-Max: 23dBm // Максимальная мощность
freqBandIndicator: 4 // Индикатор диапазона частот
schedulingInfoList: 3 items // Список информации о расписании, 3 элемента
Item 0
SchedulingInfo // Информация о расписании
si-Periodicity: rf16 (1) // Периодичность передачи SIB, 16 кадров
sib-MappingInfo: 0 items // Отсутствие информации о сопоставлении SIB
Item 1
SchedulingInfo // Информация о расписании
si-Periodicity: rf32 (2) // Периодичность передачи SIB, 32 кадра
sib-MappingInfo: 1 item // 1 элемент сопоставления SIB
Item 0
SIB-Type: sibType3 (0) // Тип SIB, тип 3
Item 2
SchedulingInfo // Информация о расписании
si-Periodicity: rf32 (2) // Периодичность передачи SIB, 32 кадра
sib-MappingInfo: 1 item // 1 элемент сопоставления SIB
Item 0
SIB-Type: sibType12-v920 (9) // Тип SIB, тип 12 версии 920
si-WindowLength: ms20 (5) // Длина окна SI
systemInfoValueTag: 0 // Тег информации о системе
nonCriticalExtension // Некритичное расширение
nonCriticalExtension // Некритичное расширение
ims-EmergencySupport-r9: true (0) // Поддержка экстренных услуг IMS
Код:
Шаг 2 : SIB 12
BCCH-DL-SCH-Message
message: c1 (0) // Сообщение c1, значение 0
c1: systemInformation (0) // Тип сообщения SIB, тип 0
systemInformation // Основной блок системы информации
criticalExtensions: systemInformation-r8 (0) // Критичные расширения информации, версия 8
systemInformation-r8 // Информация системы версии 8
sib-TypeAndInfo: 1 item // Список типов и информации SIB (1 элемент)
Item 0
sib-TypeAndInfo item: sib12-v920 (10) // Тип и информация о SIB12, версия 920
sib12-v920 // Данные для SIB12 версии 920
messageIdentifier-r9: CMAS Identifier for CMAS Presidential Level Alerts (4370) // Идентификатор сообщения CMAS для предупреждений уровня президента
serialNumber-r9: 3000 [bit length 16, 0011 0000 0000 0000 decimal value 12288] // Серийный номер
00.. .... .... .... = Geographical Scope: Display mode immediate, cell wide (0) // Географический охват: немедленное отображение на уровне ячейки
..11 0000 0000 .... = Message Code: 768 // Код сообщения
.... .... .... 0000 = Update Number: 0 // Номер обновления
warningMessageSegmentType-r9: lastSegment (1) // Тип сегмента предупреждения: последний сегмент
warningMessageSegmentNumber-r9: 0 // Номер сегмента предупреждения
warningMessageSegment-r9: 0154747a0e4acf416137a8d82ecbcf65f7388... // Сегмент предупреждения
dataCodingScheme-r9: 01 // Схема кодирования данных
0000 .... = Coding Group: Coding Group 0 // Группа кодирования: группа 0
.... 0001 = Language: English (1) // Язык: английский
Код:
Шаг 3 : Paging
PCCH-Message
message: c1 (0) // Сообщение c1, значение 0
c1: paging (0) // Тип сообщения: Paging
paging // Блок пагинга
nonCriticalExtension // Некритичное расширение
nonCriticalExtension // Некритичное расширение
cmas-Indication-r9: true (0) // Индикатор CMAS (Система оповещения для мобильных устройств)
[Expert Info (Warn/Sequence): Commercial Mobile Alert System Indication!] // Сообщение предупреждения о CMAS
[Commercial Mobile Alert System Indication!] // Уведомление о системе коммерческого мобильного оповещения
[Severity level: Warn] // Уровень серьезности: предупреждение
[Group: Sequence] // Группа: последовательность
В процессе написания кода для реализации системы CMAS я столкнулся с множеством сложностей, связанных как с теоретическими аспектами стандарта, так и с практическим применением знаний в реальной разработке. Каждая трудность стала для меня шагом к более глубокому пониманию работы с мобильными сетями и протоколами передачи данных. Но все же я пока не смог полноценно завершить эту задачу. После прочтения спецификаций 3GGP, документации Amarisoft, Matlab и LTE Toolbox, я написал код который должен передавать логику работы (синтаксис возможно не полностью идеальный). Мне будет полезно обсудить его работу и процедуры з кем то знающим, плюс это будет полезный контент для форума.Вот сам код:
C-подобный:
% Initialize LTE Toolbox configuration for TDD
enb = lteRMCDL('R.4'); % Using Reference Measurement Channel (RMC) R.4 for TDD mode
enb.TDDConfig = 1; % TDD Configuration 1
enb.SSC = 7; % Special Subframe Configuration
enb.TotSubframes = 40; % Total subframes to simulate
enb.NFrame = 0; % Initial frame number
enb.NSubframe = 0; % Initial subframe number
enb.NCellID = 17; % Physical layer cell identity
enb.CyclicPrefix = 'Normal'; % Cyclic Prefix configuration
enb.DuplexMode = 'TDD'; % Duplex mode
enb.PHICHDuration = 'Normal'; % PHICH Duration
enb.CFI = 3; % Control Format Indicator
% Initialize PDSCH configuration
enb.PDSCH.TxScheme = 'Port0'; % Transmission scheme
enb.PDSCH.Modulation = {'QPSK'}; % Modulation scheme
enb.PDSCH.RVSeq = [0 1 2 3]; % Redundancy Version sequence
enb.PDSCH.PRBSet = (0:enb.NDLRB-1)'; % Resource block allocation
% Configure SIB1
sib1 = struct();
sib1.cellAccessRelatedInfo.plmn_IdentityList = struct('PLMN-IdentityInfo', ...
struct('plmn_Identity', struct('mcc', [0 0 1], 'mnc', [0 1]), ...
'cellReservedForOperatorUse', 'notReserved'));
sib1.cellAccessRelatedInfo.trackingAreaCode = '0000000000000000'; % bit length 16
sib1.cellAccessRelatedInfo.cellIdentity = '0000000000000000000000000000'; % bit length 28
sib1.cellAccessRelatedInfo.cellBarred = 'notBarred';
sib1.cellAccessRelatedInfo.intraFreqReselection = 'notAllowed';
sib1.cellAccessRelatedInfo.csg_Indication = false;
sib1.cellSelectionInfo.q_RxLevMin = -110;
sib1.p_Max = 23;
sib1.freqBandIndicator = 4;
sib1.schedulingInfoList = struct('si_Periodicity', {'rf16', 'rf32'}, ...
'sib_MappingInfo', {{}, {'sibType12-v920'}});
sib1.si_WindowLength = 'ms20';
sib1.systemInfoValueTag = 0;
sib1.nonCriticalExtension = struct('ims_EmergencySupport_r9', true);
% Configure SIB12
sib12 = struct();
sib12.messageIdentifier_r9 = '0010001000100010'; % CMAS Identifier for Presidential Level Alerts (4370)
sib12.serialNumber_r9 = '0011000000000000'; % bit length 16, decimal value 12288
sib12.warningMessageSegmentType_r9 = 'lastSegment';
sib12.warningMessageSegmentNumber_r9 = 0;
sib12.warningMessageSegment_r9 = '0154747a0e4acf416137a8d82ecbcf65f7388...'; % Example message content
sib12.dataCodingScheme_r9 = '01'; % Coding Group 0 (Language using GSM 7 bit default alphabet), Language: English
% Configure Paging
paging = struct();
paging.cmas_Indication_r9 = true;
paging.nonCriticalExtension = struct('cmas_Indication_r9', true);
% Placeholder for ASN.1 encoding function
% Replace with actual ASN.1 encoding using an external library/tool
function encodedData = ASN1Encode(data)
% Placeholder for ASN.1 encoding
encodedData = uint8([]); % Replace with actual encoded data
end
% Custom function to generate SIB1 message
function sib1Msg = generateSIB1(sib1)
bcchMessage = struct();
bcchMessage.message = struct('c1', struct('systemInformationBlockType1', sib1));
sib1Msg = ASN1Encode(bcchMessage); % Encode SIB1 struct
end
% Custom function to generate SIB12 message
function sib12Msg = generateSIB12(sib12)
bcchMessage = struct();
bcchMessage.message = struct('c1', struct('systemInformation', struct('sibType12', sib12)));
sib12Msg = ASN1Encode(bcchMessage); % Encode SIB12 struct
end
% Custom function to generate Paging message
function pagingMsg = generatePaging(paging)
pcchMessage = struct();
pcchMessage.message = struct('c1', struct('paging', paging));
pagingMsg = ASN1Encode(pcchMessage); % Encode Paging struct
end
% Simulate the transmission of SIB1, SIB12, and Paging
txWaveform = [];
for nSubframe = 0:enb.TotSubframes-1
% Update frame and subframe numbers
enb.NSubframe = mod(nSubframe, 10);
if enb.NSubframe == 0
enb.NFrame = enb.NFrame + 1;
end
% Generate the empty resource grid for the subframe
txGrid = lteDLResourceGrid(enb);
% Generate and map PSS and SSS in specific subframes
if any(enb.NSubframe == [0, 5])
pssSymbols = ltePSS(enb);
pssIndices = ltePSSIndices(enb);
txGrid(pssIndices) = pssSymbols;
sssSymbols = lteSSS(enb);
sssIndices = lteSSSIndices(enb);
txGrid(sssIndices) = sssSymbols;
end
% Generate and transmit SIB1
if mod(enb.NFrame, 8) == 0 && enb.NSubframe == 5
sib1Msg = generateSIB1(sib1);
assert(length(sib1Msg) * 8 <= 512, 'SIB1 data exceeds allowed length.');
enb.PDSCH.PRBSet = (0:5)'; % Limited PRB for SIB1
sib1Bits = lteBCH(enb, sib1Msg); % BCH channel coding
sib1Symbols = lteDLSCH(enb, enb.PDSCH, sib1Bits); % Modulation
pdschIndices = ltePDSCHIndices(enb, enb.PDSCH, enb.PDSCH.PRBSet);
txGrid(pdschIndices) = sib1Symbols;
end
% Generate and transmit SIB12
if mod(enb.NFrame, 32) == 0 && enb.NSubframe == 5
sib12Msg = generateSIB12(sib12);
assert(length(sib12Msg) * 8 <= 512, 'SIB12 data exceeds allowed length.');
enb.PDSCH.PRBSet = (0:5)'; % Limited PRB for SIB12
sib12Bits = lteBCH(enb, sib12Msg); % BCH channel coding
sib12Symbols = lteDLSCH(enb, enb.PDSCH, sib12Bits); % Modulation
pdschIndices = ltePDSCHIndices(enb, enb.PDSCH, enb.PDSCH.PRBSet);
txGrid(pdschIndices) = sib12Symbols;
end
% Generate and transmit Paging
if mod(enb.NFrame, 4) == 0
pagingMsg = generatePaging(paging);
assert(length(pagingMsg) * 8 <= 512, 'Paging data exceeds allowed length.');
enb.PDSCH.PRBSet = (0:5)'; % Limited PRB for Paging
pagingBits = lteBCH(enb, pagingMsg); % BCH channel coding
pagingSymbols = lteDLSCH(enb, enb.PDSCH, pagingBits); % Modulation
pdschIndices = ltePDSCHIndices(enb, enb.PDSCH, enb.PDSCH.PRBSet);
txGrid(pdschIndices) = pagingSymbols;
end
% OFDM modulation
subframeWaveform = lteOFDMModulate(enb, txGrid);
txWaveform = [txWaveform; subframeWaveform];
end
% Convert the I/Q stream to int16 format
scaledTxWaveform = int16(txWaveform * 32767);
% Export the I/Q stream to a binary file in int16 format
fileID = fopen('lte_iq_stream.bin', 'w');
fwrite(fileID, [real(scaledTxWaveform) imag(scaledTxWaveform)]', 'int16');
fclose(fileID);
disp('I/Q stream has been exported to lte_iq_stream.bin in int16 format.');
На данный момент у меня встали несколько вопросов.
Как правильно внедрить схемы ASN1 в код в матлабе что бы их можно было правильно кодировать?
Где взять полноценные файлы .asn кроме текстовых вставок из спецификаций 3GGP?
Имеет ли смысл работать в TDD если для реализации сигнала не важно какой режим выбран?
В моей голове самый оптимальный вариант это скомпилировать ASN1 структуры в бинарный формат а потом его вплетать в LTE фрейм. Возможно я выбрал не тот подход и всю эту задачу можно гораздо проще осуществить, буду рад любым коментариям и любому техническому обсуждению.