You've already forked PlayIntegrityFork
mirror of
https://github.com/osm0sis/PlayIntegrityFork.git
synced 2025-09-06 06:37:06 +00:00
v13.1
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.KeyStoreSpi;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class CustomKeyStoreSpi extends KeyStoreSpi {
|
||||
public static volatile KeyStoreSpi keyStoreSpi;
|
||||
|
||||
@Override
|
||||
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||
return keyStoreSpi.engineGetKey(alias, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate[] engineGetCertificateChain(String alias) {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (e.getClassName().toLowerCase(Locale.ROOT).contains("droidguard")) {
|
||||
EntryPoint.LOG("DroidGuard detected!");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
return keyStoreSpi.engineGetCertificateChain(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate engineGetCertificate(String alias) {
|
||||
return keyStoreSpi.engineGetCertificate(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date engineGetCreationDate(String alias) {
|
||||
return keyStoreSpi.engineGetCreationDate(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException {
|
||||
keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException {
|
||||
keyStoreSpi.engineSetKeyEntry(alias, key, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
|
||||
keyStoreSpi.engineSetCertificateEntry(alias, cert);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineDeleteEntry(String alias) throws KeyStoreException {
|
||||
keyStoreSpi.engineDeleteEntry(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> engineAliases() {
|
||||
return keyStoreSpi.engineAliases();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean engineContainsAlias(String alias) {
|
||||
return keyStoreSpi.engineContainsAlias(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int engineSize() {
|
||||
return keyStoreSpi.engineSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean engineIsKeyEntry(String alias) {
|
||||
return keyStoreSpi.engineIsKeyEntry(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean engineIsCertificateEntry(String alias) {
|
||||
return keyStoreSpi.engineIsCertificateEntry(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String engineGetCertificateAlias(Certificate cert) {
|
||||
return keyStoreSpi.engineGetCertificateAlias(cert);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineStore(OutputStream stream, char[] password) throws CertificateException, IOException, NoSuchAlgorithmException {
|
||||
keyStoreSpi.engineStore(stream, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineLoad(InputStream stream, char[] password) throws CertificateException, IOException, NoSuchAlgorithmException {
|
||||
keyStoreSpi.engineLoad(stream, password);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import java.security.Provider;
|
||||
|
||||
public final class CustomProvider extends Provider {
|
||||
|
||||
CustomProvider(Provider provider) {
|
||||
super(provider.getName(), provider.getVersion(), provider.getInfo());
|
||||
putAll(provider);
|
||||
this.put("KeyStore.AndroidKeyStore", CustomKeyStoreSpi.class.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Service getService(String type, String algorithm) {
|
||||
EntryPoint.spoofDevice();
|
||||
return super.getService(type, algorithm);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.KeyStoreSpi;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.Properties;
|
||||
|
||||
public final class EntryPoint {
|
||||
private static final Properties props = new Properties();
|
||||
private static final File file = new File("/data/data/com.google.android.gms/cache/pif.prop");
|
||||
|
||||
public static void init() {
|
||||
|
||||
try (FileInputStream inputStream = new FileInputStream(file)) {
|
||||
props.load(inputStream);
|
||||
LOG("Loaded " + props.size() + " properties!");
|
||||
} catch (IOException e) {
|
||||
LOG("Couldn't load properties file: " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
spoofDevice();
|
||||
spoofProvider();
|
||||
}
|
||||
|
||||
private static void spoofProvider() {
|
||||
final String KEYSTORE = "AndroidKeyStore";
|
||||
|
||||
try {
|
||||
Provider provider = Security.getProvider(KEYSTORE);
|
||||
KeyStore keyStore = KeyStore.getInstance(KEYSTORE);
|
||||
|
||||
Field f = keyStore.getClass().getDeclaredField("keyStoreSpi");
|
||||
f.setAccessible(true);
|
||||
CustomKeyStoreSpi.keyStoreSpi = (KeyStoreSpi) f.get(keyStore);
|
||||
f.setAccessible(false);
|
||||
|
||||
CustomProvider customProvider = new CustomProvider(provider);
|
||||
Security.removeProvider(KEYSTORE);
|
||||
Security.insertProviderAt(customProvider, 1);
|
||||
|
||||
LOG("Spoof KeyStoreSpi and Provider done!");
|
||||
|
||||
} catch (KeyStoreException e) {
|
||||
LOG("Couldn't find KeyStore: " + e);
|
||||
} catch (NoSuchFieldException e) {
|
||||
LOG("Couldn't find field: " + e);
|
||||
} catch (IllegalAccessException e) {
|
||||
LOG("Couldn't change access of field: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void spoofDevice() {
|
||||
props.forEach((field, value) -> setProp((String) field, (String) value));
|
||||
}
|
||||
|
||||
private static void setProp(String name, String value) {
|
||||
try {
|
||||
Field field = Build.class.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
String oldValue = (String) field.get(null);
|
||||
field.set(null, value);
|
||||
field.setAccessible(false);
|
||||
if (value.equals(oldValue)) return;
|
||||
LOG(String.format("[%s]: %s -> %s", name, oldValue, value));
|
||||
} catch (NoSuchFieldException e) {
|
||||
LOG(String.format("Couldn't find '%s' field name.", name));
|
||||
} catch (IllegalAccessException e) {
|
||||
LOG(String.format("Couldn't modify '%s' field value.", name));
|
||||
}
|
||||
}
|
||||
|
||||
public static void LOG(String msg) {
|
||||
Log.d("PIF/Java", msg);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user