User Description of Security Detection API in Google Play Service

Keywords: Google Android xml SDK

This blog mainly records how to use Google Play Service for security detection.

1 Principles of Use of Google Play Service
Google Play Service provides a large number of API s for users to use.
In order to enable applications to integrate Google's latest products and functions at low cost.

When using Google Play Service, the basic principles are shown in the following figure, where:
1. When using Google Play Service,
The Client Library provided by Google must be integrated.
Through Client Library, applications can communicate with Google Play Service on IPC.

2. Google Play Service is a service running independently in the background of the system.
Published with Google Play Store.

3. Google Play Store is responsible for updating Google Play Service.

As you can see, Google introduced Client Library.
Decouple the application from Google Play Service.

So even if you don't modify the application, just update Google Play Services.
Apps will be able to use the latest version of Google's functionality.
At the same time, Client Library can also carry out access control and other related operations.

2 Integrated Client Library

To use Client Library, we first need to load Google Repository using Android Studio's SDK Manager.
As shown in the figure above, the main thing is to check the red line part, and then click download.

After downloading Google Repository, you only need to modify the build.gradle file corresponding to the application Module.
Load the corresponding library file.

For example:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    .....................

    //Adding dependencies on play-service
    //After the update of Google Play Service, modify the corresponding version number
    compile 'com.google.android.gms:play-services:11.0.1'
}

Note here that com.google.android.gms:play-services introduces a collection of all the API s of Google Play Service.

When we only need specific API interfaces, we can introduce separate libraries.
This can reduce the volume of the application and avoid too many methods in the application.

For example, when only SafetyNet is needed, you can compile only:

com.google.android.gms:play-services-safetynet:11.0.1

Currently, all the independent API libraries defined by Play Service can be referred to in the following links:
https://developers.google.com/android/guides/setup

3 Ensure that Google Play Service is available on the device
When the application imports Client Library, we can use the interface provided by Client Library in the application.

However, we know that an application will be installed on different vendors'machines.
Some manufacturers'ROM s do not integrate with Google Play Store, let alone Google Play Service.

Therefore, when an application needs to use the functionality of Google Play Service,
The first thing we need to do is to determine whether the current equipment has the corresponding capabilities.

At present, judging whether Google Play Service is available from the documentation point of view,
The best way is to use the interface provided by Google ApiAvailability in Client Library.

The specific approach is similar to:

//If the entire application relies on Google Play Service
//So make a judgment on MainActivity's onResume interface
//If only part of the functionality depends on the service, it can be judged before it is used.
@Override
protected void onResume() {
    super.onResume();

    //Get an example of Google ApiAvailability
    GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();

    //Use interface to determine whether device supports Google Play Service
    int ret = googleApiAvailability.isGooglePlayServicesAvailable(this);

    //If supported, the result will be returned to SUCCESS
    if (ret == ConnectionResult.SUCCESS) {
        Log.d(TAG, "This phone has available google service inside");
    .............
    } else {
        Log.e(TAG, "This phone don't have available google service inside");

        //When not supported, you can use getErrorDialog to get a prompt box with the second parameter passing in an error message
        //The prompt box will generate different styles based on the error message
        //For example, when I tested it myself, the first Google Play Service was not the latest.
        //The dialog box displays this information and provides keys for downloading updates.
        googleApiAvailability.getErrorDialog(this, ret, 0).show();
    }
}

4 Access Services Using Google API Client
When device supports Google Play Service, the application can use the corresponding functions.

As shown in the figure below, the application actually has to use the Google API Client in Client Library to access specific services.

As can be seen from the figure, the Google API Client serves as a bridge between applications and services, responsible for specific communication details.

The way to get the Google API Client in an application is as follows:

private GoogleApiClient mGoogleApiClient;

//If the Google ApiClient object is created before the onStart function of Activity is called,
//AutoManage allows the object to automatically connect to Google PlayService after onStart
private void connectGooglePlayService() {
    Log.d(TAG, "connect to google play service");

    mGoogleApiClient = new GoogleApiClient.Builder(this)
        //Here, using automatic management and manual connection, you can get the client and actively call its connection interface.
        //Pass in FailedListener to handle failures
        .enableAutoManage(this, new FailedListener())
        //We focus on security detection, so we can add SafetyNet.API
        //But this usage is now deprecated
        .addApi(SafetyNet.API)
        //Add a callback object and notify if the connection succeeds or fails
        .addConnectionCallbacks(new ConnectionCallback())
        .build();
}

private class FailedListener implements GoogleApiClient.OnConnectionFailedListener {
    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.e(TAG, "connect failed: " + connectionResult);
        //You can do some error handling
        ..............
    }
}

