Skip to content

Commit

Permalink
v15.8
Browse files Browse the repository at this point in the history
  • Loading branch information
chiteroman committed Feb 16, 2024
1 parent 3753ee5 commit 6a9f5f8
Show file tree
Hide file tree
Showing 14 changed files with 214 additions and 185 deletions.
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
applicationId = "es.chiteroman.playintegrityfix"
minSdk = 26
targetSdk = 34
versionCode = 15702
versionName = "v15.7.2"
versionCode = 15800
versionName = "v15.8"
multiDexEnabled = false

buildFeatures {
Expand All @@ -30,14 +30,23 @@ android {
externalNativeBuild {
cmake {
arguments += "-DANDROID_STL=none"
arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel"
arguments += "-DCMAKE_BUILD_TYPE=Release"
arguments += "-DPlugin.Android.BionicLinkerUtil=ON"

cFlags += "-fvisibility=hidden"
cFlags += "-fvisibility-inlines-hidden"
cFlags += "-flto"
cFlags += "-O3"
cFlags += "-mllvm -polly"

cppFlags += "-std=c++20"
cppFlags += "-fno-exceptions"
cppFlags += "-fno-rtti"
cppFlags += "-fvisibility=hidden"
cppFlags += "-fvisibility-inlines-hidden"
cppFlags += "-flto"
cppFlags += "-O3"
cppFlags += "-mllvm -polly"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ add_library(${CMAKE_PROJECT_NAME} SHARED main.cpp)

add_subdirectory(Dobby)

target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC log dobby_static)
target_link_libraries(${CMAKE_PROJECT_NAME} log dobby_static)
2 changes: 1 addition & 1 deletion app/src/main/cpp/Dobby/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ option(Plugin.SymbolResolver "Enable symbol resolver" ON)

option(Plugin.ImportTableReplace "Enable import table replace " OFF)

option(Plugin.Android.BionicLinkerUtil "Enable android bionic linker util" OFF)
option(Plugin.Android.BionicLinkerUtil "Enable android bionic linker util" ON)

option(DOBBY_BUILD_EXAMPLE "Build example" OFF)

Expand Down
52 changes: 32 additions & 20 deletions app/src/main/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <android/log.h>
#include <unistd.h>
#include <fstream>
#include <filesystem>
#include "dobby.h"
#include "json.hpp"
#include "zygisk.hpp"
Expand Down Expand Up @@ -108,6 +110,11 @@ class PlayIntegrityFix : public zygisk::ModuleBase {

auto name = env->GetStringUTFChars(args->nice_name, nullptr);

if (name == nullptr) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

bool isGmsUnstable = std::string_view(name) == "com.google.android.gms.unstable";

env->ReleaseStringUTFChars(args->nice_name, name);
Expand Down Expand Up @@ -151,16 +158,16 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
close(fd);

json = nlohmann::json::parse(jsonVector, nullptr, false, true);

parseJson();
}

void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (dexVector.empty() || json.empty()) return;

parseJson();
injectDex();

doHook();

injectDex();
}

void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
Expand Down Expand Up @@ -274,31 +281,36 @@ static void companion(int fd) {

std::vector<char> dexVector, jsonVector;

FILE *dexFile = fopen(CLASSES_DEX, "rb");
std::ifstream dexFile(CLASSES_DEX, std::ios::binary);

if (dexFile) {
fseek(dexFile, 0, SEEK_END);
dexSize = ftell(dexFile);
fseek(dexFile, 0, SEEK_SET);
if (dexFile.is_open()) {
dexFile.seekg(0, std::ios::end);
dexSize = dexFile.tellg();
dexFile.seekg(0, std::ios::beg);

dexVector.resize(dexSize);
fread(dexVector.data(), 1, dexSize, dexFile);

fclose(dexFile);
dexFile.read(dexVector.data(), dexSize);
dexFile.close();
}

FILE *jsonFile = fopen(PIF_JSON, "rb");
if (jsonFile == nullptr) jsonFile = fopen(PIF_JSON_DEFAULT, "rb");
std::ifstream jsonFile;

if (jsonFile) {
fseek(jsonFile, 0, SEEK_END);
jsonSize = ftell(jsonFile);
fseek(jsonFile, 0, SEEK_SET);
if (std::filesystem::exists(PIF_JSON)) {
jsonFile = std::ifstream(PIF_JSON);
} else if (std::filesystem::exists(PIF_JSON_DEFAULT)) {
jsonFile = std::ifstream(PIF_JSON_DEFAULT);
} else {
LOGD("Couldn't open pif.json file. Did you remove it?");
}

jsonVector.resize(jsonSize);
fread(jsonVector.data(), 1, jsonSize, jsonFile);
if (jsonFile.is_open()) {
jsonFile.seekg(0, std::ios::end);
jsonSize = jsonFile.tellg();
jsonFile.seekg(0, std::ios::beg);

fclose(jsonFile);
jsonVector.resize(jsonSize);
jsonFile.read(jsonVector.data(), jsonSize);
jsonFile.close();
}

write(fd, &dexSize, sizeof(long));
Expand Down
221 changes: 116 additions & 105 deletions app/src/main/java/es/chiteroman/playintegrityfix/CustomKeyStoreSpi.java
Original file line number Diff line number Diff line change
@@ -1,105 +1,116 @@
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 = null;

@Override
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
return keyStoreSpi.engineGetKey(alias, password);
}

@Override
public Certificate[] engineGetCertificateChain(String alias) {
for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
if (stackTraceElement.getClassName().toLowerCase(Locale.US).contains("droidguard")) {
EntryPoint.LOG("DroidGuard call certificate chain! Throw exception.");
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);
}
}
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.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;

public final class CustomKeyStoreSpi extends KeyStoreSpi {
public static KeyStoreSpi keyStoreSpi = null;
private static final String EAT_OID = "1.3.6.1.4.1.11129.2.1.25";
private static final String ASN1_OID = "1.3.6.1.4.1.11129.2.1.17";
private static final String KNOX_OID = "1.3.6.1.4.1.236.11.3.23.7";

@Override
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
return keyStoreSpi.engineGetKey(alias, password);
}

@Override
public Certificate[] engineGetCertificateChain(String alias) {
Certificate[] certificates = keyStoreSpi.engineGetCertificateChain(alias);
// This shouldn't happen...
if (certificates == null) {
throw new UnsupportedOperationException();
}
// Is certificate chain ?
if (certificates.length > 1) {
if (certificates[0] instanceof X509Certificate x509Certificate) {
if (x509Certificate.getExtensionValue(EAT_OID) != null || x509Certificate.getExtensionValue(ASN1_OID) != null || x509Certificate.getExtensionValue(KNOX_OID) != null) {
EntryPoint.LOG("Certificate chain with dangerous extensions. Throw exception!");
throw new UnsupportedOperationException();
}
}
}
return certificates;
}

@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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@

public final class CustomProvider extends Provider {

public CustomProvider(Provider provider, boolean spoof) {
public CustomProvider(Provider provider) {
super(provider.getName(), provider.getVersion(), provider.getInfo());

putAll(provider);

if (spoof) put("KeyStore.AndroidKeyStore", CustomKeyStoreSpi.class.getName());
put("KeyStore.AndroidKeyStore", CustomKeyStoreSpi.class.getName());
}

@Override
public synchronized Service getService(String type, String algorithm) {
EntryPoint.LOG(String.format("Service: '%s' | Algorithm: '%s'", type, algorithm));

if ("AndroidKeyStore".equals(algorithm)) EntryPoint.spoofFields();
new Thread(EntryPoint::spoofFields).start();

return super.getService(type, algorithm);
}
Expand Down
Loading

0 comments on commit 6a9f5f8

Please sign in to comment.