一张SIM卡里到底装了什么?用Wireshark抓包和Python脚本,带你解密USIM的文件系统
·
深入探索USIM卡文件系统:从APDU指令到Python解析实战
当你把手机卡插入设备时,这个指甲盖大小的芯片内部正在运行一个完整的微型数据库系统。作为移动通信的身份凭证,USIM卡远比普通用户想象的复杂——它包含超过200种结构化文件,存储着从基本身份信息到网络配置参数的各类数据。本文将带你用技术手段揭开这层神秘面纱。
1. USIM卡通信基础:APDU协议与文件系统架构
USIM卡本质上是一个符合ISO/IEC 7816标准的智能卡,其核心通信协议是 应用协议数据单元 (APDU)。这种指令-响应模式的交互,构成了我们与卡内文件系统对话的基础语言。
典型的APDU指令结构如下:
# SELECT命令示例
CLA = 0xA0 # 指令类
INS = 0xA4 # 指令码(SELECT)
P1 = 0x00 # 参数1(选择文件)
P2 = 0x00 # 参数2(返回FCP模板)
Lc = 0x02 # 数据长度
Data = [0x3F, 0x00] # 主目录MF的标识符
卡内文件系统采用树状结构组织:
- MF (Master File):根目录,固定标识符3F00
- ADF (Application DF):应用专属目录(如USIM ADF)
- EF (Elementary File):实际数据文件
关键入口文件 EFDIR 记录了所有应用的AID(应用标识符),相当于系统的"目录表"。读取流程如下:
- 发送SELECT EFDIR指令
- 解析响应获取record结构和数量
- 遍历record查找目标AID
- 用AID激活对应应用
2. 核心文件解析实战:IMSI与网络列表
2.1 EFIMSI:国际移动用户标识
IMSI是用户在全球移动网络中的唯一身份证,其二进制结构解析示例:
def parse_imsi(raw_data):
# 第一个字节包含长度和编码指示
length = raw_data[0] & 0x0F
digits = []
# 后续每字节存储两个BCD数字
for byte in raw_data[1:1+length]:
digits.append(str(byte & 0x0F))
digits.append(str((byte >> 4) & 0x0F))
# 去除填充位并组合
imsi = ''.join(digits[:length*2-1])
return {
'MCC': imsi[:3],
'MNC': imsi[3:5] if len(imsi[3:5]) == 2 else imsi[3:6],
'MSIN': imsi[5:]
}
典型响应数据解析对照表:
| 字节位置 | 值(Hex) | 含义 |
|---|---|---|
| 0 | 08 | IMSI长度8字节 |
| 1 | 09 | 数字9和0(倒序) |
| 2 | 21 | 数字1和2 |
| 3 | 43 | 数字3和4 |
| 4-8 | ... | 后续MSIN部分 |
2.2 EFFPLMN:禁用网络列表
运营商通过此文件阻止设备接入异常网络,其记录格式解析要点:
- 每个PLMN占3字节:MCC(2字节)+MNC(1字节)
- 列表以FF FF FF标记结束
- 状态字节指示禁止原因(0x00=常规禁止)
使用Wireshark捕获的典型APDU交换流程:
# 请求
>> A0 A4 00 00 02 6F 7B
<< 9F 0F # 返回文件大小
>> A0 B0 00 00 0F
<< 01 02 03 04 05 06 FF FF FF 90 00 # 实际数据+状态字
3. 高级文件操作与安全机制
3.1 文件访问权限控制
USIM采用三级安全机制保护敏感文件:
- ALW (Always):无需认证
- PIN :需要用户输入PIN码
- ADM :运营商级密钥控制
常见权限组合示例:
| 文件 | 读权限 | 更新权限 |
|---|---|---|
| EFIMSI | PIN | ADM |
| EFFPLMN | ALW | ADM |
| EFKEYS | ADM | ADM |
3.2 二进制解析技巧
处理TLV(标签-长度-值)格式文件的Python示例:
def parse_tlv(data):
result = {}
while len(data) > 2:
tag = data[0]
length = data[1]
value = data[2:2+length]
result[tag] = value
data = data[2+length:]
return result
# 解析EFLOCI(位置信息)
raw = bytes.fromhex('06 04 12 34 56 78 07 01 01')
print(parse_tlv(raw)) # 输出: {6: b'\x124Vx', 7: b'\x01'}
4. 构建自动化诊断工具
结合PySIM库实现批量文件读取的完整示例:
from pysim import sim
def dump_usim_files(card):
essential_files = {
'IMSI': '6F07',
'PLMNwAcT': '6F60',
'FPLMN': '6F7B',
'AD': '6FAD'
}
results = {}
for name, fid in essential_files.items():
try:
data = card.read_binary(fid)
results[name] = parse_file(name, data)
except Exception as e:
print(f"读取{fid}失败: {str(e)}")
return results
# 实际使用
with sim.Reader() as reader:
card = reader.connect()
print(dump_usim_files(card))
典型输出结构:
{
"IMSI": {
"MCC": "460",
"MNC": "01",
"MSIN": "123456789"
},
"FPLMN": [
{"MCC": "001", "MNC": "01"},
{"MCC": "310", "MNC": "260"}
]
}
在真实项目中,这类工具可以帮助快速诊断SIM卡配置问题。曾遇到一个案例:用户在国际漫游时无法注册网络,最终通过脚本比对发现是EFFPLMN列表中意外包含了当地合法运营商的PLMN代码。
更多推荐
所有评论(0)