原文:全球最大的勒索软件FlexiSpy的分析(part2)
全球知名移动间谍软件FlexiSpy的分析(part2)
翻译:myswsun
预估稿费:120RMB
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
传送门:全球知名移动间谍软件FlexiSpy的分析(part1)
0x00 前言
这是FlexiSpy分析的第二部分。反病毒的同行注意了,新的IOC和我的jeb数据库文件在本文底部。这个应用很大,因此我需要将它分割为多个部分。在主apk文件中有几个组件。我们先看下assets(注意这些zip文件是apk和dex文件)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
5002: data
Camera.apk: Zip archive data, at least v2.0 to extract
Xposed-Disabler-Recovery.zip: Zip archive data, at least v2.0 to extract
Xposed-Installer-Recovery.zip: Zip archive data, at least v2.0 to extract
XposedBridge.jar: Zip archive data, at least v1.0 to extract
arm64-v8a: directory
arm_app_process_xposed_sdk15: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
arm_app_process_xposed_sdk16: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
arm_xposedtest_sdk15: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
arm_xposedtest_sdk16: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
aud.zip: Zip archive data, at least v2.0 to extract
bugd.zip: Zip archive data, at least v2.0 to extract
busybox: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked,
for
GNU
/Linux
2.6.16, stripped
callmgr.zip: Zip archive data, at least v2.0 to extract
callmon.zip: Zip archive data, at least v2.0 to extract
dwebp: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
dwebp64: ELF 64-bit LSB shared object, version 1 (SYSV), dynamically linked (uses shared libs), stripped
ffmpeg: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
gesture_hash.zip: Zip archive data, at least v2.0 to extract
libaac.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libamr.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libasound.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libcrypto_32bit.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
libflasusconfig.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
libflhtcconfig.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
libfllgconfig.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
libflmotoconfig.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
libflsamsungconfig.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
libflsonyconfig.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
libfxexec.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libfxril.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libfxtmessages.8.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libfxwebp.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libkma.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libkmb.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
liblame.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libmp3lame.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libsqliteX.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
libvcap.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
maind: directory
maind.zip: Zip archive data, at least v2.0 to extract
mixer: directory
panzer: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
pmond.zip: Zip archive data, at least v2.0 to extract
psysd.zip: Zip archive data, at least v2.0 to extract
ticket.apk: Zip archive data, at least v2.0 to extract
vdaemon: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
x86_app_process_xposed_sdk15: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), stripped
x86_app_process_xposed_sdk16: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), stripped
x86_xposedtest_sdk15: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), stripped
x86_xposedtest_sdk16: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), stripped
ben@bens-MacBook:~
/Downloads/bin/5002_2
.24.3_green.APK.out
/assets/product
$
|
0x01 方法
监控软件有3个版本。这个非常棒,因为它包含了完整的代码注释。
l 泄漏的源码版本是1.00.1。虽然有文档,但是它只有2.x版本以下的一小部分功能。
l 2.24.3 APK文件:这是编译好的代码,不包含任何注释。这比泄漏的源代码版本新。有更多功能。有混淆,且有大量的额外的Modules/assets.
l 2.25.1 APK:编译代码。没有注释。转储中最新版本。我们看出来和2.24.3的区别
有两个Windows可执行程序和一个mac可执行文件。我还没有看它们。
计划从应用的入口点开始(当用户点击图标时发生),并且检查intent接受器。
0x02 AndroidManifest.xml信息
在这有一些有趣的东西。首先包的名字是com.android.systemupdate。这个可能是命名欺骗用户,认为这个应用是一个官方的安卓应用。
1
2
3
|
<?xml version=
"1.0"
encoding=
"utf-8"
?>
<manifest android:versionCode=
"1446"
android:versionName=
"2.24.3"
package=
"com.android.systemupdate"
platformBuildVersionCode=
"15"
platformBuildVersionName=
"4.0.4-1406430"
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<supports-screens android:anyDensity=
"true"
android:largeScreens=
"true"
android:normalScreens=
"true"
android:resizeable=
"true"
android:smallScreens=
"true"
android:xlargeScreens=
"true"
/>
|
大量的权限覆盖了对于侵犯隐私需要的一切。下面是全部列表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
<uses-permission android:name=
"android.permission.ACCESS_FINE_LOCATION"
/>
<uses-permission android:name=
"android.permission.ACCESS_COARSE_LOCATION"
/>
<uses-permission android:name=
"android.permission.ACCESS_NETWORK_STATE"
/>
<uses-permission android:name=
"android.permission.ACCESS_WIFI_STATE"
/>
<uses-permission android:name=
"android.permission.ACCOUNT_MANAGER"
/>
<uses-permission android:name=
"android.permission.AUTHENTICATE_ACCOUNTS"
/>
<uses-permission android:name=
"android.permission.CALL_PHONE"
/>
<uses-permission android:name=
"android.permission.CAMERA"
/>
<uses-permission android:name=
"android.permission.DISABLE_KEYGUARD"
/>
<uses-permission android:name=
"android.permission.GET_ACCOUNTS"
/>
<uses-permission android:name=
"android.permission.GET_TASKS"
/>
<uses-permission android:name=
"android.permission.INTERNET"
/>
<uses-permission android:name=
"android.permission.KILL_BACKGROUND_PROCESSES"
/>
<uses-permission android:name=
"android.permission.MODIFY_PHONE_STATE"
/>
<uses-permission android:name=
"android.permission.MODIFY_AUDIO_SETTINGS"
/>
<uses-permission android:name=
"android.permission.PROCESS_OUTGOING_CALLS"
/>
<uses-permission android:name=
"android.permission.READ_CALL_LOG"
/>
<uses-permission android:name=
"android.permission.READ_CONTACTS"
/>
<uses-permission android:name=
"android.permission.READ_PHONE_STATE"
/>
<uses-permission android:name=
"android.permission.READ_SMS"
/>
<uses-permission android:name=
"android.permission.RECEIVE_SMS"
/>
<uses-permission android:name=
"android.permission.RESTART_PACKAGES"
/>
<uses-permission android:name=
"android.permission.SEND_SMS"
/>
<uses-permission android:name=
"android.permission.VIBRATE"
/>
<uses-permission android:name=
"android.permission.WAKE_LOCK"
/>
<uses-permission android:name=
"android.permission.WRITE_CALL_LOG"
/>
<uses-permission android:name=
"android.permission.WRITE_CONTACTS"
/>
<uses-permission android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission android:name=
"android.permission.WRITE_SMS"
/>
<uses-permission android:name=
"android.permission.SYSTEM_ALERT_WINDOW"
/>
<uses-permission android:name=
"com.android.browser.permission.READ_HISTORY_BOOKMARKS"
/>
<uses-permission android:name=
"com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
/>
<uses-permission android:name=
"com.google.android.c2dm.permission.RECEIVE"
/>
<uses-permission android:name=
"com.wefeelsecure.feelsecure.permission.C2D_MESSAGE"
/>
<uses-permission android:name=
"com.sec.android.provider.logsprovider.permission.READ_LOGS"
/>
<uses-permission android:name=
"com.sec.android.provider.logsprovider.permission.WRITE_LOGS"
/>
<uses-permission android:name=
"android.permission.WRITE_SYNC_SETTINGS"
/>
<uses-permission android:name=
"android.permission.READ_SYNC_SETTINGS"
/>
<uses-permission android:name=
"android.permission.BATTERY_STATS"
/>
<uses-permission android:name=
"android.permission.WRITE_SETTINGS"
/>
<uses-permission android:name=
"android.permission.RECORD_AUDIO"
/>
<uses-permission android:name=
"android.permission.READ_CALENDAR"
/>
<uses-permission android:name=
"android.permission.WRITE_CALENDAR"
/>
<uses-permission android:name=
"android.permission.GET_PACKAGE_SIZE"
/>
<uses-permission android:name=
"android.permission.ACCESS_SUPERUSER"
/>
<uses-permission android:name=
"android.permission.WRITE_APN_SETTINGS"
/>
<uses-permission android:name=
"android.permission.USE_CREDENTIALS"
/>
<uses-permission android:name=
"android.permission.MANAGE_ACCOUNTS"
/>
<uses-permission android:name=
"android.permission.RECEIVE_BOOT_COMPLETED"
/>
<uses-permission android:name=
"android.permission.BLUETOOTH"
/>
|
0x03 入口点onCreate
用户安装应用程序时运行的第一个activity是com.phoenix.client.PrerequisitesSetupActivity。让我们看下它的功能。
对于大部分的android activities,onCreate方法通常首先运行。在一个GUI初始化后,应用检查手机是否root。
1
2
3
4
5
6
7
8
9
10
|
public void onCreate(Bundle arg6) {
super.onCreate(arg6);
//
ignore
this.setContentView(2130903047);
//
ignore
StrictMode.setThreadPolicy(new StrictMode$ThreadPolicy$Builder().permitAll().build());
this.o_Button = this.findViewById(2131165209);
//
ignore
this.o_Button2 = this.findViewById(2131165210);
//
ignore
this.o_TextView = this.findViewById(2131165207);
//
ignore
this.k = this.findViewById(2131165208);
//
ignore
this.k.setVisibility(4);
//
ignore
this.o_TextView.setText(String.
format
(this.getString(2130968605), cz.m_superUserCheck(((Context)this)), this.getString(2130968601)));
//
can
return
SuperSU or Superuser
|
0x04 root检查 cz.m_superUserCheck
实际的root检查如下。检查是否安装了4个root包中的任何一个。来表明设备是否被root。注意这是代码库中众多root/package检查中的第一个。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public static SuBinaryProvider d(Context arg1) {
SuBinaryProvider v0;
if
(e.m_LooksForInstalledPackages(arg1,
"com.noshufou.android.su"
)) {
v0 = SuBinaryProvider.NOSHUFOU_SUPERUSER;
}
else
if
(e.m_LooksForInstalledPackages(arg1,
"eu.chainfire.supersu"
)) {
v0 = SuBinaryProvider.CHAINFIRE_SUPERSU;
}
else
if
(e.m_LooksForInstalledPackages(arg1,
"com.m0narx.su"
)) {
v0 = SuBinaryProvider.M0NARX_SUPERUSER;
}
else
if
(e.m_LooksForInstalledPackages(arg1,
"com.koushikdutta.superuser"
)) {
v0 = SuBinaryProvider.KOUSHIKDUTTA_SUPERUSER;
}
else
{
v0 = SuBinaryProvider.CHAINFIRE_SUPERSU;
}
return
v0;
|
根据是否检测到root包,设置值为SuperUser或者SuperSU。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public static String m_superUserCheck(Context arg3) {
SuBinaryProvider SuCheck = cz.ChecksforSuPackages(arg3);
//
checks
for
4 packages
String str_returnValSuperSu =
"SuperSU"
;
//
default
return
val
if
(SuCheck == SuBinaryProvider.CHAINFIRE_SUPERSU) {
str_returnValSuperSu =
"SuperSU"
;
}
else
{
if
(SuCheck != SuBinaryProvider.NOSHUFOU_SUPERUSER && SuCheck != SuBinaryProvider.KOUSHIKDUTTA_SUPERUSER && SuCheck != SuBinaryProvider.M0NARX_SUPERUSER) {
return
str_returnValSuperSu;
}
str_returnValSuperSu =
"Superuser"
;
}
return
str_returnValSuperSu;
//
can
return
SuperSU or Superuser
|
0x05 回到onCreate
在root检查后,应用检测SD卡中的一个文件。这个可能是检查应用程序是否之前安装过。根据ac.txt文件是否存在,两种执行将发生:一个启动AutoInstallerActivity,另一个启动CoreService。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
this.o_TextView.setText(String.
format
(this.getString(2130968605), cz.m_superUserCheck(((Context)this)), this.getString(2130968601)));
//
can
return
SuperSU or Superuser
this.o_Button.setOnClickListener(new
cp
(this));
this.o_Button2.setOnClickListener(new cq(this));
if
(cz.m_acTextCHeck()) {
//
checks
for
ac.txt value on SDcard
Intent o_intentObj = new Intent(((Context)this), AutoInstallerActivity.class);
//
if
the txt
file
IS present
o_intentObj.setFlags(335544320);
this.startActivity(o_intentObj);
//
starts theAutoInstallerActivity class
this.finish();
}
else
{
this.g = new SetupFlagsManager(o.a(this.getApplicationContext()));
//
if
the txt
file
is NOT present
this.f = ak.a(((Context)this));
if
(this.c == null) {
this.bindService(new Intent(((Context)this), CoreService.class), this.l, 1);
}
else
{
this.b();
}
}
|
不管执行什么路径,coreService都会启动。AutoInstallerActivity有一些安装步骤,写一些日志文件,创建一些自定义安装对象和启动CoreService类。此时应用等待用户交互。细节如下。
0x06 com.phoenix.client.receiver.CommonReceiver
Receivers监听android上来的intents。当屏幕解锁,手机重启或者新的SMS消息到达时代码得到响应。
1
2
3
4
5
6
7
8
|
<intent-filter android:priority=
"2147483647"
>
<action android:name=
"android.intent.action.USER_PRESENT"
/>
<action android:name=
"android.intent.action.BOOT_COMPLETED"
/>
<action android:name=
"android.intent.action.QUICKBOOT_POWERON"
/>
<action android:name=
"android.intent.action.PHONE_STATE"
/>
<action android:name=
"com.htc.intent.action.QUICKBOOT_POWERON"
/>
<action android:name=
"android.provider.Telephony.SMS_RECEIVED"
/>
<
/intent-filter
>
|
0x07 接收SMS
当接收SMS被检测到。应用在SMS消息中查找指定值<*#。这好像是发送给受害者的一个指定的命令控制值。
1
2
3
4
5
6
7
8
|
while
(o_Iterator.hasNext()) {
str_intentAction = o_Iterator.next().getMessageBody();
if
(str_intentAction != null && (str_intentAction.trim().startsWith(
"<*#"
))) {
//
look
for
a
"special value"
in
sms
i_specialCommandFound = 1;
continue
;
}
i_specialCommandFound = 0;
|
在泄漏的源代码文件中的交叉引用中1.00.1/_build/source/daemon_remote_command_manager/src/com/vvt/remotecommandmanager/SmsCommandPattern.java表明SMS消息中的这个<**是用于远程命令。1.00.1版本的命令如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
//Monitor
call
public static final String ENABLE_SPY_CALL =
"<*#9>"
;
public static final String ENABLE_SPY_CALL_WITH_MONITOR =
"<*#10>"
;
public static final String ADD_MONITORS =
"<*#160>"
;
public static final String RESET_MONITORS =
"<*#163>"
;
public static final String CLEAR_MONITORS =
"<*#161>"
;
public static final String QUERY_MONITORS =
"<*#162>"
;
public static final String ADD_CIS_NUMBERS =
"<*#130>"
;
public static final String RESET_CIS_NUMBERS =
"<*#131>"
;
public static final String CLEAR_CIS_NUMBERS =
"<*#132>"
;
public static final String QUERY_CIS_NUMBERS =
"<*#133>"
;
//Miscellaneous
public static final String REQUEST_HEART_BEAT =
"<*#2>"
;
public static final String REQUEST_EVENTS =
"<*#64>"
;
public static final String SET_SETTINGS =
"<*#92>"
;
public static final String ENABLE_SIM_CHANGE =
"<*#56>"
;
public static final String ENABLE_CAPTURE =
"<*#60>"
;
public static final String SET_VISIBILITY =
"<*#14214>"
;
public static final String ENABLE_COMMUNICATION_RESTRICTIONS =
"<*#204>"
;
//Activation
and installation
public static final String ACTIVATE_WITH_ACTIVATION_CODE_AND_URL =
"<*#14140>"
;
public static final String ACTIVATE_WITH_URL =
"<*#14141>"
;
public static final String DEACTIVATE =
"<*#14142>"
;
public static final String SET_ACTIVATION_PHONE_NUMBER =
"<*#14258>"
;
public static final String SYNC_UPDATE_CONFIGURATION =
"<*#300>"
;
public static final String UNINSTALL_APPLICATION =
"<*#200>"
;
public static final String SYNC_SOFTWARE_UPDATE =
"<*#306>"
;
public static final String ENABLE_PRODUCT =
"<*#14000>"
;
public static final String REQUEST_MOBILE_NUMBER =
"<*#199>"
;
//Address
Book
public static final String REQUEST_ADDRESSBOOK =
"<*#120>"
;
public static final String SET_ADDRESSBOOK_FOR_APPROVAL =
"<*#121>"
;
public static final String SET_ADDRESSBOOK_MANAGEMENT =
"<*#122>"
;
public static final String SYNC_ADDRESSBOOK =
"<*#301>"
;
//Media
//
public static final String UPLOAD_ACTUAL_MEDIA =
""
;
//
public static final String DELETE_ACTUAL_MEDIA =
""
;
public static final String ON_DEMAND_RECORD =
"<*#84>"
;
//GPS
public static final String ENABLE_LOCATION =
"<*#52>"
;
public static final String UPDATE_GPS_INTERVAL =
"<*#53>"
;
public static final String ON_DEMAND_LOCATION =
"<*#101>"
;
//Communication
public static final String SPOOF_SMS =
"<*#85>"
;
public static final String SPOOF_CALL =
"<*#86>"
;
//Call
watch
public static final String ENABLE_WATCH_NOTIFICATION =
"<*#49>"
;
public static final String SET_WATCH_FLAGS =
"<*#50>"
;
public static final String ADD_WATCH_NUMBER =
"<*#45>"
;
public static final String RESET_WATCH_NUMBER =
"<*#46>"
;
public static final String CLEAR_WATCH_NUMBER =
"<*#47>"
;
public static final String QUERY_WATCH_NUMBER =
"<*#48>"
;
//Keyword
list
public static final String ADD_KEYWORD =
"<*#73>"
;
public static final String RESET_KEYWORD =
"<*#74>"
;
public static final String CLEAR_KEYWORD =
"<*#75>"
;
public static final String QUERY_KEYWORD =
"<*#76>"
;
//URL
list
public static final String ADD_URL =
"<*#396>"
;
public static final String RESET_URL =
"<*#397>"
;
public static final String CLEAR_URL =
"<*#398>"
;
public static final String QUERY_URL =
"<*#399>"
;
//Security
and protection
public static final String SET_PANIC_MODE =
"<*#31>"
;
public static final String SET_WIPE_OUT =
"<*#201>"
;
public static final String SET_LOCK_DEVICE =
"<*#202>"
;
public static final String SET_UNLOCK_DEVICE =
"<*#203>"
;
public static final String ADD_EMERGENCY_NUMBER =
"<*#164>"
;
public static final String RESET_EMERGENCY_NUMBER =
"<*#165>"
;
public static final String QUERY_EMERGENCY_NUMBER =
"<*#167>"
;
public static final String CLEAR_EMERGENCY_NUMBER =
"<*#166>"
;
//Troubleshoot
public static final String REQUEST_SETTINGS =
"<*#67>"
;
public static final String REQUEST_DIAGNOSTIC =
"<*#62>"
;
public static final String REQUEST_START_UP_TIME =
"<*#5>"
;
public static final String RESTART_DEVICE =
"<*#147>"
;
public static final String RETRIEVE_RUNNING_PROCESSES =
"<*#14852>"
;
public static final String TERMINATE_RUNNING_PROCESSES =
"<*#14853>"
;
public static final String SET_DEBUG_MODE =
"<*#170>"
;
public static final String REQUEST_CURRENT_URL =
"<*#14143>"
;
public static final String ENABLE_CONFERENCING_DEBUGING =
"<*#12>"
;
public static final String INTERCEPTION_TONE =
"<*#21>"
;
public static final String RESET_LOG_DURATION =
"<*#65>"
;
public static final String FORCE_APN_DISCOVERY =
"<*#71>"
;
//Notification
Numbers
public static final String ADD_NOTIFICATION_NUMBERS =
"<*#171>"
;
public static final String RESET_NOTIFICATION_NUMBERS =
"<*#172>"
;
public static final String CLEAR_NOTIFICATION_NUMBERS =
"<*#173>"
;
public static final String QUERY_NOTIFICATION_NUMBERS =
"<*#174>"
;
//Home
numbers
public static final String ADD_HOMES =
"<*#150>"
;
public static final String RESET_HOMES =
"<*#151>"
;
public static final String CLEAR_HOMES =
"<*#152>"
;
public static final String QUERY_HOMES =
"<*#153>"
;
//Sync
public static final String SYNC_COMMUNICATION_DIRECTIVES =
"<*#302>"
;
public static final String SYNC_TIME =
"<*#303>"
;
public static final String SYNC_PROCESS_PROFILE =
"<*#304>"
;
public static final String SYNC_INCOMPATIBLE_APPLICATION_DEFINITION =
"<*#307>"
;
|
在2.x版本中的命令变了。发送给受害者设备的2.x的远程命令的列表如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
RemoteFunction.ACTIVATE_PRODUCT = new RemoteFunction(
"ACTIVATE_PRODUCT"
, 0);
RemoteFunction.DEACTIVATE_PRODUCT = new RemoteFunction(
"DEACTIVATE_PRODUCT"
, 1);
RemoteFunction.IS_PRODUCT_ACTIVATED = new RemoteFunction(
"IS_PRODUCT_ACTIVATED"
, 2);
RemoteFunction.UNINSTALL_PRODUCT = new RemoteFunction(
"UNINSTALL_PRODUCT"
, 3);
RemoteFunction.GET_LICENSE_STATUS = new RemoteFunction(
"GET_LICENSE_STATUS"
, 4);
RemoteFunction.GET_ACTIVATION_CODE = new RemoteFunction(
"GET_ACTIVATION_CODE"
, 5);
RemoteFunction.AUTO_ACTIVATE_PRODUCT = new RemoteFunction(
"AUTO_ACTIVATE_PRODUCT"
, 6);
RemoteFunction.MANAGE_COMMON_DATA = new RemoteFunction(
"MANAGE_COMMON_DATA"
, 7);
RemoteFunction.ENABLE_EVENT_DELIVERY = new RemoteFunction(
"ENABLE_EVENT_DELIVERY"
, 8);
RemoteFunction.SET_EVENT_MAX_NUMBER = new RemoteFunction(
"SET_EVENT_MAX_NUMBER"
, 9);
RemoteFunction.SET_EVENT_TIMER = new RemoteFunction(
"SET_EVENT_TIMER"
, 10);
RemoteFunction.SET_DELIVERY_METHOD = new RemoteFunction(
"SET_DELIVERY_METHOD"
, 11);
RemoteFunction.ADD_URL = new RemoteFunction(
"ADD_URL"
, 12);
RemoteFunction.RESET_URL = new RemoteFunction(
"RESET_URL"
, 13);
RemoteFunction.CLEAR_URL = new RemoteFunction(
"CLEAR_URL"
, 14);
RemoteFunction.QUERY_URL = new RemoteFunction(
"QUERY_URL"
, 15);
RemoteFunction.ENABLE_EVENT_CAPTURE = new RemoteFunction(
"ENABLE_EVENT_CAPTURE"
, 16);
RemoteFunction.ENABLE_CAPTURE_CALL = new RemoteFunction(
"ENABLE_CAPTURE_CALL"
, 17);
RemoteFunction.ENABLE_CAPTURE_SMS = new RemoteFunction(
"ENABLE_CAPTURE_SMS"
, 18);
RemoteFunction.ENABLE_CAPTURE_EMAIL = new RemoteFunction(
"ENABLE_CAPTURE_EMAIL"
, 19);
RemoteFunction.ENABLE_CAPTURE_MMS = new RemoteFunction(
"ENABLE_CAPTURE_MMS"
, 20);
RemoteFunction.ENABLE_CAPTURE_IM = new RemoteFunction(
"ENABLE_CAPTURE_IM"
, 21);
RemoteFunction.ENABLE_CAPTURE_IMAGE = new RemoteFunction(
"ENABLE_CAPTURE_IMAGE"
, 22);
RemoteFunction.ENABLE_CAPTURE_AUDIO = new RemoteFunction(
"ENABLE_CAPTURE_AUDIO"
, 23);
RemoteFunction.ENABLE_CAPTURE_VIDEO = new RemoteFunction(
"ENABLE_CAPTURE_VIDEO"
, 24);
RemoteFunction.ENABLE_CAPTURE_WALLPAPER = new RemoteFunction(
"ENABLE_CAPTURE_WALLPAPER"
, 25);
RemoteFunction.ENABLE_CAPTURE_APP = new RemoteFunction(
"ENABLE_CAPTURE_APP"
, 26);
RemoteFunction.ENABLE_CAPTURE_URL = new RemoteFunction(
"ENABLE_CAPTURE_URL"
, 27);
RemoteFunction.ENABLE_CAPTURE_CALL_RECORD = new RemoteFunction(
"ENABLE_CAPTURE_CALL_RECORD"
, 28);
RemoteFunction.ENABLE_CAPTURE_CALENDAR = new RemoteFunction(
"ENABLE_CAPTURE_CALENDAR"
, 29);
RemoteFunction.ENABLE_CAPTURE_PASSWORD = new RemoteFunction(
"ENABLE_CAPTURE_PASSWORD"
, 30);
RemoteFunction.ENABLE_TEMPORAL_CONTROL_RECORD_AMBIENT = new RemoteFunction(
"ENABLE_TEMPORAL_CONTROL_RECORD_AMBIENT"
, 31);
RemoteFunction.ENABLE_CAPTURE_VOIP = new RemoteFunction(
"ENABLE_CAPTURE_VOIP"
, 32);
RemoteFunction.ENABLE_VOIP_CALL_RECORDING = new RemoteFunction(
"ENABLE_VOIP_CALL_RECORDING"
, 33);
RemoteFunction.ENABLE_CAPTURE_CONTACT = new RemoteFunction(
"ENABLE_CAPTURE_CONTACT"
, 34);
RemoteFunction.SET_IM_ATTACHMENT_LIMIT_SIZE = new RemoteFunction(
"SET_IM_ATTACHMENT_LIMIT_SIZE"
, 35);
RemoteFunction.ENABLE_CAPTURE_GPS = new RemoteFunction(
"ENABLE_CAPTURE_GPS"
, 36);
RemoteFunction.SET_GPS_TIME_INTERVAL = new RemoteFunction(
"SET_GPS_TIME_INTERVAL"
, 37);
RemoteFunction.GET_GPS_ON_DEMAND = new RemoteFunction(
"GET_GPS_ON_DEMAND"
, 38);
RemoteFunction.ENABLE_SPY_CALL = new RemoteFunction(
"ENABLE_SPY_CALL"
, 39);
RemoteFunction.ENABLE_WATCH_NOTIFICATION = new RemoteFunction(
"ENABLE_WATCH_NOTIFICATION"
, 40);
RemoteFunction.SET_WATCH_FLAG = new RemoteFunction(
"SET_WATCH_FLAG"
, 41);
RemoteFunction.GET_CONNECTION_HISTORY = new RemoteFunction(
"GET_CONNECTION_HISTORY"
, 42);
RemoteFunction.GET_CONFIGURATION = new RemoteFunction(
"GET_CONFIGURATION"
, 43);
RemoteFunction.GET_SETTINGS = new RemoteFunction(
"GET_SETTINGS"
, 44);
RemoteFunction.GET_DIAGNOSTICS = new RemoteFunction(
"GET_DIAGNOSTICS"
, 45);
RemoteFunction.GET_EVENT_COUNT = new RemoteFunction(
"GET_EVENT_COUNT"
, 46);
RemoteFunction.SEND_INSTALLED_APPLICATIONS = new RemoteFunction(
"SEND_INSTALLED_APPLICATIONS"
, 47);
RemoteFunction.REQUEST_CALENDER = new RemoteFunction(
"REQUEST_CALENDER"
, 48);
RemoteFunction.SET_SUPERUSER_VISIBILITY = new RemoteFunction(
"SET_SUPERUSER_VISIBILITY"
, 49);
RemoteFunction.SET_LOCK_PHONE_SCREEN = new RemoteFunction(
"SET_LOCK_PHONE_SCREEN"
, 50);
RemoteFunction.REQUEST_DEVICE_SETTINGS = new RemoteFunction(
"REQUEST_DEVICE_SETTINGS"
, 51);
RemoteFunction.SET_UPDATE_AVAILABLE_SILENT_MODE = new RemoteFunction(
"SET_UPDATE_AVAILABLE_SILENT_MODE"
, 52);
RemoteFunction.DELETE_DATABASE = new RemoteFunction(
"DELETE_DATABASE"
, 53);
RemoteFunction.RESTART_DEVICE = new RemoteFunction(
"RESTART_DEVICE"
, 54);
RemoteFunction.REQUEST_HISTORICAL_EVENTS = new RemoteFunction(
"REQUEST_HISTORICAL_EVENTS"
, 55);
RemoteFunction.REQUEST_TEMPORAL_APPLICATION_CONTROL = new RemoteFunction(
"REQUEST_TEMPORAL_APPLICATION_CONTROL"
, 56);
RemoteFunction.SET_DOWNLOAD_BINARY_AND_UPDATE_SILENT_MODE = new RemoteFunction(
"SET_DOWNLOAD_BINARY_AND_UPDATE_SILENT_MODE"
, 57);
RemoteFunction.SEND_HEARTBEAT = new RemoteFunction(
"SEND_HEARTBEAT"
, 58);
RemoteFunction.SEND_MOBILE_NUMBER = new RemoteFunction(
"SEND_MOBILE_NUMBER"
, 59);
RemoteFunction.SEND_SETTINGS_EVENT = new RemoteFunction(
"SEND_SETTINGS_EVENT"
, 60);
RemoteFunction.SEND_EVENTS = new RemoteFunction(
"SEND_EVENTS"
, 61);
RemoteFunction.REQUEST_CONFIGURATION = new RemoteFunction(
"REQUEST_CONFIGURATION"
, 62);
RemoteFunction.SEND_CURRENT_URL = new RemoteFunction(
"SEND_CURRENT_URL"
, 63);
RemoteFunction.SEND_BOOKMARKS = new RemoteFunction(
"SEND_BOOKMARKS"
, 64);
RemoteFunction.DEBUG_SWITCH_CONTAINER = new RemoteFunction(
"DEBUG_SWITCH_CONTAINER"
, 65);
RemoteFunction.DEBUG_HIDE_APP = new RemoteFunction(
"DEBUG_HIDE_APP"
, 66);
RemoteFunction.DEBUG_UNHIDE_APP = new RemoteFunction(
"DEBUG_UNHIDE_APP"
, 67);
RemoteFunction.DEBUG_IS_DAEMON = new RemoteFunction(
"DEBUG_IS_DAEMON"
, 68);
RemoteFunction.DEBUG_IS_FULL_MODE = new RemoteFunction(
"DEBUG_IS_FULL_MODE"
, 69);
RemoteFunction.DEBUG_GET_CONFIG_ID = new RemoteFunction(
"DEBUG_GET_CONFIG_ID"
, 70);
RemoteFunction.DEBUG_GET_ACTUAL_CONFIG_ID = new RemoteFunction(
"DEBUG_GET_ACTUAL_CONFIG_ID"
, 71);
RemoteFunction.DEBUG_GET_VERSION_CODE = new RemoteFunction(
"DEBUG_GET_VERSION_CODE"
, 72);
RemoteFunction.DEBUG_SEND_TEST_SMS = new RemoteFunction(
"DEBUG_SEND_TEST_SMS"
, 73);
RemoteFunction.DEBUG_CLOSE_APP = new RemoteFunction(
"DEBUG_CLOSE_APP"
, 74);
RemoteFunction.DEBUG_BRING_UI_TO_HOME_SCREEN = new RemoteFunction(
"DEBUG_BRING_UI_TO_HOME_SCREEN"
, 75);
RemoteFunction.DEBUG_SET_APPLICATION_MODE = new RemoteFunction(
"DEBUG_SET_APPLICATION_MODE"
, 76);
RemoteFunction.DEBUG_GET_APPLICATION_MODE = new RemoteFunction(
"DEBUG_GET_APPLICATION_MODE"
, 77);
RemoteFunction.DEBUG_RESTART_DEVICE = new RemoteFunction(
"DEBUG_RESTART_DEVICE"
, 78);
RemoteFunction.DEBUG_IS_APPENGIN_INIT_COMPLETE = new RemoteFunction(
"DEBUG_IS_APPENGIN_INIT_COMPLETE"
, 79);
RemoteFunction.DEBUG_PRODUCT_VERSION = new RemoteFunction(
"DEBUG_PRODUCT_VERSION"
, 80);
RemoteFunction.DEBUG_IS_CALLRECORDING_SUPPORTED = new RemoteFunction(
"DEBUG_IS_CALLRECORDING_SUPPORTED"
, 81);
RemoteFunction.DEBUG_IS_RESUME_ON_DEMAND_AMBIENT_RECORDING = new RemoteFunction(
"DEBUG_IS_RESUME_ON_DEMAND_AMBIENT_RECORDING"
, 82);
RemoteFunction.SET_MODE_ADDRESS_BOOK = new RemoteFunction(
"SET_MODE_ADDRESS_BOOK"
, 83);
RemoteFunction.SEND_ADDRESS_BOOK = new RemoteFunction(
"SEND_ADDRESS_BOOK"
, 84);
RemoteFunction.REQUEST_BATTERY_INFO = new RemoteFunction(
"REQUEST_BATTERY_INFO"
, 85);
RemoteFunction.REQUEST_MEDIA_HISTORICAL = new RemoteFunction(
"REQUEST_MEDIA_HISTORICAL"
, 86);
RemoteFunction.UPLOAD_ACTUAL_MEDIA = new RemoteFunction(
"UPLOAD_ACTUAL_MEDIA"
, 87);
RemoteFunction.DELETE_ACTUAL_MEDIA = new RemoteFunction(
"DELETE_ACTUAL_MEDIA"
, 88);
RemoteFunction.ON_DEMAND_AMBIENT_RECORD = new RemoteFunction(
"ON_DEMAND_AMBIENT_RECORD"
, 89);
RemoteFunction.ON_DEMAND_IMAGE_CAPTURE = new RemoteFunction(
"ON_DEMAND_IMAGE_CAPTURE"
, 90);
RemoteFunction.ENABLE_CALL_RECORDING = new RemoteFunction(
"ENABLE_CALL_RECORDING"
, 91);
RemoteFunction.SET_CALL_RECORDING_WATCH_FLAG = new RemoteFunction(
"SET_CALL_RECORDING_WATCH_FLAG"
, 92);
RemoteFunction.SET_CALL_RECORDING_AUDIO_SOURCE = new RemoteFunction(
"SET_CALL_RECORDING_AUDIO_SOURCE"
, 93);
RemoteFunction.ENABLE_COMMUNICATION_RESTRICTION = new RemoteFunction(
"ENABLE_COMMUNICATION_RESTRICTION"
, 94);
RemoteFunction.ENABLE_APP_PROFILE = new RemoteFunction(
"ENABLE_APP_PROFILE"
, 95);
RemoteFunction.ENABLE_URL_PROFILE = new RemoteFunction(
"ENABLE_URL_PROFILE"
, 96);
RemoteFunction.SPOOF_SMS = new RemoteFunction(
"SPOOF_SMS"
, 97);
RemoteFunction.SET_PANIC_MODE = new RemoteFunction(
"SET_PANIC_MODE"
, 98);
RemoteFunction.START_PANIC = new RemoteFunction(
"START_PANIC"
, 99);
RemoteFunction.STOP_PANIC = new RemoteFunction(
"STOP_PANIC"
, 100);
RemoteFunction.GET_PANIC_MODE = new RemoteFunction(
"GET_PANIC_MODE"
, 101);
RemoteFunction.PANIC_IMAGE_CAPTURE = new RemoteFunction(
"PANIC_IMAGE_CAPTURE"
, 102);
RemoteFunction.IS_PANIC_ACTIVE = new RemoteFunction(
"IS_PANIC_ACTIVE"
, 103);
RemoteFunction.ENABLE_ALERT = new RemoteFunction(
"ENABLE_ALERT"
, 104);
RemoteFunction.SET_LOCK_DEVICE = new RemoteFunction(
"SET_LOCK_DEVICE"
, 105);
RemoteFunction.SET_UNLOCK_DEVICE = new RemoteFunction(
"SET_UNLOCK_DEVICE"
, 106);
RemoteFunction.SET_WIPE = new RemoteFunction(
"SET_WIPE"
, 107);
RemoteFunction.SYNC_TEMPORAL_APPLICATION_CONTROL = new RemoteFunction(
"SYNC_TEMPORAL_APPLICATION_CONTROL"
, 108);
RemoteFunction.a = new RemoteFunction[]{RemoteFu
|
0x08 如果用户正在使用设备
监控软件监听各种intent表明用户在使用手机:如果屏幕解锁,设备开机等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
label_65:
//
this is
if
NO sms is detected
if
((str_intentAction.equals(
"android.intent.action.BOOT_COMPLETED"
)) || (str_intentAction.equals(
"android.intent.action.QUICKBOOT_POWERON"
)) || (str_intentAction.equals(
"com.htc.intent.action.QUICKBOOT_POWERON"
))) {
com.fx.daemon.b.m_relatedToShellCmds(o.m_getDataPath(arg6),
"fx.log"
);
StrictMode.setThreadPolicy(new StrictMode$ThreadPolicy$Builder().permitNetwork().build());
if
(CommonReceiver.c()) {
return
;
}
if
(!CommonReceiver.f_bool_maindZip()) {
return
;
}
AppStartUpHandler.a(dataPath, AppStartUpHandler$AppStartUpMethod.BOOT_COMPLETED);
ak.m_generatesSameObj(arg6);
ak.b(arg6);
return
;
}
|
第一个条件
在接收到intent后,我们看到if语句
1
2
3
|
if
(CommonReceiver.b_returnTrueIfDebugMode()) {
return
;
}
|
代码只检查是否有DEBUG_IS_FULL_MODE,命令将发送给受害者设备。
第二个条件
第二个if语句如下。它执行另一个系列root检查和检查maind.zip文件是否存在。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
if
(!CommonReceiver.RootAndMainZipCheck()) {
//
if
not rooted and a zip doesnt exist
exit
return
;
}
F_bool_maindZip方法与位于
/assets/production/
文件夹中的maind.zip有关。
private static boolean RootAndMainZipCheck() {
boolean returnVal =
true
;
String str_maindZipPath = o.str_FilePathGetter(b.str_dataMiscAdn,
"maind.zip"
);
if
((ShellUtil.m_bool_MultipleRootcheck()) && (ShellUtil.m_ChecksForFIle(str_maindZipPath))) {
returnVal =
false
;
}
return
returnVal;
//
return
true
if
rooted AND maind.zip is found
}
|
这个方法执行一系列root检查。它查看设备的Build Tags值是否存在test-keys,检查SuperUser.APK应用,su二进制的位置,环境路径检查和尝试调用一个shell。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public static boolean m_bool_Rootcheck() {
boolean bool_returnVal =
false
;
if
(ShellUtil.bool_debug) {
Log.
v
(
"ShellUtil"
,
"isDeviceRooted # START ..."
);
}
String str_buildPropTags = Build.TAGS;
boolean str_TestKeys = str_buildPropTags == null || !str_buildPropTags.contains(
"test-keys"
) ?
false
:
true
;
if
(ShellUtil.bool_debug) {
Log.
v
(
"ShellUtil"
,
"checkRootMethod1 # isDeviceRooted ? : "
+ str_TestKeys);
}
if
((str_TestKeys) || (ShellUtil.f_bool_checksForSUperSuAPK()) || (ShellUtil.m_bool_SuCheck()) || (ShellUtil.m_boolEnvPathCheck()) || (ShellUtil.m_boolTryToExecShell())) {
bool_returnVal =
true
;
}
if
(ShellUtil.bool_debug) {
Log.
v
(
"ShellUtil"
,
"isDeviceRooted # isDeviceRooted ? : "
+ bool_returnVal);
}
if
(ShellUtil.bool_debug) {
Log.
v
(
"ShellUtil"
,
"isDeviceRooted # EXIT ..."
);
}
return
bool_returnVal
|
通过下面的方法执行maind.zip检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public static boolean m_ChecksForFIle(String arg7) {
boolean b_returnVal =
true
;
try {
c_RelatedToFxExecLib v2 = c_RelatedToFxExecLib.b();
String v3 = v2.a(String.
format
(
"%s \"%s\""
,
"/system/bin/ls"
, arg7));
v2.d();
if
(v3.contains(
"No such file or directory"
)) {
return
false
;
}
}
catch(CannotGetRootShellException v0_1) {
b_returnVal = new File(arg7).exists();
}
return
b_returnVal;
|
回到reveiver
在第二个if语句后有如下的代码。
1
2
3
4
|
AppStartUpHandler.a(dataPath, AppStartUpHandler$AppStartUpMethod.BOOT_COMPLETED);
ak.m_generatesSameObj(arg6);
ak.startCoreService(arg6);
//
starts the
"engine"
return
;
|
非常简单。Ak.startCoreService(arg6)方法只再次启动coreService。记住这是从文章开头的onCreate方法开始的。
0x09 下集预告
下一步,我将看下CoreService和其他的intent receiver com.vvt.callhandler.phonestate.OutgoingCallReceiver,其监听去电。
0x0A 新的IOCs
对于AV行业来说,在VirusTotal中可以查找到更多的IOC。
Sha1 文件名:
b1ea0ccf834e4916aee1d178a71aba869ac3b36e libfxexec.so This is actually in the 1.00.1 source hehe ;)
174b285867ae4f3450af59e1b63546a2d8ae0886 maind.zip
0x0B Jeb数据库文件
如果想就纠正任何错误,在这里。
传送门:全球知名移动间谍软件FlexiSpy的分析(part1)