Hunting down app that shows annoying popups

Every day hundreds of new apps are added to the PlayStore. But quantity not necessarily means quality. When developers are motivared by purely short-term revenue gain, they tend to use various dirty techniques to make as much money as possible during the app’s short run.
One of such techniques is to show popup ads on the phone. Quite often app will wait for few days before start of the shitshow and it may not be obvious which app is guilty. This post shows few methods of identifying such apps.

Information in Play Store should be taken with grain of salt

Whenever you see reviews or number of installs, keep in mind that those numbers may not be genuine. Of course, Google is doing its best to protect integrity of that data, but reality is that bad actors can buy fake installs, reviews. Even the app itself can be bought, so don’t be tricked by quality of the app.
Pricing

Method 1: Recently installed apps

If you recently ibnstalled app, especially from unknown publisher - high chance that those app is responsible for popup ads. Need more proof? Let’s got to the next method.

Method 2: Identify by app icon

This method is also pretty straight forward and does not require any special tools or skills.
Whenever popup is shown, press Overview button on the phone and check the icon of the activity/screen. Often it will be the icon of the app itself. Go find that app and delete it (don’t forget to write bad review for it and report abuse)
Check out the icon

However, this method won’t work whenever developer deliberately tried to hide the app by using different icon:

Icon is not helpful here

Method 3: Use dumpsys tool

Fortunately, Android comes with plenty of useful debugging and troubleshooting commands.
One of such tools is dumpsys.

dumpsys is a tool that runs on Android devices and provides information about system services. You can call dumpsys from the command line using the Android Debug Bridge (ADB) to get diagnostic output for all system services running on a connected device.

To get Android Debug Bridge (ADB), one need to install Android SDK on the computer and enable developer mode on the phone.

After installed, you can run following command to identify rogue app (look for mFocusedApp or mCurrentFocus):

1
2
3
4
5
6
7
8
$ adb shell dumpsys window
.....
mCurConfiguration={0 1.0 themeSeq = 0 showBtnBg = 0 310mcc410mnc en_US ldltr sw360dp w360dp h616dp 640dpi nrml long port finger -keyb/v/h -nav/h mkbd/h s.6}
mHasPermanentDpad=false
mCurrentFocus=Window{fdc24c2 u0 d0 com.<hidden>.photoeditor/com.google.android.gms.ads.AdActivity}
mFocusedApp=AppWindowToken{5bafef3 token=Token{ee24d62 ActivityRecord{9b242d u0 com.<hidden>.photoeditor/com.google.android.gms.ads.AdActivity t20}}}
mInTouchMode=true mLayoutSeq=191
mLastDisplayFreezeDuration=0 due to Window{3e13406 u0 d0 StatusBar}

In this example you can see that running package is com..photoeditor. Go to play.google.com/store/apps/details?id= to find out the app.

Update: Method 2, Improved

David Šmíd suggested one easy method that eliminates the need for method 3.

If you press the button to switch apps (Overview button), long press on the app icon and another icon appears on the right to go to app info screen. Tap on ‘i’ button and it will reveal the app info.

Long press on the icon

App info

Summary

These three methods will help to find which app is responsible for annoying ad popups on Android phones. Please don’t forget to report abuse and leave appropriate comment.

How to immediately kill all background processes associated with the given package in Android

One way to achieve that is to use ActivityManager.killBackgroundProcesses(String))

Sample:

1
2
ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
am.killBackgroundProcesses(KillPackage);

To call this method, app needs to have KILL_BACKGROUND_PROCESSES permission. Add following entry to the Manifest:

1
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />

How permissions can be abused by malicious apps

Android, as Operating system, provides rich set of features to developers. However, some features are quite dangerous and can harm users. One way to contain that danger is permission system. In order to do something non-trivial on the phone app should obtain appropriate permission. However, users tend to approve permissions requests without understanding consequences.
This post describes how various permissions could be abused. List is not comprehensive in any case, and serves illustration purposes.

android.permission.BIND_ACCESSIBILITY_SERVICE

Intended Use: Write apps that use accesibility service.

How can be abused: Can be abused to spy on users, or perform actions on the phone without, such as silent installations or clicks. Interesting read about such abuse: https://blog.zimperium.com/clicking-bot-applications/

