在过去的几个月中,我一直研究Android的底层的GSM API。数年前API函数SendRawPdu还能使用,它允许开发者在将其发送给GSM基带之前,自己在较低的层次对SMS消息进行编码,相当多的能发送各种奇怪的sms(flash sms,slient sms,等等)的应用得以诞生。
不幸的是,google决定去掉该api,尚不清楚google是出于安全考虑还是出于重构其IPC IBinder 机制才这样做的。但实际就是,除非你使用一些老的手机或者固件(在大多数设备上,为了给GSM modem发送AT命令,他们都移除了ttyUSB串行接口), 否则现在就不能使用该Api函数了。
直到数月之前,我发现了API函数 SmsManager.sendDataMessage,显然该函数并没有在其他任何地方使用过(如果你查找 它,只能找到少数的几个例子,但没有涉及怎么用自己编码的PDU数据使用该函数)。使用该API函数,我们能够自己编码我们的SMS,而且我们能够指定其 中的“port”参数(该参数能标识我们发送的sms的类型)。本文讨论的port是2948,也就是发送WAP PUSH 通知的端口。
WAP PUSH消息是一种以前就有的机制,它主要用于强制远程设备访问SMS负载中编码了的URL,这个特殊的请求被称为“Service Load”(SL)请求,该请求中一个类似如下的XML负载被编码在二进制form中,和PDU一起发送给设备。
1
2
3
4
|
<?xml version=“1.0″?>
<!DOCTYPE sl PUBLIC “-//WAPFORUM//DTD SL 1.0//EN”
“www.wapforum.org/DTD/sl.dtd”>
<sl href=“http://some-evil-site.com/evil-content.html”/>
|
如今,该协议由于显然的原因没有被处理(之所以说是不处理,而不是不支持,是因为GSM基带任然能够收到它,只是上层软件–os及其组件,不对其进行处理)。例如Android 5.0中,当设备收到这样的负载时,能看到下面的日志(logcat –b radio)
1
2
3
4
5
6
7
8
9
|
D/WAP PUSH( 1287): Rx: 0a0603…
D/RILC ( 185): SOCKET RIL_SOCKET_1 REQUEST: SMS_ACKNOWLEDGE length:20
D/RILC ( 185): RequestComplete, RIL_SOCKET_1
E/RILC ( 185): Send Response to RIL_SOCKET_1
D/RILJ ( 1287): [9277]< SMS_ACKNOWLEDGE [SUB0]
V/WAP PUSH( 1287): appid found: 2:application/vnd.wap.slc
W/WAP PUSH( 1287): wap push manager not found!
V/WAP PUSH( 1287): fall back to existing handler
V/WAP PUSH( 1287): Delivering MMS to: com.google.android.talk com.google.android.apps.hangouts.sms.MmsWapPushDeliverReceiver
|
因此事件传递给了Google Hangouts应用(作者手机上默认处理SMS/MMS的处理者),如果不是简单的MMS而是其他的(本例中为WAP PUSH),则它会忽略这种类型的负载。
1
2
3
4
5
6
7
8
|
public class MmsWapPushDeliverReceiver extends BroadcastReceiver
{
public void onReceive(Context paramContext, Intent paramIntent)
{
if ((“android.provider.Telephony.WAP_PUSH_DELIVER”.equals(paramIntent.getAction())) && (“application/vnd.wap.mms-message”.equals(paramIntent.getType())))
RealTimeChatService.a(paramIntent.getByteArrayExtra(“data”));
}
}
|
这也就意味着,虽然设备收到了数据,对用户却没有任何提示,数据也不会被系统保存,而是直接丢弃掉。
有个细节对我们来说是很方便的—在传送了WAP PUSH消息后,接收方的BTS会回复我们一个传送端口。仅仅当接收方设备是开着的,并且能接收到该消息时(有足够的GSM网络型号覆盖),我们才会收到 该回复。事实上,API函数sendDataMessage 将其最后一个参数作为传送的PendingIntent.换言之,一旦delivery report返回,我们的应用就会收到通知。
我们可以利用这个做到以下几点:
1
2
3
4
|
①构造一个WAP PUSH消息,并自己编码;
②将其传递给sendDataMessage API,并注册一个delivery intent;
③WAP PUSH会发送到目标手机上,如果目标手机是开着的,我们就会收到通知。如果目标手机是关机的,只要它一开,我们也会收到通知;
④目标对象不会有任何察觉
|
因此,我们可以追踪目标对象的GSM网络活动,知道其设备什么时候是开着的,而又不让其察觉。
一个简单的POC程序
https://github.com/evilsocket/pdusms
[via@living]
Copyright © hongdaChiaki. All Rights Reserved. 鸿大千秋 版权所有
联系方式:
地址: 深圳市南山区招商街道沿山社区沿山路43号创业壹号大楼A栋107室
邮箱:service@hongdaqianqiu.com
备案号:粤ICP备15078875号