Android手機電話和簡訊通訊都是由架構層RIL.java發送指令到RIL(Radio Interface Layer)層通訊端,由radio守護進程負責偵聽通訊端,如果傳來訊號,radio則按照相應指示去處理。“/android4.0/hardware/ril/reference-ril/reference-ril.c”有關打電話和發簡訊代碼。
1. 訪控撥打到電話
由以上分析可知,Zygote在啟動時會建立打電話的白名單設定檔,而此設定檔的模式是“全域可讀寫”,因此,radio進程可以讀取它的內容作為撥號和傳送簡訊的白名單。本課題開發了如下函數:
/*
* to judge whether the dial string is in theoutgoing white list
* return -1 if the outgoingcallwhitelist filecan not be open
* return 1 if the dial string is in theoutgoingcallwhitelist
* else return 0
* */
static intDialStringIsInOutgoingWhiteList(const char *dialstring);
此函數是使用fopen函數開啟白名單檔案,然後按行讀取其中內容,判斷電話號碼字串dialstring是否和相應的行匹配。
接著,找到撥打到電話的函數,如下所示:
/*
* This a dial function
* */
static voidrequestDial(void *data, size_t datalen, RIL_Token t);
該函數是首先將data所指向的資料強制轉化為RIL_Dial類型,然後解析出撥號指令,如下所示:
p_dial = (RIL_Dial*)data;
switch(p_dial->clir) {
case 1: clir = "I"; break; /*invocation*/
case 2: clir = "i"; break; /*suppression*/
default:
case 0: clir= ""; break; /*subscriptiondefault*/
}
asprintf(&cmd,"ATD%s%s;", p_dial->address, clir);
其中,p_dial->address所指向的字串是撥打到電話的號碼,於是加入以下代碼:
#ifdef HAVE_SMACK
/*
* control outgoing call
* */
int rc =DialStringIsInOutgoingWhiteList(p_dial->address);
if(rc == 0) {
LOGE("the dialstring is not in theoutgoingcallwhitelist!");
goto next;
}
#endif
ret =at_send_command(cmd, NULL); // cmdcontains the outgoing dial string
next:
free(cmd);
… …
這樣,當使用者撥打不在通訊錄內號碼時,撥號指令不能夠被進一步發送。
2. 訪控傳送簡訊
在撥號函數中,很容易找到號碼,但radio在傳送簡訊函數中,是將號碼整合到pdu中,如下所示:
static voidrequestSendSMS(void *data, size_t datalen, RIL_Token t)
{
int err;
const char *smsc;
const char *pdu;
int tpLayerLength;
char *cmd1, *cmd2;
RIL_SMS_Response response;
ATResponse *p_response = NULL;
smsc = ((const char **)data)[0];
pdu = ((const char **)data)[1];
tpLayerLength = strlen(pdu)/2;
… …
}
如上所示,smsc指向簡訊中心號碼字串,pdu指向字串中包含了傳送簡訊的目的地號碼。因此,本課題開發出如下函數對傳送簡訊進行控制:
/*
* to judge whether the sms string is in theoutgoing white list
* return -1 if the outgoingcallwhitelist filecan not be open
* return 1 if the sms string is in theoutgoingcallwhitelist
* else return 0
* */
static intSmsStringIsInOutgoingWhiteList(const char *pdu);
這個函數也是開啟白名單設定檔,但不在使用字串函數strcmp,而是使用了strstr函數來判斷簡訊號碼字串是否pdu所指向的字串的子串。最後添加以下代碼即可:
#ifdef HAVE_SMACK
if(SmsStringIsInOutgoingWhiteList(pdu) == 0){
LOGE("the sms string is not in theoutgoingcallwhitelist!");
err = 1;
goto next;
}
#endif
err = at_send_command_sms(cmd1, cmd2,"+CMGS:", &p_response);
next:
if (err != 0 || p_response->success == 0) gotoerror;
… …
通過調研,有些惡意軟體作者並不是使用發簡訊許可權來完成發簡訊行為,而是通過JNI等技術繞過Android架構層許可權檢查來實現發簡訊,但目前他們還無法繞過radio,因此,本課題已經能夠實現對打電話和發簡訊的有力控制,以阻止惡意軟體“惡意計費”的行為。