private class ConnectionCallback implements GoogleApiClient.ConnectionCallbacks {
    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.d(TAG, "connect to google play service success");
        //Successful connection and corresponding work
        ...........
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.e(TAG, "connect to google play service fail");
        //Connection failure, processing
        ...........
    }
}

Once the application creates a Google ApiClient and successfully connects to Google Play Service,
You can use the corresponding function through the corresponding API.

5 Safety Net Security Detection Function
Next, let's take SafetyNet as an example to see how to use the security detection function provided by Google Play Service.

5.1 Attestation API
From the results of documents and tests, the Attestation API is mainly used to detect:
The security and compatibility of the Android running environment of the device is similar to CTS testing.

It should be noted that:
Before using this API, you need to go to Google Developers Console.
Open the Android Device Verification API and apply for the corresponding Apk key.
Specific Web addresses can be searched by themselves, and can be applied by Google Mail.

After applying for the key value, you need to add the following in the application's AndroidManifest.xml:

<meta-data android:name="com.google.android.safetynet.ATTEST_API_KEY"
    <!--Here*Hidden part of the information--> 
    android:value="AIzaSyCPVFlNC********-*********2NcvGi2sj0" />

When the key value is added, the application can use the attest interface of SafetyNet.

Here we take an old-fashioned invocation method as an example to introduce the use of API:

private void attest() {
    // attest interface requires a token, and the length is not less than 16 bytes
    byte[] nonce = getRequestNonce(); // Should be at least 16 bytes in length.

    //As you can see, mGoogle ApiClient is passed into the interface
    //As you can imagine, its underlying implementation relies on mGoogle ApiClient to communicate
    SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
            //Set up the callback interface and notify the connection service when the result is returned
            //You can see that this is an asynchronous callback design.
            .setResultCallback(new ResultCallback<SafetyNetApi.AttestationResult>() {
                @Override
                public void onResult(SafetyNetApi.AttestationResult result) {
                    Status status = result.getStatus();

                    //After the server successfully returns the result, the information can be retrieved.
                    if (status.isSuccess()) {
                        //Attest results in a JWS string that needs to be parsed locally
                        String ret = result.getJwsResult();
                        Log.d(TAG, "attest success with ret: " + ret);
                        ..............
                    } else {
                        // An error occurred while communicating with the service.
                        Log.d(TAG, "attest fail");
                    }
                }
            });
}

private byte[] getRequestNonce() {
    String token = "ATTest " + System.currentTimeMillis() + TAG;
    return token.getBytes();
}

It should be noted that:
The API's daily access to Google services is limited (presumably because it's free).

In fact, the Google API console counts the number of requests per API, as shown in the following figure:

5.2 Safe Browsing API
Safe Browsing API is mainly used for detection:
Is there a potential threat to a url's corresponding address?

Like the Attestation API, you also need to go to Google Developers Console before using the API.
Open the Safe Browsing API and apply for the corresponding App key value.

When using AndroidManifest.xml, you need to add something similar to the following:

<meta-data android:name="com.google.android.safetynet.API_KEY"
    <!--For the same application, use differentAPIWhen sharing the samekey -->
    <!--Google The server side also counts this API Visits-->
    android:value="AIzaSyCPVFlNC********-*********2NcvGi2sj0" />

The way the API is used is similar to:

private void browseTest(String url) {
    //It's easy to see that the specific usage is similar to Attest.
    SafetyNet.SafetyNetApi.lookupUri(mGoogleApiClient, url,
            //Specify the type of threat of concern
            SafeBrowsingThreat.TYPE_POTENTIALLY_HARMFUL_APPLICATION,
            SafeBrowsingThreat.TYPE_SOCIAL_ENGINEERING)
            //Similarly, the callback interface is defined
            .setResultCallback(new ResultCallback<SafetyNetApi.SafeBrowsingResult>() {
                    @Override
                    public void onResult(SafetyNetApi.SafeBrowsingResult result) {
                        Status status = result.getStatus();

                        if ((status != null) && status.isSuccess()) {
                            // Indicates communication with the service was successful.
                            // Identify any detected threats.
                            Log.d(TAG, "browse test success");

                            //List < Safe Browsing Threat > can be retrieved from the returned results
                            //Safe Browsing Threat can get the type of threat through getThreatType
                            mHandler.sendMessage(
                                    mHandler.obtainMessage(BROWSE, result.getDetectedThreats()));
                        } else {
                            // An error occurred. Let the user proceed without warning.
                            Log.e(TAG, "browse test fail: " + result.getStatus());
                            ...........
                        }
                    }
            });
}

5.3 Verify Apps API
Finally, let's look at the Verify Apps API of Google Play Service.

This API is mainly used for detection:
Are there harmful applications installed on mobile phones?

Unlike the previous two APIs, the Feature corresponding to the terminal must be turned on before using the API.

The corresponding code is similar to:

