Custom props!

This commit is contained in:
chiteroman 2023-11-25 17:31:37 +01:00
parent 27c00e2ce7
commit edffde9b1a
No known key found for this signature in database
GPG Key ID: 15FF53015D426D8E
7 changed files with 24804 additions and 49 deletions

View File

@ -28,7 +28,7 @@ It injects a classes.dex file to modify few fields in android.os.Build class. Al
it creates a hook to modify system properties.
The purpose of the module is to avoid a hardware attestation.
## About 'pif.prop' file
## About 'pif.json' file
You can modify this file to spoof android.os.Build fields in GMS unstable process and try to pass Device verdict.
You can't use values from recent devices due this devices must use a hardware attestation.

24689
app/src/main/cpp/json.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,19 @@
#include <android/log.h>
#include <sys/system_properties.h>
#include <unistd.h>
#include <string_view>
#include <map>
#include <vector>
#include <fstream>
#include "zygisk.hpp"
#include "dobby.h"
#include "json.hpp"
#define DEX_FILE_PATH "/data/adb/modules/playintegrityfix/classes.dex"
#define PROP_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__)
#define FIRST_API_LEVEL "25"
#define SECURITY_PATCH "2017-08-05"
static std::string FIRST_API_LEVEL, SECURITY_PATCH;
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
@ -27,10 +28,18 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
std::string_view prop(name);
if (prop.ends_with("api_level")) {
value = FIRST_API_LEVEL;
if (FIRST_API_LEVEL == "NULL") {
value = nullptr;
} else {
value = FIRST_API_LEVEL.c_str();
}
LOGD("[%s] -> %s", name, value);
} else if (prop.ends_with("security_patch")) {
value = SECURITY_PATCH;
if (SECURITY_PATCH == "NULL") {
value = nullptr;
} else {
value = SECURITY_PATCH.c_str();
}
LOGD("[%s] -> %s", name, value);
}
@ -90,23 +99,44 @@ public:
return;
}
ssize_t size;
char buffer[10000];
int fd = api->connectCompanion();
long size;
char buffer[1024];
size = read(fd, buffer, sizeof(buffer));
while ((size = read(fd, buffer, sizeof(buffer))) > 0) {
if (size > 0) {
moduleDex.insert(moduleDex.end(), buffer, buffer + size);
} else {
LOGD("Couldn't load classes.dex file in memory");
close(fd);
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
lseek(fd, 0, SEEK_SET);
size = read(fd, buffer, sizeof(buffer));
if (size > 0) {
jsonStr.insert(jsonStr.end(), buffer, buffer + size);
} else {
LOGD("Couldn't load pif.json file in memory");
}
close(fd);
LOGD("Received from socket %lu bytes!", moduleDex.size());
LOGD("Received 'classes.dex' file from socket: %d bytes",
static_cast<int>(moduleDex.size()));
LOGD("Received 'pif.json' file from socket: %d bytes", static_cast<int>(jsonStr.size()));
}
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (moduleDex.empty()) return;
readJson();
inject();
doHook();
@ -120,6 +150,21 @@ private:
zygisk::Api *api = nullptr;
JNIEnv *env = nullptr;
std::vector<char> moduleDex;
std::string jsonStr;
void readJson() {
nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false);
auto getStringFromJson = [&json](const std::string &key) {
return json.contains(key) && !json[key].is_null() ? json[key].get<std::string>()
: "NULL";
};
SECURITY_PATCH = getStringFromJson("SECURITY_PATCH");
FIRST_API_LEVEL = getStringFromJson("FIRST_API_LEVEL");
json.clear();
}
void inject() {
LOGD("get system classloader");
@ -144,34 +189,34 @@ private:
auto entryClass = (jclass) entryClassObj;
LOGD("read json");
auto readProps = env->GetStaticMethodID(entryClass, "readJson",
"(Ljava/lang/String;)V");
auto javaStr = env->NewStringUTF(jsonStr.c_str());
env->CallStaticVoidMethod(entryClass, readProps, javaStr);
LOGD("call init");
auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V");
env->CallStaticVoidMethod(entryClass, entryInit);
moduleDex.clear();
jsonStr.clear();
}
};
static void companion(int fd) {
FILE *file = fopen("/data/adb/modules/playintegrityfix/classes.dex", "rb");
std::ifstream dex(DEX_FILE_PATH, std::ios::binary);
std::ifstream prop(PROP_FILE_PATH);
if (file == nullptr) {
write(fd, nullptr, 0);
return;
}
std::vector<char> dexVector((std::istreambuf_iterator<char>(dex)),
std::istreambuf_iterator<char>());
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
std::vector<char> propVector((std::istreambuf_iterator<char>(prop)),
std::istreambuf_iterator<char>());
std::vector<char> vector(size);
fread(vector.data(), 1, size, file);
fclose(file);
write(fd, vector.data(), size);
vector.clear();
write(fd, dexVector.data(), dexVector.size());
lseek(fd, 0, SEEK_SET);
write(fd, propVector.data(), propVector.size());
}
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)

