From f11a6a62e65a2e00d1705b3d299e8e1b65a15d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Wed, 19 Aug 2026 02:00:25 +0300 Subject: [PATCH] Fix IMSI decode: drop TS 24.008 type+parity nibble --- simtrace2_pysniff/server/decode.py | 4 ++++ tests/test_decode.py | 19 +++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/simtrace2_pysniff/server/decode.py b/simtrace2_pysniff/server/decode.py index 0e5ce03..7bbb134 100644 --- a/simtrace2_pysniff/server/decode.py +++ b/simtrace2_pysniff/server/decode.py @@ -2325,6 +2325,10 @@ def _decode_imsi(raw, p1=None): if len(raw) <= 2: # 6F07 is also the ISIM Service Table (IST) return _decode_service_table(raw, IST_SERVICES) digits = _swap_nibbles(raw[1:].hex()).rstrip('fF') + # First nibble is the mobile-identity type (001) + parity indicator + # (TS 24.008), not an IMSI digit. + if digits: + digits = digits[1:] return {'imsi': digits or None} diff --git a/tests/test_decode.py b/tests/test_decode.py index ebc35da..23a17cb 100644 --- a/tests/test_decode.py +++ b/tests/test_decode.py @@ -961,9 +961,16 @@ class TestSelectPath(unittest.TestCase): class TestFileDecoders(unittest.TestCase): def test_imsi(self): from simtrace2_pysniff.server.decode import _decode_file_data - f = _decode_file_data('6f07', bytes.fromhex('0f52001132547698f0')) + f = _decode_file_data('6f07', bytes.fromhex('082905102143658709')) self.assertEqual(f['imsi'], '250011234567890') + def test_imsi_real_card(self): + # Real capture (Mi A1): 08 length byte + 8 bytes, first nibble is the + # TS 24.008 type+parity indicator (9 = IMSI, odd). + from simtrace2_pysniff.server.decode import _decode_file_data + f = _decode_file_data('6f07', bytes.fromhex('082905917700917259')) + self.assertEqual(f['imsi'], '250197700192795') + def test_iccid(self): from simtrace2_pysniff.server.decode import _decode_file_data f = _decode_file_data('2fe2', bytes.fromhex('98891020000000460012')) @@ -1090,14 +1097,14 @@ class TestFileDecoders(unittest.TestCase): def test_read_binary_direct(self): # SELECT EF_IMSI then READ BINARY → file decoded in body. r = decode_message(bytes.fromhex('00b0000009') + - bytes.fromhex('0f52001132547698f0') + bytes.fromhex('9000'), + bytes.fromhex('082905102143658709') + bytes.fromhex('9000'), prev={'sel': {'fid': '6f07', 'name': 'EF_IMSI'}}) self.assertEqual(r['file']['imsi'], '250011234567890') self.assertIn('IMSI 250011234567890', r['summary']) def test_read_binary_offset_skip(self): r = decode_message(bytes.fromhex('00b00100') + - bytes.fromhex('0f52001132547698f0') + bytes.fromhex('9000'), + bytes.fromhex('082905102143658709') + bytes.fromhex('9000'), prev={'sel': {'fid': '6f07'}}) self.assertNotIn('file', r) @@ -1163,7 +1170,7 @@ class TestSelectionTracking(unittest.TestCase): db.insert_message(sid, 0.0, 'atr', b'\x3b\x00') db.insert_message(sid, 0.1, 'tpdu', bytes.fromhex('a0a40804047fff6f079000')) db.insert_message(sid, 0.2, 'tpdu', - bytes.fromhex('00b0000009') + bytes.fromhex('0f52001132547698f0') + bytes.fromhex('9000')) + bytes.fromhex('00b0000009') + bytes.fromhex('082905102143658709') + bytes.fromhex('9000')) msgs = db.get_messages(sid) read = msgs[2] self.assertEqual(read['decoded']['file']['imsi'], '250011234567890') @@ -1177,7 +1184,7 @@ class TestSelectionTracking(unittest.TestCase): db.insert_message(sid, 0.0, 'tpdu', bytes.fromhex('a0a40804047fff6f079000')) db.insert_message(sid, 0.1, 'atr', b'\x3b\x00') db.insert_message(sid, 0.2, 'tpdu', - bytes.fromhex('00b0000009') + bytes.fromhex('0f52001132547698f0') + bytes.fromhex('9000')) + bytes.fromhex('00b0000009') + bytes.fromhex('082905102143658709') + bytes.fromhex('9000')) msgs = db.get_messages(sid) self.assertNotIn('file', msgs[2]['decoded']) @@ -1191,7 +1198,7 @@ class TestSelectionTracking(unittest.TestCase): db.insert_message(sid, 0.0, 'tpdu', bytes.fromhex('a0a40804047fff6f079000')) db.insert_message(sid, 0.1, 'tpdu', bytes.fromhex('a0a40804047fff6f136a82')) db.insert_message(sid, 0.2, 'tpdu', - bytes.fromhex('00b0000009') + bytes.fromhex('0f52001132547698f0') + bytes.fromhex('9000')) + bytes.fromhex('00b0000009') + bytes.fromhex('082905102143658709') + bytes.fromhex('9000')) msgs = db.get_messages(sid) read = msgs[2] self.assertEqual(read['decoded']['file']['imsi'], '250011234567890')