android.permission.ACCESS_COARSE_LOCATION

Intended Use: Access coarse location sources, such as the mobile network database, to determine an approximate phone location, where available.

How can be abused: Malicious applications can use this to determine approximately where you are.

android.permission.ACCESS_FINE_LOCATION

Intended Use: Access fine location sources, such as the Global Positioning System on the phone, where available.

How can be abused: Malicious applications can use this to determine where you are and may consume additional battery power.

android.permission.ACCESS_LOCATION_EXTRA_COMMANDS

Intended Use: Access extra location provider commands.

How can be abused: Malicious applications could use this to interfere with the operation of the GPS or other location sources.

android.permission.ACCESS_MOCK_LOCATION

Intended Use: Create mock location sources for testing.
Intended Use: This allows the app to override the location and/or status returned by other location sources such as GPS or location providers.

How can be abused: Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers.

android.permission.BROADCAST_PACKAGE_REMOVED

Intended Use: Allows an application to broadcast a notification that an application package has been removed.

How can be abused: Malicious applications may use this to kill any other application running.

android.permission.BROADCAST_SMS

Intended Use: Allows an application to broadcast a notification that an SMS message has been received.

How can be abused: Malicious applications may use this to forge incoming SMS messages.

android.permission.BROADCAST_STICKY

Intended Use: Allows an application to send sticky broadcasts, which remain after the broadcast ends. These are broadcasts whose data is held by the system after being finished, so that clients can quickly retrieve that data without having to wait for the next broadcast.

How can be abused: Malicious applications can make the phone slow or unstable by causing it to use too much memory.

android.permission.BROADCAST_WAP_PUSH

Intended Use: Allows an application to broadcast a notification that a WAP-PUSH message has been received.

How can be abused: Malicious applications may use this to forge MMS message receipt or to replace the content of any web page silently with malicious variants.

android.permission.CALL_PRIVILEGED

Intended Use: Allows the application to call any phone number, including emergency numbers, without your intervention.

How can be abused: Malicious applications may place unnecessary and illegal calls to emergency services.

android.permission.CHANGE_COMPONENT_ENABLED_STATE

Intended Use: Allows an application to change whether or not a component of another application is enabled.

How can be abused: Malicious applications can use this to disable important phone capabilities. It is important to be careful with permission, as it is possible to bring application components into an unusable, inconsistent or unstable state.

android.permission.DELETE_PACKAGES

Intended Use: Allows an application to delete Android packages.

How can be abused: Malicious applications can use this to delete important applications.

android.permission.DUMP

Intended Use: Allows application to retrieve internal status of the system.

How can be abused: Malicious applications may retrieve a wide variety of private and secure information that they should never normally need.

android.permission.GET_TASKS

Intended Use: Allows application to retrieve information about currently and recently running tasks.

How can be abused: May allow malicious applications to discover private information about other applications.

android.permission.INSTALL_PACKAGES

Intended Use: Allows an application to install new or updated Android packages.

How can be abused: Malicious applications can use this to add new applications with arbitrarily powerful permissions.

android.permission.PROCESS_OUTGOING_CALLS

Intended Use: Allows application to process outgoing calls and change the number to be dialled.

How can be abused: Malicious applications may monitor, redirect or prevent outgoing calls.

android.permission.READ_CALENDAR

Intended Use: Allows an application to read all of the calendar events stored on your phone.

How can be abused: Malicious applications can use this to send your calendar events to other people.

android.permission.READ_CONTACTS

Intended Use: Allows an application to read all of the contact (address) data stored on your phone.

How can be abused: Malicious applications can use this to send your data to other people.

android.permission.READ_SMS

Intended Use: Allows application to read SMS messages stored on your phone or SIM card.

How can be abused: Malicious applications may read your confidential messages.

android.permission.RECEIVE_MMS

Intended Use: Allows application to receive and process MMS messages.

How can be abused: Malicious applications may monitor your messages or delete them without showing them to you.

android.permission.REORDER_TASKS

Intended Use: Allows an application to move tasks to the foreground and background.

How can be abused: Malicious applications can force themselves to the front without your control.

android.permission.SET_DEBUG_APP

