You've already forked TrickyStore
mirror of
https://github.com/5ec1cff/TrickyStore.git
synced 2025-09-06 06:37:07 +00:00
Refine spoof build vars
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
|||||||
[submodule "module/src/main/cpp/external/LSPlt"]
|
[submodule "module/src/main/cpp/external/LSPlt"]
|
||||||
path = module/src/main/cpp/external/LSPlt
|
path = module/src/main/cpp/external/LSPlt
|
||||||
url = https://github.com/LSPosed/LSPlt
|
url = https://github.com/LSPosed/LSPlt
|
||||||
[submodule "module/src/main/cpp/external/glaze"]
|
|
||||||
path = module/src/main/cpp/external/glaze
|
|
||||||
url = https://github.com/stephenberry/glaze
|
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -51,21 +51,19 @@ edit your spoof config.
|
|||||||
|
|
||||||
Here is an example of spoof config:
|
Here is an example of spoof config:
|
||||||
|
|
||||||
```json
|
```
|
||||||
{
|
MANUFACTURER=Google
|
||||||
"manufacturer": "Google",
|
MODEL=Pixel
|
||||||
"model": "Pixel",
|
FINGERPRINT=google/sailfish/sailfish:8.1.0/OPM1.171019.011/4448085:user/release-keys
|
||||||
"fingerprint": "google/sailfish/sailfish:8.1.0/OPM1.171019.011/4448085:user/release-keys",
|
BRAND=google
|
||||||
"brand": "google",
|
PRODUCT=sailfish
|
||||||
"product": "sailfish",
|
DEVICE=sailfish
|
||||||
"device": "sailfish",
|
RELEASE=8.1.0
|
||||||
"release": "8.1.0",
|
ID=OPM1.171019.011
|
||||||
"id": "OPM1.171019.011",
|
INCREMENTAL=4448085
|
||||||
"incremental": "4448085",
|
TYPE=user
|
||||||
"security_patch": "2017-12-05",
|
TAGS=release-keys
|
||||||
"type": "user",
|
SECURITY_PATCH=2017-12-05
|
||||||
"tags": "release-keys"
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Support TEE broken devices
|
## Support TEE broken devices
|
||||||
|
|||||||
@@ -16,12 +16,6 @@ val commitHash: String by rootProject.extra
|
|||||||
val abiList: List<String> by rootProject.extra
|
val abiList: List<String> by rootProject.extra
|
||||||
val androidMinSdkVersion: Int by rootProject.extra
|
val androidMinSdkVersion: Int by rootProject.extra
|
||||||
|
|
||||||
val releaseFlags = arrayOf(
|
|
||||||
"-O3", "-flto",
|
|
||||||
"-Wno-unused", "-Wno-unused-parameter",
|
|
||||||
"-Wl,--exclude-libs,ALL", "-Wl,-icf=all,--lto-O3", "-Wl,-s,-x,--gc-sections"
|
|
||||||
)
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
ndk {
|
ndk {
|
||||||
@@ -43,45 +37,24 @@ android {
|
|||||||
|
|
||||||
cmaker {
|
cmaker {
|
||||||
default {
|
default {
|
||||||
val cmakeArgs = arrayOf(
|
arguments += arrayOf(
|
||||||
"-DANDROID_STL=none",
|
"-DANDROID_STL=none",
|
||||||
|
"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON",
|
||||||
|
"-DANDROID_ALLOW_UNDEFINED_SYMBOLS=ON",
|
||||||
"-DMODULE_NAME=$moduleId",
|
"-DMODULE_NAME=$moduleId",
|
||||||
)
|
"-DCMAKE_CXX_STANDARD=23",
|
||||||
arguments += cmakeArgs
|
"-DCMAKE_C_STANDARD=23",
|
||||||
abiFilters("arm64-v8a", "x86_64")
|
"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON",
|
||||||
}
|
"-DCMAKE_VISIBILITY_INLINES_HIDDEN=ON",
|
||||||
buildTypes {
|
"-DCMAKE_CXX_VISIBILITY_PRESET=hidden",
|
||||||
when (it.name) {
|
"-DCMAKE_C_VISIBILITY_PRESET=hidden",
|
||||||
"release" -> {
|
)
|
||||||
cppFlags += releaseFlags
|
abiFilters(*abiList.toTypedArray())
|
||||||
cFlags += releaseFlags
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val commonFlags = arrayOf(
|
|
||||||
// Silent noisy warnings
|
|
||||||
"-Wno-reorder-ctor",
|
|
||||||
"-Wno-overloaded-virtual",
|
|
||||||
"-Wno-unused-function",
|
|
||||||
"-Wno-unused-but-set-variable",
|
|
||||||
"-Wno-unused-private-field",
|
|
||||||
"-Wno-missing-braces",
|
|
||||||
"-Wno-delete-non-abstract-non-virtual-dtor",
|
|
||||||
"-Wno-unused-variable",
|
|
||||||
"-Wno-sometimes-uninitialized",
|
|
||||||
"-Wno-logical-op-parentheses",
|
|
||||||
"-Wno-shift-count-overflow",
|
|
||||||
"-Wno-deprecated-declarations",
|
|
||||||
"-Wno-infinite-recursion",
|
|
||||||
"-Wno-format",
|
|
||||||
"-Wno-deprecated-volatile",
|
|
||||||
)
|
|
||||||
cppFlags += commonFlags
|
|
||||||
cFlags += commonFlags
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(libs.cxx)
|
implementation(libs.cxx)
|
||||||
}
|
}
|
||||||
|
|
||||||
androidComponents.onVariants { variant ->
|
androidComponents.onVariants { variant ->
|
||||||
|
|||||||
@@ -1,24 +1,9 @@
|
|||||||
cmake_minimum_required(VERSION 3.28)
|
cmake_minimum_required(VERSION 3.28)
|
||||||
project(sample)
|
project(trick_store)
|
||||||
|
|
||||||
if (CCACHE)
|
|
||||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
|
|
||||||
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
find_package(cxx REQUIRED CONFIG)
|
find_package(cxx REQUIRED CONFIG)
|
||||||
link_libraries(cxx::cxx)
|
link_libraries(cxx::cxx)
|
||||||
|
|
||||||
find_program(CCACHE ccache)
|
|
||||||
|
|
||||||
set(LINKER_FLAGS "-ffixed-x18 -Wl,--hash-style=both")
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
|
|
||||||
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
|
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
|
||||||
|
|
||||||
add_library(elf_util STATIC elf_util/elf_util.cpp)
|
add_library(elf_util STATIC elf_util/elf_util.cpp)
|
||||||
add_library(my_logging STATIC logging/logging.cpp)
|
add_library(my_logging STATIC logging/logging.cpp)
|
||||||
|
|
||||||
@@ -32,7 +17,6 @@ target_link_libraries(elf_util lsplt my_logging)
|
|||||||
|
|
||||||
# libutils stub
|
# libutils stub
|
||||||
add_library(utils SHARED binder/stub_utils.cpp)
|
add_library(utils SHARED binder/stub_utils.cpp)
|
||||||
target_compile_options(utils PRIVATE -fvisibility=default -fno-visibility-inlines-hidden)
|
|
||||||
target_include_directories(utils PUBLIC binder/include)
|
target_include_directories(utils PUBLIC binder/include)
|
||||||
|
|
||||||
# libbinder stub
|
# libbinder stub
|
||||||
@@ -42,11 +26,9 @@ target_link_libraries(binder PRIVATE utils)
|
|||||||
|
|
||||||
add_executable(libinject.so inject/main.cpp inject/utils.cpp)
|
add_executable(libinject.so inject/main.cpp inject/utils.cpp)
|
||||||
target_link_libraries(libinject.so PRIVATE lsplt my_logging)
|
target_link_libraries(libinject.so PRIVATE lsplt my_logging)
|
||||||
target_compile_options(libinject.so PRIVATE -fvisibility=hidden -fvisibility-inlines-hidden)
|
|
||||||
|
|
||||||
add_library(${MODULE_NAME} SHARED binder_interceptor.cpp)
|
add_library(${MODULE_NAME} SHARED binder_interceptor.cpp)
|
||||||
target_link_libraries(${MODULE_NAME} PRIVATE log binder utils elf_util my_logging)
|
target_link_libraries(${MODULE_NAME} PRIVATE log binder utils elf_util my_logging)
|
||||||
target_compile_options(${MODULE_NAME} PRIVATE -fvisibility=hidden -fvisibility-inlines-hidden)
|
|
||||||
|
|
||||||
add_library(tszygisk SHARED zygisk/main.cpp)
|
add_library(tszygisk SHARED zygisk/main.cpp)
|
||||||
target_link_libraries(tszygisk PRIVATE log my_logging glaze::glaze)
|
target_link_libraries(tszygisk PRIVATE log my_logging)
|
||||||
|
|||||||
2
module/src/main/cpp/external/CMakeLists.txt
vendored
2
module/src/main/cpp/external/CMakeLists.txt
vendored
@@ -8,5 +8,3 @@ target_include_directories(lsplt PUBLIC LSPlt/lsplt/src/main/jni/include)
|
|||||||
target_include_directories(lsplt PRIVATE LSPlt/lsplt/src/main/jni)
|
target_include_directories(lsplt PRIVATE LSPlt/lsplt/src/main/jni)
|
||||||
target_link_libraries(lsplt PUBLIC my_logging)
|
target_link_libraries(lsplt PUBLIC my_logging)
|
||||||
# end lsplt
|
# end lsplt
|
||||||
|
|
||||||
add_subdirectory(glaze)
|
|
||||||
|
|||||||
1
module/src/main/cpp/external/glaze
vendored
1
module/src/main/cpp/external/glaze
vendored
Submodule module/src/main/cpp/external/glaze deleted from c365ba48fb
@@ -13,8 +13,8 @@
|
|||||||
#define LOGD(...) logging::log(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
#define LOGD(...) logging::log(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||||
#define LOGV(...) logging::log(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
#define LOGV(...) logging::log(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define LOGD(...)
|
#define LOGD(...) (void)0
|
||||||
#define LOGV(...)
|
#define LOGV(...) (void)0
|
||||||
#endif
|
#endif
|
||||||
#define LOGI(...) logging::log(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
#define LOGI(...) logging::log(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||||
#define LOGW(...) logging::log(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
|
#define LOGW(...) logging::log(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#include <cstdlib>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
#include <array>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <memory>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <tuple>
|
||||||
|
#include <unistd.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "glaze/glaze.hpp"
|
|
||||||
#include "logging.hpp"
|
#include "logging.hpp"
|
||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
|
|
||||||
@@ -14,21 +18,51 @@ using zygisk::AppSpecializeArgs;
|
|||||||
using zygisk::ServerSpecializeArgs;
|
using zygisk::ServerSpecializeArgs;
|
||||||
using namespace std::string_view_literals;
|
using namespace std::string_view_literals;
|
||||||
|
|
||||||
struct spoof_config {
|
template <size_t N> struct FixedString {
|
||||||
std::string manufacturer{"Google"};
|
// NOLINTNEXTLINE(*-explicit-constructor)
|
||||||
std::string model{"Pixel"};
|
[[maybe_unused]] consteval inline FixedString(const char (&str)[N]) {
|
||||||
std::string fingerprint{"google/sailfish/sailfish:8.1.0/OPM1.171019.011/4448085:user/release-keys"};
|
std::copy_n(str, N, data);
|
||||||
std::string brand{"google"};
|
}
|
||||||
std::string product{"sailfish"};
|
consteval inline FixedString() = default;
|
||||||
std::string device{"sailfish"};
|
char data[N] = {};
|
||||||
std::string release{"8.1.0"};
|
|
||||||
std::string id{"OPM1.171019.011"};
|
|
||||||
std::string incremental{"4448085"};
|
|
||||||
std::string security_patch{"2017-12-05"};
|
|
||||||
std::string type{"user"};
|
|
||||||
std::string tags{"release-keys"};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using PropValue = std::array<char, 127>;
|
||||||
|
|
||||||
|
template<typename T, FixedString Field, bool Version=false>
|
||||||
|
struct Prop {
|
||||||
|
using Type [[maybe_unused]] = T;
|
||||||
|
bool has_value{false};
|
||||||
|
PropValue value {};
|
||||||
|
|
||||||
|
[[maybe_unused]] inline consteval static const char *getField() {
|
||||||
|
return Field.data;
|
||||||
|
}
|
||||||
|
[[maybe_unused]] inline consteval static bool isVersion() {
|
||||||
|
return Version;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(Prop<void, "", false>) % sizeof(void*) == 0);
|
||||||
|
|
||||||
|
using SpoofConfig = std::tuple<
|
||||||
|
Prop<jstring, "MANUFACTURER">,
|
||||||
|
Prop<jstring, "MODEL">,
|
||||||
|
Prop<jstring, "FINGERPRINT">,
|
||||||
|
Prop<jstring, "BRAND">,
|
||||||
|
Prop<jstring, "PRODUCT">,
|
||||||
|
Prop<jstring, "DEVICE">,
|
||||||
|
Prop<jstring, "RELEASE", true>,
|
||||||
|
Prop<jstring, "ID">,
|
||||||
|
Prop<jstring, "INCREMENTAL", true>,
|
||||||
|
Prop<jstring, "TYPE">,
|
||||||
|
Prop<jstring, "TAGS">,
|
||||||
|
Prop<jstring, "SECURITY_PATCH", true>,
|
||||||
|
Prop<jstring, "BRAND">,
|
||||||
|
Prop<jstring, "HARDWARE">,
|
||||||
|
Prop<jint, "DEVICE_INITIAL_SDK_INT", true>
|
||||||
|
>;
|
||||||
|
|
||||||
|
|
||||||
ssize_t xread(int fd, void *buffer, size_t count) {
|
ssize_t xread(int fd, void *buffer, size_t count) {
|
||||||
ssize_t total = 0;
|
ssize_t total = 0;
|
||||||
@@ -43,7 +77,7 @@ ssize_t xread(int fd, void *buffer, size_t count) {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t xwrite(int fd, void *buffer, size_t count) {
|
ssize_t xwrite(int fd, const void *buffer, size_t count) {
|
||||||
ssize_t total = 0;
|
ssize_t total = 0;
|
||||||
char *buf = (char *)buffer;
|
char *buf = (char *)buffer;
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@@ -56,6 +90,11 @@ ssize_t xwrite(int fd, void *buffer, size_t count) {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void trim(std::string_view &str) {
|
||||||
|
str.remove_prefix(std::min(str.find_first_not_of(" \t"), str.size()));
|
||||||
|
str.remove_suffix(std::min(str.size() - str.find_last_not_of(" \t") - 1, str.size()));
|
||||||
|
}
|
||||||
|
|
||||||
class TrickyStore : public zygisk::ModuleBase {
|
class TrickyStore : public zygisk::ModuleBase {
|
||||||
public:
|
public:
|
||||||
void onLoad(Api *api, JNIEnv *env) override {
|
void onLoad(Api *api, JNIEnv *env) override {
|
||||||
@@ -66,27 +105,15 @@ public:
|
|||||||
void preAppSpecialize(AppSpecializeArgs *args) override {
|
void preAppSpecialize(AppSpecializeArgs *args) override {
|
||||||
api_->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
api_->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
int enabled = 0;
|
int enabled = 0;
|
||||||
spoof_config spoofConfig{};
|
SpoofConfig spoofConfig{};
|
||||||
{
|
auto fd = api_->connectCompanion();
|
||||||
auto fd = api_->connectCompanion();
|
if (fd >= 0) [[likely]] {
|
||||||
if (fd >= 0) [[likely]] {
|
// read enabled
|
||||||
// read enabled
|
xread(fd, &enabled, sizeof(enabled));
|
||||||
xread(fd, &enabled, sizeof(enabled));
|
if (enabled) {
|
||||||
if (enabled) {
|
xread(fd, &spoofConfig, sizeof(spoofConfig));
|
||||||
size_t bufferSize = 0;
|
|
||||||
std::string buffer;
|
|
||||||
// read size first
|
|
||||||
xread(fd, &bufferSize, sizeof(bufferSize));
|
|
||||||
// resize and receive
|
|
||||||
buffer.resize(bufferSize);
|
|
||||||
xread(fd, buffer.data(), bufferSize);
|
|
||||||
// parse
|
|
||||||
if (glz::read_json(spoofConfig, buffer)) [[unlikely]] {
|
|
||||||
LOGE("[preAppSpecialize] spoofConfig parse error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enabled) return;
|
if (!enabled) return;
|
||||||
@@ -106,18 +133,21 @@ public:
|
|||||||
auto buildClass = env_->FindClass("android/os/Build");
|
auto buildClass = env_->FindClass("android/os/Build");
|
||||||
auto buildVersionClass = env_->FindClass("android/os/Build$VERSION");
|
auto buildVersionClass = env_->FindClass("android/os/Build$VERSION");
|
||||||
|
|
||||||
setField(buildClass, "MANUFACTURER", std::move(spoofConfig.manufacturer));
|
std::apply([this, &buildClass, &buildVersionClass](auto &&... args) {
|
||||||
setField(buildClass, "MODEL", std::move(spoofConfig.model));
|
((!args.has_value ||
|
||||||
setField(buildClass, "FINGERPRINT", std::move(spoofConfig.fingerprint));
|
(setField<typename std::remove_cvref_t<decltype(args)>::Type>(
|
||||||
setField(buildClass, "BRAND", std::move(spoofConfig.brand));
|
std::remove_cvref_t<decltype(args)>::isVersion() ? buildVersionClass
|
||||||
setField(buildClass, "PRODUCT", std::move(spoofConfig.product));
|
: buildClass,
|
||||||
setField(buildClass, "DEVICE", std::move(spoofConfig.device));
|
std::remove_cvref_t<decltype(args)>::getField(),
|
||||||
setField(buildVersionClass, "RELEASE", std::move(spoofConfig.release));
|
args.value) &&
|
||||||
setField(buildClass, "ID", std::move(spoofConfig.id));
|
(LOGI("%s set %s to %s",
|
||||||
setField(buildVersionClass, "INCREMENTAL", std::move(spoofConfig.incremental));
|
std::remove_cvref_t<decltype(args)>::isVersion() ? "VERSION" : "Build",
|
||||||
setField(buildVersionClass, "SECURITY_PATCH", std::move(spoofConfig.security_patch));
|
std::remove_cvref_t<decltype(args)>::getField(),
|
||||||
setField(buildClass, "TYPE", std::move(spoofConfig.type));
|
args.value.data()), true))
|
||||||
setField(buildClass, "TAGS", std::move(spoofConfig.tags));
|
? void(0)
|
||||||
|
: LOGE("Failed to set %s to %s", std::remove_cvref_t<decltype(args)>::getField(),
|
||||||
|
args.value.data())), ...);
|
||||||
|
}, spoofConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
env_->ReleaseStringUTFChars(args->nice_name, nice_name);
|
env_->ReleaseStringUTFChars(args->nice_name, nice_name);
|
||||||
@@ -129,63 +159,126 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Api *api_;
|
Api *api_{nullptr};
|
||||||
JNIEnv *env_;
|
JNIEnv *env_{nullptr};
|
||||||
|
|
||||||
inline void setField(jclass clazz, const char* field, std::string&& value) {
|
template<typename T>
|
||||||
|
inline bool setField(jclass clazz, const char* field, const PropValue& value);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool setField<jstring>(jclass clazz, const char* field, const PropValue& value) {
|
||||||
auto id = env_->GetStaticFieldID(clazz, field, "Ljava/lang/String;");
|
auto id = env_->GetStaticFieldID(clazz, field, "Ljava/lang/String;");
|
||||||
env_->SetStaticObjectField(clazz, id, env_->NewStringUTF(value.c_str()));
|
if (!id) return false;
|
||||||
|
env_->SetStaticObjectField(clazz, id, env_->NewStringUTF(value.data()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool setField<jint>(jclass clazz, const char* field, const PropValue& value) {
|
||||||
|
auto id = env_->GetStaticFieldID(clazz, field, "I");
|
||||||
|
if (!id) return false;
|
||||||
|
char *p = nullptr;
|
||||||
|
jint x = static_cast<jint>(strtol(value.data(), &p, 10));
|
||||||
|
if (p == value.data()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
env_->SetStaticIntField(clazz, id, x);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool setField<jboolean>(jclass clazz, const char* field, const PropValue& value) {
|
||||||
|
auto id = env_->GetStaticFieldID(clazz, field, "Z");
|
||||||
|
if (!id) return false;
|
||||||
|
auto x = std::string_view(value.data());
|
||||||
|
if (x == "1" || x == "true") {
|
||||||
|
env_->SetStaticBooleanField(clazz, id, JNI_TRUE);
|
||||||
|
} else if (x == "0" || x == "false") {
|
||||||
|
env_->SetStaticBooleanField(clazz, id, JNI_FALSE);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void write_spoof_configs(const struct spoof_config& spoofConfig) {
|
|
||||||
std::string buffer{};
|
|
||||||
|
|
||||||
if (glz::write<glz::opts{.prettify = true}>(spoofConfig, buffer)) [[unlikely]] {
|
|
||||||
// This should NEVER happen, but it's not the reason we don't handle the case
|
|
||||||
LOGE("[write_spoof_configs] Failed to parse json to std::string");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove old one first
|
|
||||||
std::filesystem::remove("/data/adb/tricky_store/spoof_build_vars"sv);
|
|
||||||
FILE* file = fopen("/data/adb/tricky_store/spoof_build_vars", "w");
|
|
||||||
if (!file) [[unlikely]] {
|
|
||||||
LOGE("[write_spoof_configs] Failed to open spoof_build_vars");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fprintf(file, "%s", buffer.c_str()) < 0) [[unlikely]] {
|
|
||||||
LOGE("[write_spoof_configs] Failed to write spoof_build_vars");
|
|
||||||
fclose(file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
LOGI("[write_spoof_configs] write done!");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void companion_handler(int fd) {
|
static void companion_handler(int fd) {
|
||||||
int enabled = access("/data/adb/tricky_store/spoof_build_vars", F_OK) == 0;
|
constexpr auto kSpoofConfigFile = "/data/adb/tricky_store/spoof_build_vars"sv;
|
||||||
|
constexpr auto kDefaultSpoofConfig =
|
||||||
|
R"EOF(MANUFACTURER=Google
|
||||||
|
MODEL=Pixel
|
||||||
|
FINGERPRINT=google/sailfish/sailfish:8.1.0/OPM1.171019.011/4448085:user/release-keys
|
||||||
|
BRAND=google
|
||||||
|
PRODUCT=sailfish
|
||||||
|
DEVICE=sailfish
|
||||||
|
RELEASE=8.1.0
|
||||||
|
ID=OPM1.171019.011
|
||||||
|
INCREMENTAL=4448085
|
||||||
|
TYPE=user
|
||||||
|
TAGS=release-keys
|
||||||
|
SECURITY_PATCH=2017-12-05
|
||||||
|
)EOF"sv;
|
||||||
|
struct stat st{};
|
||||||
|
int enabled = stat(kSpoofConfigFile.data(), &st) == 0;
|
||||||
xwrite(fd, &enabled, sizeof(enabled));
|
xwrite(fd, &enabled, sizeof(enabled));
|
||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spoof_config spoofConfig{};
|
int cfd = -1;
|
||||||
auto ec = glz::read_file_json(spoofConfig, "/data/adb/tricky_store/spoof_build_vars"sv, std::string{});
|
if (st.st_size == 0) {
|
||||||
if (ec) [[unlikely]] {
|
cfd = open(kSpoofConfigFile.data(), O_RDWR);
|
||||||
LOGW("[companion_handler] Failed to parse spoof_build_vars, writing and using default spoof config...");
|
if (cfd > 0) {
|
||||||
write_spoof_configs(spoofConfig);
|
xwrite(fd, kDefaultSpoofConfig.data(), kDefaultSpoofConfig.size());
|
||||||
|
lseek(cfd, 0, SEEK_SET);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cfd = open(kSpoofConfigFile.data(), O_RDONLY);
|
||||||
|
}
|
||||||
|
if (cfd < 0) {
|
||||||
|
LOGE("[companion_handler] Failed to open spoof_build_vars");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SpoofConfig spoof_config{};
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_ptr<FILE, decltype([](auto *f) {fclose(f); })> config {fdopen(cfd, "r")};
|
||||||
|
char *l = nullptr;
|
||||||
|
struct finally { char *l; ~finally() { free(l); } } finally{l};
|
||||||
|
size_t len = 0;
|
||||||
|
ssize_t n;
|
||||||
|
while ((n = getline(&l, &len, config.get())) != -1) {
|
||||||
|
if (n == 0) continue;
|
||||||
|
std::string_view line{l, static_cast<size_t>(n)};
|
||||||
|
if (line.back() == '\n') {
|
||||||
|
line.remove_suffix(1);
|
||||||
|
}
|
||||||
|
auto d = line.find_first_of('=');
|
||||||
|
if (d == std::string_view::npos) {
|
||||||
|
LOGW("Ignore invalid line %.*s", static_cast<int>(line.size()), line.data());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto key = line.substr(0, d);
|
||||||
|
trim(key);
|
||||||
|
auto value = line.substr(d + 1);
|
||||||
|
trim(value);
|
||||||
|
std::apply([&key, &value](auto &&... args) {
|
||||||
|
((key == std::remove_cvref_t<decltype(args)>::getField() &&
|
||||||
|
(LOGD("Read config: %.*s = %.*s", static_cast<int>(key.size()), key.data(),
|
||||||
|
static_cast<int>(value.size()), value.data()),
|
||||||
|
args.value.size() >= value.size() + 1 ?
|
||||||
|
(args.has_value = true,
|
||||||
|
strlcpy(args.value.data(), value.data(),
|
||||||
|
std::min(args.value.size(), value.size() + 1))) :
|
||||||
|
(LOGW("Config value %.*s for %.*s is too long, ignored",
|
||||||
|
static_cast<int>(value.size()), value.data(),
|
||||||
|
static_cast<int>(key.size()), key.data()), true))) || ...);
|
||||||
|
}, spoof_config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string buffer = glz::write_json(spoofConfig).value_or("");
|
xwrite(fd, &spoof_config, sizeof(spoof_config));
|
||||||
size_t bufferSize = buffer.size();
|
|
||||||
// Send buffer size first
|
|
||||||
xwrite(fd, &bufferSize, sizeof(bufferSize));
|
|
||||||
// client resize string stl and receive buffer
|
|
||||||
xwrite(fd, buffer.data(), bufferSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register our module class and the companion handler function
|
// Register our module class and the companion handler function
|
||||||
|
|||||||
Reference in New Issue
Block a user