测试apk-异常管控netLocation攻击者开发

本文档详述了一个apk测试过程,旨在触发手机中的异常功耗管控机制。测试步骤包括在不同手机上安装apk,设置应用白名单,并通过adb shell命令获取定位信息。源码分析显示,apk在后台无限制地进行网络位置监听。然而,系统日志表明该应用未触发消息通知,因为其被判定为不满足特定条件,如未在智能优化应用列表中。
摘要由CSDN通过智能技术生成

1. 目的

基于《软件绿色联盟应用体验标准》中 NetLocation 资源的定义,进 NetLocation 频繁次数的测试apk。旨在触发手机中异常功耗管控机制。

NetWorkLocation异常

2. 测试步骤

H手机和T手机、其他手机进行安装该apk.
所有手机都需要设置应用为白名单。

2.1 手机白名单设置方法:

手机管家->应用启动设置:允许自启动、允许关联启动、允许后台启动
H手机白名单

2.2 测试环境

  1. 必须开启GPS和WiFi连接,再打开app进行测试
  2. home 回到桌面,灭屏至少30分钟以上,再亮屏查看消息通知栏

2.2 dump 相关命令

2.2.1 adb shell dumpsys appops --op X

用途X:获取手机应用定位信息

APP_OP_COARSE_LOCATION = 0
APP_OP_FINE_LOCATION = 1
APP_OP_MONITOR_LOCATION = 41
APP_OP_MONITOR_HIGH_POWER_LOCATION = 42
APP_OP_MOCK_LOCATION = 58
APP_OP_ACCESS_MEDIA_LOCATION = 90
APP_OP_FINE_LOCATION_SOURCE = 108
APP_OP_COARSE_LOCATION_SOURCE = 109

例如:adb shell dumpsys appops --op 41

$ adb shell dumpsys appops --op 41
Current AppOps Service state:
  Settings:
    top_state_settle_time=+5s0ms
    fg_service_state_settle_time=+5s0ms
    bg_state_settle_time=+1s0ms


  Uid 1000:
    state=pers
    capability=LCMN
    appWidgetVisible=false
    Package android:
      MONITOR_LOCATION (allow / switch COARSE_LOCATION=allow):
        null=[
          Access: [pers-s] 2022-04-22 17:43:07.078 (-5d4h11m26s922ms) duration=+35s984ms
        ]
        SensorNotificationService=[
          Access: [pers-s] 2022-04-20 22:12:25.441 (-6d23h42m8s559ms) duration=+2d0h15m48s945ms
        ]
        GnssService=[
          Access: [pers-s] 2022-04-22 17:43:28.020 (-5d4h11m5s980ms) duration=+9s997ms
        ]
2.2.2 adb shell dumpsys location

用途X:获取手机应用定位信息

2.2 运行本apk

NetWorkLocation异常

2.3 日志查看

adb shell dumpsys appops --op 41

  Uid u0a398:
    state=top
    startNesting=2
    Package com.sufadi.blocaknetlocation:
      MONITOR_LOCATION (allow / switch COARSE_LOCATION=allow):
          Access: [top-s] 2022-06-06 13:57:20.258 (-1m31s751ms)
          Running start at: +1m31s750ms
          startNesting=1

3. apk 源码

本apk作用:仅使用网络定位,但是后台一直无限制进行网络位置监听。

3.1 UI

UI

3.2 核心逻辑

3.2.1 MainActivity
package com.sufadi.blocaknetlocation

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

class MainActivity : AppCompatActivity() {

    companion object {
        val TAG = "blocaknetlocation_MainActivity"
        val REQUES_CODE_OK = 200
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        applyPermission()
    }

    fun applyPermission() {
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
            || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED){//未开启定位权限

            Log.d(TAG, "applyPermission")
            ActivityCompat.requestPermissions(this, arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION), REQUES_CODE_OK)
        } else {
            Log.d(TAG, "startService BlockNetLocationService")
            startService(Intent(this, BlockNetLocationService::class.java))
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray) {
        when (requestCode) {
            REQUES_CODE_OK-> if (grantResults.size == 2 &&
                grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                for (grant in grantResults) {
                    Log.d(TAG, "grant: $grant")
                }
                ActivityCompat.requestPermissions(this, arrayOf(
                    Manifest.permission.ACCESS_BACKGROUND_LOCATION), REQUES_CODE_OK)
                /*Toast.makeText(this@MainActivity, "未开启定位权限,请手动到设置去开启权限", Toast.LENGTH_LONG).show()
                finish()*/
            } else {
                Log.d(TAG, "startService BlockNetLocationService 1")
                startService(Intent(this, BlockNetLocationService::class.java))
            }
        }

        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }
}