private void enableVerifyFeature() {
    if (!mEnableVerifyFeature) {
        //Get an instance of SafeNetClient, which should encapsulate Google ApiClient at the bottom of the object        
        mSafetyNetClient = SafetyNet.getClient(this);

        //SafeNetClient has two interfaces related to the features required by Verify App
        //IsVerifyApps Enabled and enableVerifyApps, respectively
        //Among them, isVerify Apps Enabled is mainly used to determine whether Feature is turned on or not.
        //When enableVerifyApps judges that Feature is not open, dialog will pop up to remind the user to open (if Feature is turned on, dialog will not pop up)
        mSafetyNetClient.enableVerifyApps()
                .addOnCompleteListener(new OnCompleteListener<SafetyNetApi.VerifyAppsUserResponse>() {
                    @Override
                    public void onComplete(Task<SafetyNetApi.VerifyAppsUserResponse> task) {
                        if (task.isSuccessful()) {
                            SafetyNetApi.VerifyAppsUserResponse result = task.getResult();

                            //After the user clicks on the dialog or feature, he enters the branch.
                            if (result.isVerifyAppsEnabled()) {
                                Log.d(TAG, "The user gave consent " +
                                        "to enable the Verify Apps feature.");
                                ..................
                            } else {
                                Log.e(TAG, "The user didn't give consent " +
                                        "to enable the Verify Apps feature.");
                                ...............
                            }
                        } else {
                            Log.e(TAG, "A general error occurred.");
                            ...............
                        }
                    }
                });
    }
}

Once Verify App's corresponding Feature is turned on, we can use Verify App's API, where the old-fashioned usage is similar to:

private void listHarmfulApps() {
    //Also dependent on Google ApiClient
    SafetyNet.SafetyNetApi.listHarmfulApps(mGoogleApiClient)
            //After getting the result, call back
            .setResultCallback(new ResultCallbacks<SafetyNetApi.HarmfulAppsResult>() {
                @Override
                public void onSuccess(@NonNull SafetyNetApi.HarmfulAppsResult harmfulAppsResult) {
                    Log.d(TAG, "list harm full success");
                    ..............
                }

                @Override
                public void onFailure(@NonNull Status status) {
                    Log.d(TAG, "list harm full fail: " + status);
                }
            });
}

Finally, let's take a look at the new calls recommended by official documents:

private void listHarmfulApps() {
    mSafetyNetClient.listHarmfulApps()
        //Add Listener callback
        .addOnCompleteListener(new OnCompleteListener<SafetyNetApi.HarmfulAppsResponse>() {
                @Override
                public void onComplete(Task<SafetyNetApi.HarmfulAppsResponse> task) {
                    Log.d(TAG, "listHarmfulApps onComplete");

                    //Interface returns valid results
                    if (task.isSuccessful()) {
                        SafetyNetApi.HarmfulAppsResponse result = task.getResult();
                        long scanTimeMs = result.getLastScanTimeMs();
                        Log.d(TAG, "list harmful apps used time: " + scanTimeMs);

                        //Get a list of harmful applications
                        List<HarmfulAppsData> appList = result.getHarmfulAppsList();
                        if (appList.isEmpty()) {
                            Log.d(TAG, "There are no known " +
                                    "potentially harmful apps installed.");
                        } else {
                            Log.e(TAG,
                                    "Potentially harmful apps are installed!");

                            //Getting information about harmful applications
                            for (HarmfulAppsData harmfulApp : appList) {
                                Log.e(TAG, "Information about a harmful app:");
                                Log.e(TAG,
                                        "  APK: " + harmfulApp.apkPackageName);
                                Log.e(TAG,
                                        "  SHA-256: " + harmfulApp.apkSha256);

                                // Categories are defined in VerifyAppsConstants.
                                Log.e(TAG,
                                        "  Category: " + harmfulApp.apkCategory);
                           }
                        }
                    } else {
                        Log.e(TAG, "An error occurred. ");
                    }
                }
        //Add a failed callback interface
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                e.printStackTrace();
            }
        });
}

It should be noted that:
In my own tests, I found that the listHarmfulApps interface was not stable, and occasionally encounter an error coded for 1204 on Android 6.0.
Referring to Google's API documentation, we found that this is the internal error of the Verify App API.
In addition, the interface on Android 7.0 platform does not seem to be effective (I do not know if it is related to specific vendors).

In the end, I had to tuck up the interface. The ability of the interface was simply slag and it was almost impossible to detect the threat samples effectively.

6 Summary
This document mainly introduces the principle and integration method of Google Play Service.
Taking SafetyNet API as an example, this paper introduces how to use the functions provided by Google Play Service.

Reference
https://developers.google.com/android/guides/overview
https://developer.android.com/training/safetynet

Posted by alin19 on Wed, 19 Jun 2019 14:08:41 -0700