mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-12 21:27:41 +02:00
Add SafetyNet check
This commit is contained in:
@ -5,9 +5,11 @@ import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.utils.Async;
|
||||
import com.topjohnwu.magisk.utils.Logger;
|
||||
import com.topjohnwu.magisk.utils.SafetyNetHelper;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class SplashActivity extends AppCompatActivity {
|
||||
@ -36,6 +38,24 @@ public class SplashActivity extends AppCompatActivity {
|
||||
.putBoolean("hosts", Utils.itemExist(false, "/magisk/.core/hosts"))
|
||||
.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.LoadModules(prefs) {
|
||||
|
@ -178,10 +178,10 @@ public class Async {
|
||||
Logger.dev("FlashZip: File created successfully - " + mCachedFile.getPath());
|
||||
in.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e(Logger.LOG_TAG, "FlashZip: Invalid Uri");
|
||||
Log.e(Logger.TAG, "FlashZip: Invalid Uri");
|
||||
throw 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;
|
||||
}
|
||||
}
|
||||
|
@ -4,23 +4,29 @@ import android.util.Log;
|
||||
|
||||
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 void debug(String msg) {
|
||||
Log.d(DEBUG_TAG, msg);
|
||||
}
|
||||
|
||||
public static void dev(String msg, Object... args) {
|
||||
if (devLog) {
|
||||
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 {
|
||||
Log.d(LOG_TAG, String.format(msg, args));
|
||||
Log.d(DEV_TAG, String.format(msg, args));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void dev(String msg) {
|
||||
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);
|
||||
}
|
Reference in New Issue
Block a user