Intended Use: Allows an application to turn on debugging for another application.

How can be abused: Malicious applications can use this to kill other applications.

android.permission.SET_PREFERRED_APPLICATIONS

Intended Use: Allows an application to modify your preferred applications.

How can be abused: This can allow malicious applications to silently change the applications that are run, spoofing your existing applications to collect private data from you.

android.permission.SYSTEM_ALERT_WINDOW

Intended Use: Allows an application to show system-alert windows.

How can be abused: Malicious applications can take over the entire screen of the phone.

android.permission.WRITE_CALENDAR

Intended Use: Allows an application to add or change the events on your calendar, which may send emails to guests.

How can be abused: Malicious applications can use this to erase or modify your calendar events or to send emails to guests.

android.permission.WRITE_CONTACTS

Intended Use: Allows an application to modify the contact (address) data stored on your phone.

How can be abused: Malicious applications can use this to erase or modify your contact data.

android.permission.BROADCAST_STICKY

send sticky broadcast

Allows an application to send sticky broadcasts, which remain after the broadcast ends. These are broadcasts whose data is held by the system after being finished, so that clients can quickly retrieve that data without having to wait for the next broadcast.

Malicious applications can make the phone slow or unstable by causing it to use too much memory.

Code sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Register for the battery changed event
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
// Intent is sticky so using null as receiver works fine
// return value contains the status
Intent batteryStatus = this.registerReceiver(null, filter);
// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL;
boolean isFull = status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;

Source: https://aruljack.blogspot.in/2012/10/what-is-meant-by-stick-intents.html

Deprecated methods

Sticky broadcasts should not be used. They provide no security (anyone can access them), no protection (anyone can modify them), and many other problems. The recommended pattern is to use a non-sticky broadcast to report that something has changed, with another mechanism for apps to retrieve the current value whenever desired.

These methods were deprecated in API level 21:

android.permission.DISABLE_KEYGUARD

disable key lock

Allows an application to disable the key lock and any associated password security. A legitimate example of this is the phone disabling the key lock when receiving an incoming phone call, then re-enabling the key lock when the call is finished.

Protection level: normal

Usage in AndroidManifest.xml:

1
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"></uses-permission>

KeyguardManager.KeyguardLock

This class was deprecated in API level 13.
Use FLAG_DISMISS_KEYGUARD and/or FLAG_SHOW_WHEN_LOCKED instead; this allows you to seamlessly hide the keyguard as your application moves in and out of the foreground and does not require that any special permissions be requested. Handle returned by newKeyguardLock(String) that allows you to disable / reenable the keyguar

https://developer.android.com/reference/android/app/KeyguardManager.KeyguardLock.html

Sample usage:

1
2
3
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Activity.KEYGUARD_SERVICE);
KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.disableKeyguard();

1
2
3
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Activity.KEYGUARD_SERVICE);
KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.reenableKeyguard();

android.permission.CONNECTIVITY_INTERNAL

use privileged ConnectivityManager API

Allows an internal user to use privileged ConnectivityManager API

Note about protection level

This permission has protection level: signatureOrSystem. It is a permission that the system grants only to applications that are in the Android system image or that are signed with the same certificate as the application that declared the permission.

*”signatureOrSystem” permissions are no longer available to all apps residing en the /system partition. Instead, there is a new /system/priv-app directory, and only apps whose APKs are in that directory are allowed to use signatureOrSystem permissions without sharing the platform cert. This will reduce the surface area for possible exploits of system- bundled applications to try to gain access to permission-guarded operations.

The ApplicationInfo.FLAG_SYSTEM flag continues to mean what it is says in the documentation: it indicates that the application apk was bundled on the /system partition. A new hidden flag FLAG_PRIVILEGED has been introduced that reflects the actual right to access these permissions.*

Privileged apps are stored in /system/priv-app folder.

Usage in AndroidManifest.xml:

1
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />

Failure obtaining that permission before use will cause crash:

1
... setWifiApEnabled: InvocationTarget: java.lang.reflect.InvocationTargetException, java.lang.SecurityException: ConnectivityService: Neither user 10291 nor current process has android.permission.CONNECTIVITY_INTERNAL.

Sources: