大家好,最近在做关于RIL短信发送的项目,遇到一些难点,希望大家帮忙解决一下难题。
首先以单条手机短信的发送为例,流程如下:
-> SmsManager.getDefault().sendTextMessage()
-> 经过IBinder接口到IccSmsInterfaceManagerProxy
-> 具体实现在IccSmsInterfaceManager执行方法为sendtext()
-> 再经过SMSDispatcher.java,辗转到RIL.java的sendSMS(GSM短信)和sendCdmaSms(CDMA短信)两个方法负责最后的加工。
-> 最后由RIL的native层通过LOCAL_SOCKET发送出去。
而查看RIL.JAVA的源码SOCKET_NAME_RIL = "rild",所以我的方法就是,通过反射模仿短信BINDER服务端部分的信息加工过程,最后建立一个LOCAL_SOCKET连接,将信息发送出去。
首先经过测试,我可以通过LocalSocket连接到rild。所以我可以开始利用反射来模仿短信数据的打包过程,我尽量用的都是原来的消息结构体如:RILRequest。
最终短信还是没能发送出去,我的机器是双卡双待的,代码如下:
执行sendsms(mContext);发送短信
static class RILSender extends Handler implements Runnable {
public RILSender(Looper looper) {
super(looper);
}
// ***** Runnable implementation
@Override
public void run() {
// setup if needed
}
// ***** Handler implementation
@Override
public void handleMessage(Message msg) {
SysLog.logW(TAG, "[+]RILSender MSG = "+msg.what);
}
}
public static boolean sendsms(Context context) {
String destAddr = "13078950351";
String text = "短信内容";
PendingIntent sentIntent = null;
PendingIntent deliveryIntent = null;
// SmsManager smsm = SmsManager.getDefault();
String scAddr = "";// 获取服务中心号码
SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddr, destAddr,
text, (deliveryIntent != null));
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("smsc", pdus.encodedScAddress);
map.put("pdu", pdus.encodedMessage);
byte smsc[] = (byte[]) map.get("smsc");
byte pdu[] = (byte[]) map.get("pdu");
// 获取话机类型gsm或者cdma
TelephonyManager tm = new TelephonyManager(context);
tm.getPhoneType();
TelephonyManager telMag = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
Class<TelephonyManager> c = TelephonyManager.class;
Method mthEndCall = null;
int phoneType = 0;
try {
mthEndCall = c.getDeclaredMethod("getPhoneType", (Class[]) null);
mthEndCall.setAccessible(true);
phoneType = Integer.parseInt(String.valueOf(mthEndCall.invoke(
telMag, (Object[]) null)));
} catch (Exception e) {
e.printStackTrace();
return false;
}
if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
SysLog.logW(TAG, "[+]PHONE_TYPE_GSM");
// String str_smsc = IccUtils.bytesToHexString(smsc);
// String str_pdu = IccUtils.bytesToHexString(pdu);
String str_smsc = null;
String str_pdu = null;
HRef href = new HRef();
if (!href.setClass("com.android.internal.telephony.uicc.IccUtils")) {
return false;
}
try {
Object obj_smsc = href.invokeMethod("bytesToHexString", smsc);
Object obj_pdu = href.invokeMethod("bytesToHexString", pdu);
str_smsc = String.valueOf(obj_smsc);
str_pdu = String.valueOf(obj_pdu);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
Message msg = mSender.obtainMessage(
RILConstants.RIL_REQUEST_SEND_SMS, new Object());
sendGsmSms(str_smsc, str_pdu, msg);
} else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
SysLog.logW(TAG, "[+]PHONE_TYPE_CDMA");
Message msg = mSender.obtainMessage(
RILConstants.RIL_REQUEST_CDMA_SEND_SMS, new Object());
sendCdmaSms(pdu, msg);
}
return true;
}
private static boolean sendGsmSms(String smscPDU, String pdu, Message result) {
HRef href = new HRef();
if (!href.setClass("com.android.internal.telephony.RILRequest")) {
SysLog.logW(TAG,
"[+]cannot find com.android.internal.telephony.RILRequest");
return false;
}
Object rr = null;
try {
rr = href.invokeMethod("obtain", RILConstants.RIL_REQUEST_SEND_SMS,
result);
Object mParcel = href.getObject(rr, "mParcel");
href.invokeMethod(mParcel, "writeInt", true, 2);
href.invokeMethod(mParcel, "writeString", true, smscPDU);
href.invokeMethod(mParcel, "writeString", true, pdu);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// RILRequest rr = RILRequest.obtain(RILConstants.RIL_REQUEST_SEND_SMS,
// result);
// rr.mParcel.writeInt(2);
// rr.mParcel.writeString(smscPDU);
// rr.mParcel.writeString(pdu);
return send(rr);
}
private static boolean sendCdmaSms(byte[] pdu, Message result) {
int address_nbr_of_digits;
int subaddr_nbr_of_digits;
int bearerDataLength;
ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
DataInputStream dis = new DataInputStream(bais);
HRef href = new HRef();
if (!href.setClass("com.android.internal.telephony.RILRequest")) {
return false;
}
Object rr = null;
try {
rr = href.invokeMethod("obtain",
RILConstants.RIL_REQUEST_CDMA_SEND_SMS, result);
Object mParcel = href.getObject(rr, "mParcel");
// teleServiceId
href.invokeMethod(mParcel, "writeInt", true, dis.readInt());
// servicePresent
href.invokeMethod(mParcel, "writeByte", true, (byte) dis.readInt());
// serviceCategory
href.invokeMethod(mParcel, "writeInt", true, dis.readInt());
// address_digit_mode
href.invokeMethod(mParcel, "writeInt", true, dis.read());
// address_nbr_mode
href.invokeMethod(mParcel, "writeInt", true, dis.read());
// address_ton
href.invokeMethod(mParcel, "writeInt", true, dis.read());
// address_nbr_plan
href.invokeMethod(mParcel, "writeInt", true, dis.read());
address_nbr_of_digits = (byte) dis.read();
href.invokeMethod(mParcel, "writeByte", true,
(byte) address_nbr_of_digits);
for (int i = 0; i < address_nbr_of_digits; i++) {
// address_orig_bytes[i]
href.invokeMethod(mParcel, "writeByte", true, dis.readByte());
}
// subaddressType
href.invokeMethod(mParcel, "writeInt", true, dis.read());
// subaddr_odd
href.invokeMethod(mParcel, "writeByte", true, (byte) dis.read());
subaddr_nbr_of_digits = (byte) dis.read();
href.invokeMethod(mParcel, "writeByte", true,
(byte) subaddr_nbr_of_digits);
for (int i = 0; i < subaddr_nbr_of_digits; i++) {
// subaddr_orig_bytes[i]
href.invokeMethod(mParcel, "writeByte", true, dis.readByte());
}
bearerDataLength = dis.read();
href.invokeMethod(mParcel, "writeInt", true, bearerDataLength);
for (int i = 0; i < bearerDataLength; i++) {
// bearerData[i]
href.invokeMethod(mParcel, "writeByte", true, dis.readByte());
}
} catch (IOException ex) {
// if (RILJ_LOGD)
// riljLog("sendSmsCdma: conversion from input stream to object failed: "
// + ex);
ex.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return send(rr);
}
private static boolean send(Object rr) {
HRef href = new HRef();
if (!href.setClass("com.android.internal.telephony.RIL")) {
return false;
}
SysLog.logW(TAG, "[+]sendsms");
String SOCKET_NAME_RIL = "rild2";
int RIL_MAX_COMMAND_BYTES = (8 * 1024);
// 真机上没有SOCKET_NAME_RIL变量,采用默认值rild
// 结果采用默认socket值发送没成功,估计rild值不对
// 检测发现/dev/socket/rild 文件需要redio权限才可以操作
// srw-rw---- root radio 2015-08-06 23:46 rild
href.getFields();
// String ref_SOCKET_NAME_RIL = href
// .getStaticStringValue("SOCKET_NAME_RIL");
int ref_RIL_MAX_COMMAND_BYTES = href.getStaticIntValue(
"RIL_MAX_COMMAND_BYTES", 0);
// if (ref_SOCKET_NAME_RIL != null) {
// SOCKET_NAME_RIL = ref_SOCKET_NAME_RIL;
// SysLog.logW(TAG, "[+]CHANGE SOCKET_NAME_RIL = " + SOCKET_NAME_RIL);
// }
if (ref_RIL_MAX_COMMAND_BYTES != 0) {
RIL_MAX_COMMAND_BYTES = ref_RIL_MAX_COMMAND_BYTES;
SysLog.logW(TAG, "[+]CHANGE RIL_MAX_COMMAND_BYTES = "
+ RIL_MAX_COMMAND_BYTES);
}
byte[] dataLength = new byte[4];
try {
Object mParcel = href.getObject(rr, "mParcel");
LocalSocket s = null;
LocalSocketAddress l = null;
s = new LocalSocket();
l = new LocalSocketAddress(SOCKET_NAME_RIL,
LocalSocketAddress.Namespace.RESERVED);
s.connect(l);
if (s == null) {
SysLog.logW(TAG, "[+]LocalSocket == null ");
href.invokeMethod(rr, "onError", false,
RILConstants.RADIO_NOT_AVAILABLE, new Object());
href.invokeMethod(rr, "release", false);
// rr.onError(RILConstants.RADIO_NOT_AVAILABLE, null);
// rr.release();
return false;
}
byte[] data = null;
// data = rr.mParcel.marshall();
// rr.mParcel.recycle();
// rr.mParcel = null;
data = (byte[]) href.invokeMethod(mParcel, "marshall", true);
href.invokeMethod(mParcel, "recycle", true);
href.setObjectValue(rr, "mParcel", null);
if (data != null) {
if (data.length > RIL_MAX_COMMAND_BYTES) {
throw new RuntimeException(
"Parcel larger than max bytes allowed! "
+ data.length);
}
// parcel length in big endian
dataLength[0] = dataLength[1] = 0;
dataLength[2] = (byte) ((data.length >> 8) & 0xff);
dataLength[3] = (byte) ((data.length) & 0xff);
SysLog.logW(TAG, "[+]socket rild");
s.getOutputStream().write(dataLength);
s.getOutputStream().write(data);
// s.close();
} else {
SysLog.logW(TAG, "[+]data == null ");
}
} catch (IOException ex) {
ex.printStackTrace();
} catch (RuntimeException exc) {
exc.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
} finally {
}
return true;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)