View File

@ -1,29 +1,40 @@
package es.chiteroman.playintegrityfix;
import android.os.Build;
import android.util.JsonReader;
import android.util.Log;
import java.io.IOException;
import java.io.StringReader;
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.HashMap;
import java.util.Map;
public final class EntryPoint {
private static final String PRODUCT = "sailfish";
private static final String DEVICE = "sailfish";
private static final String MANUFACTURER = "Google";
private static final String BRAND = "google";
private static final String MODEL = "Pixel";
private static final String FINGERPRINT = "google/sailfish/sailfish:7.1.2/NZH54D/4146044:user/release-keys";
private static final String SECURITY_PATCH = "2017-08-05";
private static final Map<String, String> map = new HashMap<>();
public static void init() {
spoofProvider();
spoofDevice();
}
public static void readJson(String data) {
try (JsonReader reader = new JsonReader(new StringReader(data))) {
reader.beginObject();
while (reader.hasNext()) {
map.put(reader.nextName(), reader.nextString());
}
reader.endObject();
} catch (IOException e) {
LOG("Couldn't read JSON from Zygisk: " + e);
}
}
private static void spoofProvider() {
final String KEYSTORE = "AndroidKeyStore";
@ -52,13 +63,15 @@ public final class EntryPoint {
}
static void spoofDevice() {
setProp("PRODUCT", PRODUCT);
setProp("DEVICE", DEVICE);
setProp("MANUFACTURER", MANUFACTURER);
setProp("BRAND", BRAND);
setProp("MODEL", MODEL);
setProp("FINGERPRINT", FINGERPRINT);
setVersionProp("SECURITY_PATCH", SECURITY_PATCH);
if (map.isEmpty()) return;
setProp("PRODUCT", map.get("PRODUCT"));
setProp("DEVICE", map.get("DEVICE"));
setProp("MANUFACTURER", map.get("MANUFACTURER"));
setProp("BRAND", map.get("BRAND"));
setProp("MODEL", map.get("MODEL"));
setProp("FINGERPRINT", map.get("FINGERPRINT"));
setVersionProp("SECURITY_PATCH", map.get("SECURITY_PATCH"));
}
private static void setProp(String name, String value) {

View File

@ -10,8 +10,7 @@ https://t.me/playintegrityfix
If you want an undetectable resetprop, use Kitsune Magisk.
If you want to spoof your own props, modify the props in source code and build by yourself.
Or you can use unstable build, you can download in GitHub repo.
Should work and don't crash nothing.
Maybe in a future I do a custom spoof version... But I won't release it as stable build.
I recommend to clear GMS data and cache before reboot.

View File

@ -1,7 +1,6 @@
id=playintegrityfix
name=Play Integrity Fix
version=v13.7
versionCode=137
version=v1.1-PROPS
versionCode=1
author=chiteroman
description=Fix CTS profile (SafetyNet) and DEVICE verdict (Play Integrity).
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json

10
module/pif.json Normal file
View File

@ -0,0 +1,10 @@
{
"PRODUCT": "taimen",
"DEVICE": "taimen",
"MANUFACTURER": "Google",
"BRAND": "google",
"MODEL": "Pixel 2 XL",
"FINGERPRINT": "google/taimen/taimen:8.1.0/OPM4.171019.021.R1/4833808:user/release-keys",
"SECURITY_PATCH": "2018-07-05",
"FIRST_API_LEVEL": "25"
}