Android Process Survival Series: (1) Use Activity to Promote Privileges

Posted by Tuck on Tue, 18 Jun 2019 00:30:02 +0200

http://www.jianshu.com/p/4ff700faab78

The secret of QQ's long-term survival was to monitor the user's unlock screen operation, activate a transparent window of a pixel when the screen was locked, and destroy the Activity when it was unlocked. I have to admire the programmed ape of goose factory. He can come up with such a wonderful plan! Regardless of how you upgrade Android, the solution is really a trial and error! Users have no perception, the goal has been achieved, the best of both worlds.

First verify: cmd input in lock screen state

adb shell dumpsys activity activities

Let's take a look at dump's output: the top-level Task message, package name: com.tencent.reading. I looked at the list of applications. It's "Daily Express", and it's Tencent.


dump output

We can see that Office Acticity is the top-level Activity. With curiosity, we found the directory where the source code is located. Referring to the relevant code, we wrote a demo ourselves.

The concrete realization is divided into two steps:

  1. Create a transparent Activity
  2. Monitor user unlock screen operation
Step 1: Create a transparent Activity

1. Setting window s properties in onCreate method

Window window = getWindow();
window.setGravity(Gravity.TOP | Gravity.LEFT);
LayoutParams attributes = window.getAttributes();
attributes.x = 0;
attributes.y = 0;
attributes.height = 1;
attributes.width = 1;
window.setAttributes(attributes);

2. Set some attributes in Manifest, including excluding the latest task list, transparent topics, startup mode, etc.

<activity
    android:name="com.silence.keeplive.onepx.OnePxActivity"    
    android:excludeFromRecents="true"
    android:exported="false"
    android:finishOnTaskLaunch="false"
    android:launchMode="singleInstance"
    android:process=":main"
    android:theme="@android:style/Theme.Translucent"    
    android:configChanges="keyboardHidden|orientation|screenSize" />

3. Handling Touch and Destruction Events
Since Activity is activated when the screen is locked, it can never exist after the user lights up the screen. We're going to do something with Activity's life cycle. For the sake of security, we also need to deal with the touching events of Activity, just destroy Activity directly.

@Override
protected void onResume() {    
  super.onResume();    
  if (isScreenOn()) {       
      finishSelf();    
  }
}

@Override
protected void onDestroy() {    
  super.onDestroy();    
  if (instance != null && instance.get() == this) {        
    instance = null;   
  }
}

public void finishSelf() {    
  if (!isFinishing()) {        
    finish();    
  }  
}

private boolean isScreenOn() {    
    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);        
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {            
        return powerManager.isInteractive();        
    } else {            
        return powerManager.isScreenOn();        
     }    
 }
Step 2: Monitor the user's unlock screen operation

To achieve this function, three broadcasts should be registered:

<action android:name="android.intent.action.USER_PRESENT"/>
<action android:name="android.intent.action.SCREEN_ON"/>
<action android:name="android.intent.action.SCREEN_OFF"/>

But there is a problem here. USER_PRESENT can be registered statically, and the other two can only receive broadcasts through dynamic registration. We will register all three broadcasts dynamically and statically, but it won't do any harm. Then it receives the broadcast event on the switch screen and processes the Activity.

if ("android.intent.action.SCREEN_OFF".equals(action)) {    
    Log.i(TAG, "Lock screen opens one pixel");
    CheckTopTask.setForeground(context);    
    mHandler.postDelayed(mCheckTopTask, 3000);
} else if ("android.intent.action.USER_PRESENT".equals(action) || "android.intent.action.SCREEN_ON".equals(action)) {   
    Log.i(TAG, "Open screen and close one pixel");    
    OnePxActivity onePxActivity = OnePxActivity.instance != null ? OnePxActivity.instance.get() : null;   
    if (onePxActivity != null) {        
        onePxActivity.finishSelf();   
    }    
    mHandler.removeCallbacks(mCheckTopTask);
}

Here's a place where there's a chicken burglar. Since transparent Activity has been activated when the screen is locked, why do you have to perform a task in three seconds? For fear that other applications will adopt the same solution, cover it with Activeness on top of us. This task is to check whether the current activity is in the foreground after three seconds, and if not, start again to get the focus of the foreground. I think that's what Tencent did, capitalized "clothes"!

The final function is that Activity occupies the front desk for us to ensure that the process is not killed. The back desk Service is working hard to achieve the goal.~~

Topics: Android shell