3.2.2 BlockNetLocationService

主要进行网络定位的监听

package com.sufadi.blocaknetlocation

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log

class BlockNetLocationService: Service() {

    companion object {
        val TAG = "BlockNetLocationService"
        val FORGROUND_ID = 0x11
    }

    lateinit var locationManager: LocationManager
    lateinit var netWorkListener: NetworkListener

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        super.onCreate()
        Log.d(TAG, "onCreate")
        startMyForeground()

        locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
        netWorkListener = NetworkListener()
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000L, 0f, netWorkListener)
    }

    override fun onDestroy() {
        super.onDestroy()
        locationManager.removeUpdates(netWorkListener)
        stopForeground(true)
    }

    inner class NetworkListener : LocationListener {

        // 位置的改变
        override fun onLocationChanged(location: Location) {
            val latitude = location.latitude// 维度
            val longitude = location.longitude// 经度
            //显示当前坐标
            Log.d(TAG, "网络定位 location:($latitude,$longitude)")
        }

        // gps卫星有一个没有找到
        override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
            Log.d(TAG, "网络定位 onStatusChanged:provider$provider,status: $status, extras:$extras")
        }

        // 某个设置被打开
        override fun onProviderEnabled(provider: String) {
            Log.d(TAG, "网络定位 onProviderEnabled$provider")
        }

        // 某个设置被关闭
        override fun onProviderDisabled(provider: String) {
            Log.d(TAG, "网络定位 onProviderDisabled$provider")
        }

    }

    private fun startMyForeground() {
        Log.d(TAG, "startMyForeground show notification")
        Log.d(TAG, "PhoneDataService startMyForeground sdk :" + android.os.Build.VERSION.SDK_INT)
        val nb = Notification.Builder(this)

        if (android.os.Build.VERSION.SDK_INT >= 26) {
            val CHANNEL_ONE_ID = "channel_id_foreground"
            val CHANNEL_ONE_NAME = "Channel One"
            var notificationChannel: NotificationChannel? = null

            notificationChannel = NotificationChannel(
                CHANNEL_ONE_ID,
                CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_LOW
            )

            nb.setChannelId(CHANNEL_ONE_ID)

            val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            manager.createNotificationChannel(notificationChannel)
        }

        nb.setSmallIcon(R.mipmap.ic_launcher)
        nb.setContentTitle(getString(R.string.notification_title))
        nb.setContentText(getString(R.string.notification_Content))

        try {
            startForeground(FORGROUND_ID, nb.build())
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }
}

3.3 不触发消息通知的分析

2022-06-06 17:31:41.988 2490-3391/? I/APwActAnalysis: can not process the net location app: com.sufadi.blocaknetlocation

655      private void analyseNetLocationAct(AppPowerRecord arg18, long arg19) {
656          AppPowerActAnalysis v0 = this;
657          long v10 = arg18.getNetLocationTime();
658          int v12 = 12;
659          int v13 = arg18.getPowerLevel(v12);
660          String v14 = arg18.mAppName;
661          if(v13 == 2 || v13 == 3) {
662              AppActAnalyzer v15 = v0.getAnalyzer(v12);
663              if(v15 != null) {
664                  v15.initActAnalyzer(v14, v10, arg19, 1, v13);
665                  int v8 = v15.startActAnalyzer();
666                  if(v8 == 1) {
667                      Log.i("APwActAnalysis", "a abnormal net location app, K_L : " + v14);
668                      v0.mAppPowerSave.dispatchAbnormalApp(v14, v12, v10, 1, arg19);
669                  }
670                  else if(v8 == -1) {
671                      Log.i("APwActAnalysis", "net location high power app: " + v14 + " level: " + v13 + " duration:" + v10);
672                      v0.mAppPowerSave.handleHighPowerApp(v14, v12, v10, arg19);
673                  }
674                  else {
675                      Log.i("APwActAnalysis", "can not process the net location app: " + v14);
676                  }
677              }
678              else {
679                  v0.mAppPowerSave.handleHighPowerApp(v14, v12, v10, arg19);
680              }
681          }
682      }

27      public int startActAnalyzer() {
            // isCtrlScope 为false,则 getOptimizeType = 0,  而我们demo app 的设置为 1,isCtrlScope为true
            // isPrivilegeUserApp demo app 也非写死的应用
            // isImportantDefaultApp demo app 也非重要进程
            // isClockApp demo app 也不是闹钟应用
28          if (!isCtrlScope() || isPrivilegeUserApp() || isImportantDefaultApp() || isClockApp()) {
29              return 0;
30          }
31          int optimizeType = this.mIAppManager.getOptimizeType(this.mPkg);
32          if (optimizeType == 2) { // 智能自动管理
33              int i = this.mPowerLevel;
34              if ((i == 2 || i == 3) && NET_LOCATION_APPS_BLACK_LIST.contains(this.mPkg)) {
35                  return 1;
36              }
37              return -1;
38          } else if (optimizeType != 3) { // 不允许自启动+不允许关联启动+不允许后台启动
39              return -1;
40          } else {
41              int i2 = this.mPowerLevel;
42              if (i2 == 2 || i2 == 3) {
43                  return 1;
44              }
45              return -1;
46          }
47      }
48  }

=================================================================================
1152      public boolean isCtrlScope(String str) {
1153          return getOptimizeType(str) != 0;
1154      }


1115      public int getOptimizeType(String str) {
1116          if (this.mSmartOptimizeApps.contains(str)) {
1117              return 2;
1118          }
1119          if (this.mAlwaysOptimizeApps.contains(str)) {
1120              return 3;
1121          }
1122          if (this.mNeverOptimizeApps.contains(str)) {
1123              return 1;
1124          }
1125          if ((!mHasThreeOptimize && DEBUG_USB) || mFeedbacKillSystemApps.contains(str) || this.mOutScopeCtrlApps.contains(str)) {
1126              return 2;
1127          }
1128          if (!this.mAppManager.asSmartOptimizeApp(str) || this.mSmartOptimizeHideApps.contains(str)) {
1129              return 0;
1130          }
1131          this.mOutScopeCtrlApps.add(str);
1132          Log.i("ApplistMgr", str + " as smart opt...");
1133          return 2;
1134      }


user@chuanghangren-Lenovo-Product:~$ adb shell dumpsys powergenius -a|grep "com.sufadi.blocaknetlocation"
        mNeverOptimizeApps: [com.huawei.localBackup, com.huawei.appmarket, com.tencent.mm, com.sufadi.blockgps, com.sufadi.blocaknetlocation, com.unionpay, com.sufadi.blockalarm, com.huawei.hwid]


862      private void loadSmartOptHideAppsNew() {
863          List<String> appOptimizeType = AppAwareAdapter.getAppOptimizeType(new int[]{1, -1, -1, -1}, (int[]) null, new int[]{0, -1, -1, -1});
864          if (appOptimizeType != null) {
865              this.mSmartOptimizeHideApps.addAll(appOptimizeType);
866              Log.i("ApplistMgr", "mSmartOptimizeHideApps: " + this.mSmartOptimizeHideApps);
867          }
868      }

