背景
最近遇到一个极其小众的需求:罗森电子票ローチケApp(安卓)需要读取SIM卡的“本机电话号码”来发送验证码,但手里的日本电话卡未配置本机号码(显示为未知/Unknown)。又因为是预付费卡,无法联系运营商下发更新卡片配置信息。
既然本机号码是可以由运营商更改的(例如povo2),那就存在手动修改的可能。调查下来发现两种途径可以自己修改:
方案一
使用xposed/lsposed模块SIMNumberSetter。
应当是最简单有效的办法,但兼容性存疑,特别是博主提到对小米的设备支持不佳。测试下来手上的三台小米备用机均无法使用,作罢。朋友帮忙测试了索尼的设备,可以打开插件,但不确定是否可以写卡。
方案二
使用高通的MODEM
接口,发送AT指令调试SIM卡模块。此方法参考了@新垣平的文章:修改SIM卡的“本机号码”。
AT 指的是 AT指令集,也叫做 Hayes命令集,是一种用于控制调制解调器(modem)和通信设备的标准命令集。AT 指令以 “AT”(Attention)开头,后面跟随具体的命令内容,设备接收到这些指令后会返回响应。(ChatGPT)
此篇博客中提到9091
模式下,电脑上会多出两个串口设备,其中之一是MODEM
。实际测试下来,查到资料似乎是使用以下的adb
命令开放9091
端口
adb shell
su
setprop sys.usb.config diag,diag_mdm,diag_mdm2,qdss,qdss_mdm,serial_cdev,dpl,rmnet,adb
# 或者
setprop sys.usb.config rndis,diag,diag_mdm,diag_mdm2,qdss,qdss_mdm,serial_cdev,dpl
但是或许是因为未正确配置驱动,adb shell
中执行此命令后,手机插上电脑无反应(也没有检测到adb设备,所以应该是切换了通讯模式)。关开开发者选项中的adb调试
开关即可恢复普通adb状态。
于是又尝试直接从adb shell
中监听modem端口,通过安卓的/dev/smd7
设备文件访问调制解调器。
需要开启两个终端,都进入adb shell
,其中一个用来给smd7
发送指令,一个监听返回内容。
监听:
adb shell
su
cat /dev/smd7
发送指令:
adb shell
su
echo -r "at\r" > /dev/smd7
如果配置正确,会显示OK
。
> at
OK
此时可以尝试发送读取SIM卡卡号的指令
> at+crsm=178,28480,1,4,28
+CRSM: 144,0,"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
OK
其中,返回值144
为成功,其它(例如103
)为失败代码。
使用以下指令写号码
> at+crsm=220,28480,1,4,28,"FFFFFFFFFFFFFFFFFFFFFFFFFFFF0891181111111165FFFFFFFFFFFF"
+CRSM: 144,0,""
OK
注意,写号码指令中包含一堆引号,在使用echo
传入命令时,务必使用如下的转义符
echo -e "at+crsm=220,28480,1,4,28,\"FFFFFFFFFFFFFFFFFFFFFFFFFFFF0891181111111165FFFFFFFFFFFF\"\r" > /dev/smd7
此处的28字节(56个16进制数字)MSISDN的含义可参考文章中的介绍。简而言之,上面字符串中的0891181111111165FF
,即为电话号码:
08
:此后8字节(16个数字)有效91
:代表国际前缀+
- 此后到
FF
前的数字均按照每对数字反转并填充的原则,例如,1234即反转为2143。最终读到F
,表示号码结束。
(图片来自3GPP手册)
写卡结果
小范围测试发现,爱尔兰48的电话卡可读不可写,中国移动可读可写,JOYTEL可读可写,Rakuten不可读不可写。
尾声
因为日本卡无法写号,最终的方案是给台湾卡(主卡)写了日本的号码以欺骗ローチケ读取到日本号码,同时在双卡手机上用日本卡(副卡)收验证短信。