Add SafetyNet check
This commit is contained in:
parent
3c33f7d294
commit
442e840a53
@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 25
|
compileSdkVersion 25
|
||||||
buildToolsVersion "25.0.1"
|
buildToolsVersion "25.0.2"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.topjohnwu.magisk"
|
applicationId "com.topjohnwu.magisk"
|
||||||
@ -49,9 +49,9 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
compile 'com.android.support:recyclerview-v7:25.0.1'
|
compile 'com.android.support:recyclerview-v7:25.1.0'
|
||||||
compile 'com.android.support:cardview-v7:25.0.1'
|
compile 'com.android.support:cardview-v7:25.1.0'
|
||||||
compile 'com.android.support:design:25.0.1'
|
compile 'com.android.support:design:25.1.0'
|
||||||
compile 'com.jakewharton:butterknife:8.4.0'
|
compile 'com.jakewharton:butterknife:8.4.0'
|
||||||
compile 'com.google.code.gson:gson:2.8.0'
|
compile 'com.google.code.gson:gson:2.8.0'
|
||||||
compile 'com.github.clans:fab:1.6.4'
|
compile 'com.github.clans:fab:1.6.4'
|
||||||
@ -59,5 +59,6 @@ dependencies {
|
|||||||
compile 'com.madgag.spongycastle:prov:1.54.0.0'
|
compile 'com.madgag.spongycastle:prov:1.54.0.0'
|
||||||
compile 'com.madgag.spongycastle:pkix:1.54.0.0'
|
compile 'com.madgag.spongycastle:pkix:1.54.0.0'
|
||||||
compile 'com.madgag.spongycastle:pg:1.54.0.0'
|
compile 'com.madgag.spongycastle:pg:1.54.0.0'
|
||||||
|
compile 'com.google.android.gms:play-services-safetynet:10.0.1'
|
||||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
|
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,10 @@
|
|||||||
android:resource="@xml/file_paths" />
|
android:resource="@xml/file_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.version"
|
||||||
|
android:value="@integer/google_play_services_version" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -5,9 +5,11 @@ import android.content.SharedPreferences;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.Async;
|
import com.topjohnwu.magisk.utils.Async;
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
import com.topjohnwu.magisk.utils.Logger;
|
||||||
|
import com.topjohnwu.magisk.utils.SafetyNetHelper;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
public class SplashActivity extends AppCompatActivity {
|
public class SplashActivity extends AppCompatActivity {
|
||||||
@ -36,6 +38,24 @@ public class SplashActivity extends AppCompatActivity {
|
|||||||
.putBoolean("hosts", Utils.itemExist(false, "/magisk/.core/hosts"))
|
.putBoolean("hosts", Utils.itemExist(false, "/magisk/.core/hosts"))
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
|
// Simple POC for checking SN status
|
||||||
|
new SafetyNetHelper(getApplicationContext()) {
|
||||||
|
@Override
|
||||||
|
public void handleResults(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case -1:
|
||||||
|
Toast.makeText(mContext, "SN: Error", Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
Toast.makeText(mContext, "SN: Fail", Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Toast.makeText(mContext, "SN: Success", Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.requestTest();
|
||||||
|
|
||||||
new Async.CheckUpdates(prefs).exec();
|
new Async.CheckUpdates(prefs).exec();
|
||||||
|
|
||||||
new Async.LoadModules(prefs) {
|
new Async.LoadModules(prefs) {
|
||||||
|
@ -178,10 +178,10 @@ public class Async {
|
|||||||
Logger.dev("FlashZip: File created successfully - " + mCachedFile.getPath());
|
Logger.dev("FlashZip: File created successfully - " + mCachedFile.getPath());
|
||||||
in.close();
|
in.close();
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.e(Logger.LOG_TAG, "FlashZip: Invalid Uri");
|
Log.e(Logger.TAG, "FlashZip: Invalid Uri");
|
||||||
throw e;
|
throw e;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(Logger.LOG_TAG, "FlashZip: Error in creating file");
|
Log.e(Logger.TAG, "FlashZip: Error in creating file");
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,29 @@ import android.util.Log;
|
|||||||
|
|
||||||
public class Logger {
|
public class Logger {
|
||||||
|
|
||||||
public static final String LOG_TAG = "Magisk: DEV";
|
public static final String TAG = "Magisk";
|
||||||
|
public static final String DEV_TAG = "Magisk: DEV";
|
||||||
|
public static final String DEBUG_TAG = "Magisk: DEBUG";
|
||||||
|
|
||||||
public static boolean logShell, devLog;
|
public static boolean logShell, devLog;
|
||||||
|
|
||||||
|
public static void debug(String msg) {
|
||||||
|
Log.d(DEBUG_TAG, msg);
|
||||||
|
}
|
||||||
|
|
||||||
public static void dev(String msg, Object... args) {
|
public static void dev(String msg, Object... args) {
|
||||||
if (devLog) {
|
if (devLog) {
|
||||||
if (args.length == 1 && args[0] instanceof Throwable) {
|
if (args.length == 1 && args[0] instanceof Throwable) {
|
||||||
Log.d(LOG_TAG, msg, (Throwable) args[0]);
|
Log.d(DEV_TAG, msg, (Throwable) args[0]);
|
||||||
} else {
|
} else {
|
||||||
Log.d(LOG_TAG, String.format(msg, args));
|
Log.d(DEV_TAG, String.format(msg, args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dev(String msg) {
|
public static void dev(String msg) {
|
||||||
if (devLog) {
|
if (devLog) {
|
||||||
Log.d(LOG_TAG, msg);
|
Log.d(DEV_TAG, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.Base64;
|
||||||
|
|
||||||
|
import com.google.android.gms.common.ConnectionResult;
|
||||||
|
import com.google.android.gms.common.api.GoogleApiClient;
|
||||||
|
import com.google.android.gms.common.api.Status;
|
||||||
|
import com.google.android.gms.safetynet.SafetyNet;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public abstract class SafetyNetHelper
|
||||||
|
implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
|
||||||
|
|
||||||
|
private GoogleApiClient mGoogleApiClient;
|
||||||
|
protected Context mContext;
|
||||||
|
|
||||||
|
public SafetyNetHelper(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
|
||||||
|
.addApi(SafetyNet.API)
|
||||||
|
.addConnectionCallbacks(this)
|
||||||
|
.addOnConnectionFailedListener(this)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConnectionFailed(@NonNull ConnectionResult result) {
|
||||||
|
Logger.dev("SN: Google API fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConnected(@Nullable Bundle bundle) {
|
||||||
|
Logger.dev("SN: Google API Connected");
|
||||||
|
safetyNetCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConnectionSuspended(int i) {
|
||||||
|
Logger.dev("SN: Google API Suspended");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestTest() {
|
||||||
|
// Connect Google Service
|
||||||
|
mGoogleApiClient.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void safetyNetCheck() {
|
||||||
|
// Create nonce
|
||||||
|
byte[] nonce = new byte[24];
|
||||||
|
new SecureRandom().nextBytes(nonce);
|
||||||
|
|
||||||
|
Logger.dev("SN: Check with nonce: " + Base64.encodeToString(nonce, Base64.DEFAULT));
|
||||||
|
|
||||||
|
// Call SafetyNet
|
||||||
|
SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
|
||||||
|
.setResultCallback(result -> {
|
||||||
|
Status status = result.getStatus();
|
||||||
|
if (status.isSuccess()) {
|
||||||
|
String json = new String(Base64.decode(result.getJwsResult().split("\\.")[1], Base64.DEFAULT));
|
||||||
|
Logger.dev("SN: Response: " + json);
|
||||||
|
try {
|
||||||
|
JSONObject decoded = new JSONObject(json);
|
||||||
|
handleResults(decoded.getBoolean("ctsProfileMatch") ? 1 : 0);
|
||||||
|
} catch (JSONException ignored) {}
|
||||||
|
} else {
|
||||||
|
Logger.dev("SN: No response");
|
||||||
|
handleResults(-1);
|
||||||
|
}
|
||||||
|
// Disconnect
|
||||||
|
mGoogleApiClient.disconnect();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void handleResults(int i);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user