863      public boolean asSmartOptimizeApp(String str) {
864          String str2;
865          List users = this.mUserManager.getUsers();
866          if (users == null) {
867              Log.w(TAG, "users is null.");
868              return false;
869          }
870          ApplicationInfo applicationInfo = null;
871          Iterator it = users.iterator();
872          while (true) {
873              if (!it.hasNext()) {
874                  break;
875              }
876              try {
877                  applicationInfo = this.mPM.getApplicationInfoAsUser(str, 0, ((UserInfo) it.next()).id);
878                  break;
879              } catch (PackageManager.NameNotFoundException unused) {
880              } catch (RuntimeException e) {
881                  Log.e(TAG, "RuntimeException: ", e);
882              } catch (Exception e2) {
883                  Log.e(TAG, "Exception: ", e2);
884              }
885          }
886          if (!isSystemApp(applicationInfo)) {
887              return true;
888          }
             // 可删除的第三方应用目录
889          if (applicationInfo == null || (str2 = applicationInfo.sourceDir) == null || !str2.contains("/system/delapp")) {
890              return false;
891          }
892          return true;
893      }
=================================================================================
154      private static final ArrayList<String> mPrivilegeUserApps = new ArrayList<String>() {
155          {
156              add("com.whatsapp");
157              add("com.facebook.katana");
158              add("com.facebook.orca");
159              add("com.tencent.mm");
160              add("jp.netstar.familysmile");
161              add("com.nttdocomo.android.gesturecontrol");
162              add("jp.softbank.mb.parentalcontrols");
163          }
164      };
=================================================================================
133      public boolean isImportantDefaultApp() {
134          String stringForUser;
135          String defaultLauncher = this.mIAppType.getDefaultLauncher();
136          if (defaultLauncher != null && defaultLauncher.equals(this.mPkg)) {
137              return true;
138          }
139          String usingLauncher = this.mIAppType.getUsingLauncher();
140          if (usingLauncher != null && usingLauncher.equals(this.mPkg)) {
141              return true;
142          }
143          String curLiveWallpaper = this.mIAppType.getCurLiveWallpaper();
144          if (curLiveWallpaper != null && curLiveWallpaper.equals(this.mPkg)) {
145              return true;
146          }
147          String defaultInputMethod = this.mIAppType.getDefaultInputMethod();
148          if (defaultInputMethod != null && defaultInputMethod.equals(this.mPkg)) {
149              return true;
150          }
151          String defaultSmsApplication = this.mIAppType.getDefaultSmsApplication();
152          if (defaultSmsApplication != null && defaultSmsApplication.equals(this.mPkg)) {
153              return true;
154          }
155          int curUserId = this.mIAppManager.getCurUserId();
156          if (curUserId == 0 || (stringForUser = Settings.Secure.getStringForUser(this.mContext.getContentResolver(), "sms_default_application", curUserId)) == null || !stringForUser.equals(this.mPkg)) {
157              return false;
158          }
159          return true;
160      }

426      public static String getDefaultSmsApplication(Context context) {
427          try {
428              ComponentName component = (ComponentName) ReflectUtils.invokeMethod("getDefaultSmsApplication", "com.android.internal.telephony.SmsApplication", new Object[]{context, Boolean.valueOf(false)});
429              if (component == null) {
430                  return null;
431              }
432              String defaultSmsPackage = component.getPackageName();
433              Log.i("CommonAdapter", "defaultSmsApplication: " + defaultSmsPackage);
434              return defaultSmsPackage;
435          } catch (Exception e) {
436              Log.w("CommonAdapter", "no method getDefaultSmsApplication");
437              return null;
438          }
439      }

adb shell settings get secure sms_default_application
com.android.mms

 adb shell pm list users Users
Users:
        UserInfo{0:+86 132 6685 2358:13} running

2022-06-08 11:36:54.276 2494-3513/? I/SmsApplication: updatedNeeded = false for userId = 0
2022-06-08 11:36:54.283 2494-3513/? I/CommonAdapter: defaultSmsApplication: com.android.mms
2022-06-08 11:36:54.284 2494-3513/? I/APwActAnalysis: can not process the net location app: com.game.map.email.alarm.network
=================================================================================
162      /* access modifiers changed from: protected */
163      public boolean isClockApp() {
164          if ("com.android.deskclock".equals(this.mPkg) || "com.huawei.deskclock".equals(this.mPkg) || "com.huawei.calendar".equals(this.mPkg) || "com.android.calendar".equals(this.mPkg)) {
165              return true;
166          }
167          ArrayList<String> appsByType = this.mIAppType.getAppsByType(10);
168          if (appsByType == null || appsByType.size() <= 0 || !appsByType.contains(this.mPkg)) {
169              return false;
170          }
171          return true;
172      }

2022-06-08 11:42:54.943 2494-3513/? I/APwActAnalysis: can not process the net location app: com.game.map.email.alarm.network

APwActAnalysis|com.sufadi.blocaknetlocation|AppPowerMonitor 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值