用Xposed框架拦截Android操作系统的短信接收
来源:互联网 发布:淘宝卖家怎么添加客服 编辑:程序博客网 时间:2024/06/05 04:50
短信接收原理
关于Android操作系统短信的接收和发送流程的文章网上有一大堆,但是真正说得很清楚的不多,这篇blog写得不错。其实要想真正弄懂Android操作系统短信的流程,还是Linus的那句话: Read the fucking source code.呵呵
在Android操作系统中,大部分敏感信息的传递过程都是基于binder机制的,当然SMS也不例外。对于SMS的接收流程的描述从Framework层和Application层这两个层面进行介绍。
- Framework层
当短信到达Framework层后,会首先启动RIL中的RILReceiver去接收短信,在RILReceiver中使用LocalSocket去读短信,然后把读到的短信放在一个Parcel对象中,然后调用processResponse(Parcel p)去处理,processResponse()中调用processUnsolicited(Parcel p)处理。
Android操作系统对应的源码如下:
class RILReceiver implements Runnable { byte[] buffer; RILReceiver() { buffer = new byte[RIL_MAX_COMMAND_BYTES]; } @Override public void run() { int retryCount = 0; try {for (;;) { LocalSocket s = null; LocalSocketAddress l; try { s = new LocalSocket(); l = new LocalSocketAddress(SOCKET_NAME_RIL, LocalSocketAddress.Namespace.RESERVED); s.connect(l); } catch (IOException ex){ try { if (s != null) { s.close(); } } catch (IOException ex2) { //ignore failure to close after failure to connect } // don't print an error message after the the first time // or after the 8th time if (retryCount == 8) { Rlog.e (RILJ_LOG_TAG, "Couldn't find '" + SOCKET_NAME_RIL + "' socket after " + retryCount + " times, continuing to retry silently"); } else if (retryCount > 0 && retryCount < 8) { Rlog.i (RILJ_LOG_TAG, "Couldn't find '" + SOCKET_NAME_RIL + "' socket; retrying after timeout"); } try { Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); } catch (InterruptedException er) { } retryCount++; continue; } retryCount = 0; mSocket = s; Rlog.i(RILJ_LOG_TAG, "Connected to '" + SOCKET_NAME_RIL + "' socket"); int length = 0; try { InputStream is = mSocket.getInputStream(); for (;;) { Parcel p; length = readRilMessage(is, buffer); if (length < 0) { // End-of-stream reached break; } p = Parcel.obtain(); p.unmarshall(buffer, 0, length); p.setDataPosition(0); //Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes"); processResponse(p); p.recycle(); } } catch (java.io.IOException ex) { Rlog.i(RILJ_LOG_TAG, "'" + SOCKET_NAME_RIL + "' socket closed", ex); } catch (Throwable tr) { Rlog.e(RILJ_LOG_TAG, "Uncaught exception read length=" + length + "Exception:" + tr.toString()); } Rlog.i(RILJ_LOG_TAG, "Disconnected from '" + SOCKET_NAME_RIL + "' socket"); setRadioState (RadioState.RADIO_UNAVAILABLE); try { mSocket.close(); } catch (IOException ex) { } mSocket = null; RILRequest.resetSerial(); // Clear request list on close clearRequestList(RADIO_NOT_AVAILABLE, false); }} catch (Throwable tr) { Rlog.e(RILJ_LOG_TAG,"Uncaught exception", tr); } /* We're disconnected so we don't know the ril version */ notifyRegistrantsRilConnectionChanged(-1); } }
- Application层
在App层,PrivilegedSmsReceiver在接收到短信来了的广播之后,由SmsReceiver启动SmsReceiverService来做具体的处理。接收短信的action为SMS_RECEIVED_ACTION,所以调用handleSmsReceived()处理,使用insertMessage()将短信插入数据库,这里首先会判断短信是否为CLASS_0短信,如果是则直接显示,不插入数据库。如果不是则会进行消息的替换或者插入数据库,替换使用了SmsMessaged的isReplace()方法判断,原则是短信协议标识mProtocolIdentifier的判断。如果既不是CLASS_0短信也不需要替换,则将短信插入数据库,然后使用MessagingNotification在StatusBar做一个notification,通知用户短信来了。这里就不附上Android操作系统的相关代码了,感兴趣的,可以自己在Grepcode或者AndroidXRef上自己查看。
编码实现
上面已经弄清楚原理了,研究Android操作系统对应部分的源码,不难找出相应的解决方案。这里选择一种比较简单的hook,用xposed框架进行拦截。当然也是经过多次失败尝试后找到的一种比较有效的方法。思路很简单,就是针对短信接收流程中调用的函数,拦截该函数,获取接收端的信息流,对信息流进行按位异或处理。下面给出核心部分的源码:
package com.example.receiver;import de.robv.android.xposed.IXposedHookLoadPackage;import de.robv.android.xposed.XC_MethodHook;import de.robv.android.xposed.XposedBridge;import de.robv.android.xposed.XposedHelpers;import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;/** * @author Li Jiansong * @date:2015-7-27 上午11:15:48 * @version : * *Server端短信接收端的拦截,经过多次尝试,最终有效的是下面的方案 *拦截SmsMessage的内部类PduParser的getUserDataUCS2方法,该方法返回类型为String *String getUserDataUCS2(int byteCount) * */public class RecvHooker implements IXposedHookLoadPackage{ private static final String TARGET_PACKAGE = "com.android.mms"; @Override public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { // TODO Auto-generated method stub //XposedBridge.log("--------loaded app:"+lpparam.packageName);// if(!lpparam.packageName.equals("com.android.mms"))// return; if (!TARGET_PACKAGE.equals(lpparam.packageName)) { // XposedBridge.log("SendRawSMSMod: ignoring package: " + // lpparam.packageName); return; }// /**// * 拦截SmsMessage的内部类PduParser的getUserData方法,// * byte[] getUserData(){}// * 该方法不带参数// */// final Class<?> recvClazz=XposedHelpers.findClass("com.android.internal.telephony.gsm"// +".SmsMessage$PduParser",lpparam.classLoader);// // XposedBridge.log("==========开始进入拦截----");// // XposedHelpers.findAndHookMethod(recvClazz, "getUserData",// new XC_MethodHook(){// // @Override// protected void afterHookedMethod(MethodHookParam param)// throws Throwable {// // TODO Auto-generated method stub// //super.beforeHookedMethod(param);// // XposedBridge.log("=========getUserData被调用");// byte[] recvByteSms=(byte[]) param.getResult();// String strRecvSms="";// strRecvSms+=new String(recvByteSms);// // //byte[] srtbyte = strRecvSms.getBytes();// //String lsx="6666666666666666666666666666666666";// param.setResult(strRecvSms.getBytes());// //SmsMessage msg=new SmsMessage();// // XposedBridge.log("========接收的短信内容为:"+strRecvSms);// return;// }// // // }); //XposedBridge.log("-------开始拦截");// findAndHookMethod("com.android.internal.telephony.gsm.SmsMessage",lpparam.classLoader,// "getSubmitPdu",String.class,// String.class, String.class, boolean.class, byte[].class,// int.class, int.class, int.class, new XC_MethodHook(){// // /**// * 拦截SmsMessage的getSubmitPdu方法,其有5个参数// * String scAddress,// * String destinationAddress, // * String message,// * boolean statusReportRequested, // * byte[] header// * // */// // /**// * Get an SMS-SUBMIT PDU for a destination address and a message// *// * @param scAddress Service Centre address. Null means use default.// * @return a <code>SubmitPdu</code> containing the encoded SC// * address, if applicable, and the encoded message.// * Returns null on encode error.// */// @Override// protected void beforeHookedMethod(MethodHookParam param)// throws Throwable {// // TODO Auto-generated method stub// // super.beforeHookedMethod(param);// XposedBridge.log("getSubmitPdu被调用");// if(param.args[2]==null){// return;// }// String message=(String) param.args[2];// XposedBridge.log("======before:SMS message:"+message);// SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// message+=df.format(new Date());// XposedBridge.log("========after SMS message:"+message);// SubmitPdu rawPdu=new SubmitPdu();// //StringTokenizer stringTokenizer=new StringTokenizer(string, delimiters, returnDelimiters)// param.setResult(rawPdu);// XposedBridge.log("=============hook替换成功");// // return;// // }// });// final Class<?> recvClazz=XposedHelpers.findClass("com.android.internal.telephony.gsm"// +".SmsMessage$PduParser",lpparam.classLoader); XposedBridge.log("=========开始进入拦截"); XposedHelpers.findAndHookMethod("com.android.internal.telephony.gsm"+".SmsMessage$PduParser", lpparam.classLoader,"getUserDataUCS2",int.class, new XC_MethodHook(){ /** * Interprets the user data payload as UCS2 characters, and * decodes them into a String. * * @param byteCount the number of bytes in the user data payload * @return a String with the decoded characters */ /** * 拦截SmsMessage的内部类PduParser的getUserDataUCS2方法,该方法返回类型为String * String getUserDataUCS2(int byteCount) * */ @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { // TODO Auto-generated method stub // super.afterHookedMethod(param); try { String strMms=(String) param.getResult(); XposedBridge.log("=========before:"+strMms); //String after="666666666666666"; char[] recvArray=strMms.toCharArray(); for(int i=0;i<recvArray.length;i++){ recvArray[i]=(char) (recvArray[i]^20000); } String enCodeSms=new String(recvArray); param.setResult(enCodeSms); XposedBridge.log("=========after:"+param.getResult()); //return; } catch (Exception e) { // TODO Auto-generated catch block //e.printStackTrace(); XposedBridge.log(e); } } }); }}
测试
下面给出一个测试例子,向10086发送一条短信,10086自动给出回应信息。由于回应的信息被拦截处理了,所以显示的是乱码。从后台的日志可以看出完整的原来正常的短信信息。
1 0
- 用Xposed框架拦截Android操作系统的短信接收
- 用Xposed框架拦截Android操作系统的短信接收
- 基于xposed的短信拦截
- Android-拦截接收短信
- Android-拦截接收短信
- Android拦截短信,接收短信
- Xposed实现短信拦截
- Android中短信的收发机制 发送短信 接收短信 拦截短信 监听短信
- Android广播机制—拦截接收短信
- Android中Xposed框架篇---利用Xposed框架实现拦截系统方法
- Android中Xposed框架篇---利用Xposed框架实现拦截系统方法
- Android中Xposed框架篇-利用Xposed框架实现拦截系统方法
- Android中Xposed框架篇---利用Xposed框架实现拦截系统方法
- android 短信的接收!
- android 短信接收流程分析——为更好的拦截短信做准备
- android 短信接收流程分析——为更好的拦截短信做准备
- 短信接收拦截
- 用Xposed框架拦截微信、人人、QQ等LBS应用的当前位置
- Plus One
- 二叉排序树 SDUTOJ 2482
- iOS开发的一些奇巧淫技
- iOS开发-优秀博客-实用技巧
- 获取JNIEnv的方法
- 用Xposed框架拦截Android操作系统的短信接收
- 【LruCache完全解析】Android高效加载大图、多图解决方案,有效避免程序OOM (AdapterView使用LruCache图片缓存)
- python发送请求两种代理设置方式
- NYOJ~懒省事的小明
- codevs1064
- hdoj1753大明A+B
- 用Xposed框架拦截Android操作系统的短信接收
- HDU 1347 Grandpa is Famous
- MySQL操作监控