mirror of
https://github.com/LittleTurtle2333/SimplicityTools.git
synced 2026-07-12 19:31:17 +08:00
Merge branch 'main' of https://github.com/qqlittleice233/SimplicityTools into qqlittleice233-main
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
|||||||
[submodule "blockmiui"]
|
[submodule "blockmiui"]
|
||||||
path = blockmiui
|
path = blockmiui
|
||||||
url = https://github.com/577fkj/blockmiui.git
|
url = https://github.com/577fkj/blockmiui.git
|
||||||
|
[submodule "app/src/main/cpp/dex_builder"]
|
||||||
|
path = app/src/main/cpp/dex_builder
|
||||||
|
url = https://github.com/LSPosed/DexBuilder
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ android {
|
|||||||
targetSdk = 32
|
targetSdk = 32
|
||||||
versionCode = 40
|
versionCode = 40
|
||||||
versionName = "1.3.9"
|
versionName = "1.3.9"
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
targets("DexBuilder")
|
||||||
|
abiFilters("arm64-v8a")
|
||||||
|
cppFlags("-std=c++17")
|
||||||
|
cFlags("-std=gnu99")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -53,6 +61,15 @@ android {
|
|||||||
"Simplicity_Tools_Xposed-${versionName}-${name}.apk"
|
"Simplicity_Tools_Xposed-${versionName}-${name}.apk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
androidResources {
|
||||||
|
noCompress("libDexBuilder.so")
|
||||||
|
}
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
path("src/main/cpp/CMakeLists.txt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ndkVersion = "23.1.7779620"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
2
app/proguard-rules.pro
vendored
2
app/proguard-rules.pro
vendored
@@ -36,5 +36,7 @@
|
|||||||
public static void throw*(...);
|
public static void throw*(...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-keep class me.iacn.biliroaming.utils.DexHelper { *; }
|
||||||
|
|
||||||
-allowaccessmodification
|
-allowaccessmodification
|
||||||
-overloadaggressively
|
-overloadaggressively
|
||||||
25
app/src/main/cpp/CMakeLists.txt
Normal file
25
app/src/main/cpp/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.18.1)
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
|
||||||
|
add_subdirectory(dex_builder)
|
||||||
|
|
||||||
|
add_library(
|
||||||
|
DexBuilder
|
||||||
|
SHARED
|
||||||
|
native.cpp
|
||||||
|
biliroaming.cc
|
||||||
|
)
|
||||||
|
target_include_directories(DexBuilder PUBLIC dex_builder/include)
|
||||||
|
|
||||||
|
find_library(
|
||||||
|
log-lib
|
||||||
|
log)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
DexBuilder
|
||||||
|
${log-lib}
|
||||||
|
dex_builder_static
|
||||||
|
)
|
||||||
669
app/src/main/cpp/biliroaming.cc
Normal file
669
app/src/main/cpp/biliroaming.cc
Normal file
@@ -0,0 +1,669 @@
|
|||||||
|
#include <android/log.h>
|
||||||
|
#include <dex_helper.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#define LOG_TAG "QAuxv"
|
||||||
|
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define PLOGE(fmt, args...) \
|
||||||
|
LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
jfieldID token_field;
|
||||||
|
jfieldID class_loader_field;
|
||||||
|
jmethodID load_class_method;
|
||||||
|
// jmethodID get_declared_method;
|
||||||
|
// jmethodID get_declared_field;
|
||||||
|
jmethodID get_name_method;
|
||||||
|
jmethodID get_declaring_class_method;
|
||||||
|
jmethodID get_parameters_method;
|
||||||
|
jmethodID get_class_name_method;
|
||||||
|
jfieldID path_list_field;
|
||||||
|
jfieldID element_field;
|
||||||
|
jfieldID dex_file_field;
|
||||||
|
jfieldID cookie_field;
|
||||||
|
|
||||||
|
jclass LoadClass(JNIEnv *env, jobject class_loader,
|
||||||
|
std::string_view descriptor) {
|
||||||
|
if (descriptor.empty())
|
||||||
|
return nullptr;
|
||||||
|
if (descriptor[0] != 'L')
|
||||||
|
return nullptr;
|
||||||
|
std::string name(descriptor.substr(1, descriptor.length() - 2));
|
||||||
|
std::replace(name.begin(), name.end(), '/', '.');
|
||||||
|
auto java_name = env->NewStringUTF(name.data());
|
||||||
|
auto res = (jclass)env->CallObjectMethod(class_loader, load_class_method,
|
||||||
|
java_name, false);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetClassDescriptor(JNIEnv *env, jclass clazz) {
|
||||||
|
auto java_name = (jstring)env->CallObjectMethod(clazz, get_class_name_method);
|
||||||
|
auto name = env->GetStringUTFChars(java_name, nullptr);
|
||||||
|
std::string descriptor = name;
|
||||||
|
std::replace(descriptor.begin(), descriptor.end(), '.', '/');
|
||||||
|
if (descriptor[0] != '[') {
|
||||||
|
if (descriptor == "boolean") {
|
||||||
|
descriptor = "Z";
|
||||||
|
} else if (descriptor == "byte") {
|
||||||
|
descriptor = "B";
|
||||||
|
} else if (descriptor == "short") {
|
||||||
|
descriptor = "S";
|
||||||
|
} else if (descriptor == "char") {
|
||||||
|
descriptor = "C";
|
||||||
|
} else if (descriptor == "int") {
|
||||||
|
descriptor = "I";
|
||||||
|
} else if (descriptor == "long") {
|
||||||
|
descriptor = "J";
|
||||||
|
} else if (descriptor == "float") {
|
||||||
|
descriptor = "F";
|
||||||
|
} else if (descriptor == "double") {
|
||||||
|
descriptor = "D";
|
||||||
|
}
|
||||||
|
descriptor = "L" + std::string(name) + ";";
|
||||||
|
}
|
||||||
|
env->ReleaseStringUTFChars(java_name, name);
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
struct MyDexFile {
|
||||||
|
const void *begin_{};
|
||||||
|
size_t size_{};
|
||||||
|
const uint8_t *const data_begin_{};
|
||||||
|
const size_t data_size_{};
|
||||||
|
|
||||||
|
virtual ~MyDexFile() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlongArray JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_findMethodUsingString(
|
||||||
|
JNIEnv *env, jobject thiz, jstring str, jboolean match_prefix,
|
||||||
|
jlong return_type, jshort parameter_count, jstring parameter_shorty,
|
||||||
|
jlong declaring_class, jlongArray parameter_types,
|
||||||
|
jlongArray contains_parameter_types, jintArray dex_priority,
|
||||||
|
jboolean find_first) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return nullptr;
|
||||||
|
if (!str)
|
||||||
|
return nullptr;
|
||||||
|
auto str_ = env->GetStringUTFChars(str, nullptr);
|
||||||
|
auto parameter_shorty_ =
|
||||||
|
parameter_shorty ? env->GetStringUTFChars(parameter_shorty, nullptr)
|
||||||
|
: nullptr;
|
||||||
|
std::vector<size_t> dex_priority_;
|
||||||
|
jint *dex_priority_elements = nullptr;
|
||||||
|
if (dex_priority) {
|
||||||
|
dex_priority_elements = env->GetIntArrayElements(dex_priority, nullptr);
|
||||||
|
dex_priority_.assign(dex_priority_elements,
|
||||||
|
dex_priority_elements +
|
||||||
|
env->GetArrayLength(dex_priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> parameter_types_;
|
||||||
|
jlong *parameter_types_elements = nullptr;
|
||||||
|
if (parameter_types) {
|
||||||
|
parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(parameter_types, nullptr);
|
||||||
|
parameter_types_.assign(parameter_types_elements,
|
||||||
|
parameter_types_elements +
|
||||||
|
env->GetArrayLength(parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> contains_parameter_types_;
|
||||||
|
jlong *contains_parameter_types_elements = nullptr;
|
||||||
|
if (contains_parameter_types) {
|
||||||
|
contains_parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(contains_parameter_types, nullptr);
|
||||||
|
contains_parameter_types_.assign(
|
||||||
|
contains_parameter_types_elements,
|
||||||
|
contains_parameter_types_elements +
|
||||||
|
env->GetArrayLength(contains_parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto out = helper->FindMethodUsingString(
|
||||||
|
str_, match_prefix, return_type, parameter_count, parameter_shorty_ ? parameter_shorty_ : "",
|
||||||
|
declaring_class, contains_parameter_types_, contains_parameter_types_,
|
||||||
|
dex_priority_, find_first);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(str, str_);
|
||||||
|
if (parameter_shorty_)
|
||||||
|
env->ReleaseStringUTFChars(parameter_shorty, parameter_shorty_);
|
||||||
|
if (dex_priority_elements)
|
||||||
|
env->ReleaseIntArrayElements(dex_priority, dex_priority_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(parameter_types, parameter_types_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (contains_parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(contains_parameter_types,
|
||||||
|
contains_parameter_types_elements, JNI_ABORT);
|
||||||
|
auto res = env->NewLongArray(static_cast<int>(out.size()));
|
||||||
|
auto res_element = env->GetLongArrayElements(res, nullptr);
|
||||||
|
for (size_t i = 0; i < out.size(); ++i) {
|
||||||
|
res_element[i] = out[i];
|
||||||
|
}
|
||||||
|
env->ReleaseLongArrayElements(res, res_element, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_load(JNIEnv *env, jobject thiz,
|
||||||
|
jobject class_loader) {
|
||||||
|
if (!class_loader)
|
||||||
|
return 0;
|
||||||
|
auto path_list = env->GetObjectField(class_loader, path_list_field);
|
||||||
|
if (!path_list)
|
||||||
|
return 0;
|
||||||
|
auto elements = (jobjectArray)env->GetObjectField(path_list, element_field);
|
||||||
|
if (!elements)
|
||||||
|
return 0;
|
||||||
|
std::vector<std::tuple<const void *, size_t, const void *, size_t>> images;
|
||||||
|
for (auto i = 0, len = env->GetArrayLength(elements); i < len; ++i) {
|
||||||
|
auto element = env->GetObjectArrayElement(elements, i);
|
||||||
|
if (!element) continue;
|
||||||
|
auto java_dex_file = env->GetObjectField(element, dex_file_field);
|
||||||
|
if (!java_dex_file) continue;
|
||||||
|
auto cookie = (jlongArray)env->GetObjectField(java_dex_file, cookie_field);
|
||||||
|
if (!cookie) continue;
|
||||||
|
auto dex_file_length = env->GetArrayLength(cookie);
|
||||||
|
const auto *dex_files = reinterpret_cast<const MyDexFile **>(
|
||||||
|
env->GetLongArrayElements(cookie, nullptr));
|
||||||
|
while (dex_file_length-- > 1) {
|
||||||
|
const auto *dex_file = dex_files[dex_file_length];
|
||||||
|
if (!dex_file) {
|
||||||
|
LOGE("dex_file is nullptr at %d", dex_file_length);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LOGD("Got dex file %d", dex_file_length);
|
||||||
|
if (dex::Reader::IsCompact(dex_file->begin_)) {
|
||||||
|
images.emplace_back(dex_file->begin_, dex_file->size_, dex_file->data_begin_, dex_file->data_size_);
|
||||||
|
} else {
|
||||||
|
images.emplace_back(dex_file->begin_, dex_file->size_, nullptr, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (images.empty()) return 0;
|
||||||
|
auto res = reinterpret_cast<jlong>(new DexHelper(images));
|
||||||
|
env->SetLongField(thiz, token_field, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlongArray JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_findMethodInvoking(
|
||||||
|
JNIEnv *env, jobject thiz, jlong method_index, jlong return_type,
|
||||||
|
jshort parameter_count, jstring parameter_shorty, jlong declaring_class,
|
||||||
|
jlongArray parameter_types, jlongArray contains_parameter_types,
|
||||||
|
jintArray dex_priority, jboolean find_first) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return nullptr;
|
||||||
|
auto parameter_shorty_ =
|
||||||
|
parameter_shorty ? env->GetStringUTFChars(parameter_shorty, nullptr)
|
||||||
|
: nullptr;
|
||||||
|
std::vector<size_t> dex_priority_;
|
||||||
|
jint *dex_priority_elements = nullptr;
|
||||||
|
if (dex_priority) {
|
||||||
|
dex_priority_elements = env->GetIntArrayElements(dex_priority, nullptr);
|
||||||
|
dex_priority_.assign(dex_priority_elements,
|
||||||
|
dex_priority_elements +
|
||||||
|
env->GetArrayLength(dex_priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> parameter_types_;
|
||||||
|
jlong *parameter_types_elements = nullptr;
|
||||||
|
if (parameter_types) {
|
||||||
|
parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(parameter_types, nullptr);
|
||||||
|
parameter_types_.assign(parameter_types_elements,
|
||||||
|
parameter_types_elements +
|
||||||
|
env->GetArrayLength(parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> contains_parameter_types_;
|
||||||
|
jlong *contains_parameter_types_elements = nullptr;
|
||||||
|
if (contains_parameter_types) {
|
||||||
|
contains_parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(contains_parameter_types, nullptr);
|
||||||
|
contains_parameter_types_.assign(
|
||||||
|
contains_parameter_types_elements,
|
||||||
|
contains_parameter_types_elements +
|
||||||
|
env->GetArrayLength(contains_parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto out = helper->FindMethodInvoking(
|
||||||
|
method_index, return_type, parameter_count, parameter_shorty_ ? parameter_shorty_ : "",
|
||||||
|
declaring_class, contains_parameter_types_, contains_parameter_types_,
|
||||||
|
dex_priority_, find_first);
|
||||||
|
|
||||||
|
if (parameter_shorty_)
|
||||||
|
env->ReleaseStringUTFChars(parameter_shorty, parameter_shorty_);
|
||||||
|
if (dex_priority_elements)
|
||||||
|
env->ReleaseIntArrayElements(dex_priority, dex_priority_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(parameter_types, parameter_types_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (contains_parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(contains_parameter_types,
|
||||||
|
contains_parameter_types_elements, JNI_ABORT);
|
||||||
|
auto res = env->NewLongArray(static_cast<int>(out.size()));
|
||||||
|
auto res_element = env->GetLongArrayElements(res, nullptr);
|
||||||
|
for (size_t i = 0; i < out.size(); ++i) {
|
||||||
|
res_element[i] = out[i];
|
||||||
|
}
|
||||||
|
env->ReleaseLongArrayElements(res, res_element, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
extern "C" JNIEXPORT jlongArray JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_findMethodInvoked(
|
||||||
|
JNIEnv *env, jobject thiz, jlong method_index, jlong return_type,
|
||||||
|
jshort parameter_count, jstring parameter_shorty, jlong declaring_class,
|
||||||
|
jlongArray parameter_types, jlongArray contains_parameter_types,
|
||||||
|
jintArray dex_priority, jboolean find_first) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return nullptr;
|
||||||
|
auto parameter_shorty_ =
|
||||||
|
parameter_shorty ? env->GetStringUTFChars(parameter_shorty, nullptr)
|
||||||
|
: nullptr;
|
||||||
|
std::vector<size_t> dex_priority_;
|
||||||
|
jint *dex_priority_elements = nullptr;
|
||||||
|
if (dex_priority) {
|
||||||
|
dex_priority_elements = env->GetIntArrayElements(dex_priority, nullptr);
|
||||||
|
dex_priority_.assign(dex_priority_elements,
|
||||||
|
dex_priority_elements +
|
||||||
|
env->GetArrayLength(dex_priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> parameter_types_;
|
||||||
|
jlong *parameter_types_elements = nullptr;
|
||||||
|
if (parameter_types) {
|
||||||
|
parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(parameter_types, nullptr);
|
||||||
|
parameter_types_.assign(parameter_types_elements,
|
||||||
|
parameter_types_elements +
|
||||||
|
env->GetArrayLength(parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> contains_parameter_types_;
|
||||||
|
jlong *contains_parameter_types_elements = nullptr;
|
||||||
|
if (contains_parameter_types) {
|
||||||
|
contains_parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(contains_parameter_types, nullptr);
|
||||||
|
contains_parameter_types_.assign(
|
||||||
|
contains_parameter_types_elements,
|
||||||
|
contains_parameter_types_elements +
|
||||||
|
env->GetArrayLength(contains_parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto out = helper->FindMethodInvoked(
|
||||||
|
method_index, return_type, parameter_count, parameter_shorty_ ? parameter_shorty_ : "",
|
||||||
|
declaring_class, contains_parameter_types_, contains_parameter_types_,
|
||||||
|
dex_priority_, find_first);
|
||||||
|
|
||||||
|
if (parameter_shorty_)
|
||||||
|
env->ReleaseStringUTFChars(parameter_shorty, parameter_shorty_);
|
||||||
|
if (dex_priority_elements)
|
||||||
|
env->ReleaseIntArrayElements(dex_priority, dex_priority_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(parameter_types, parameter_types_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (contains_parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(contains_parameter_types,
|
||||||
|
contains_parameter_types_elements, JNI_ABORT);
|
||||||
|
auto res = env->NewLongArray(static_cast<int>(out.size()));
|
||||||
|
auto res_element = env->GetLongArrayElements(res, nullptr);
|
||||||
|
for (size_t i = 0; i < out.size(); ++i) {
|
||||||
|
res_element[i] = out[i];
|
||||||
|
}
|
||||||
|
env->ReleaseLongArrayElements(res, res_element, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
extern "C" JNIEXPORT jlongArray JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_findMethodSettingField(
|
||||||
|
JNIEnv *env, jobject thiz, jlong field_index, jlong return_type,
|
||||||
|
jshort parameter_count, jstring parameter_shorty, jlong declaring_class,
|
||||||
|
jlongArray parameter_types, jlongArray contains_parameter_types,
|
||||||
|
jintArray dex_priority, jboolean find_first) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return nullptr;
|
||||||
|
auto parameter_shorty_ =
|
||||||
|
parameter_shorty ? env->GetStringUTFChars(parameter_shorty, nullptr)
|
||||||
|
: nullptr;
|
||||||
|
std::vector<size_t> dex_priority_;
|
||||||
|
jint *dex_priority_elements = nullptr;
|
||||||
|
if (dex_priority) {
|
||||||
|
dex_priority_elements = env->GetIntArrayElements(dex_priority, nullptr);
|
||||||
|
dex_priority_.assign(dex_priority_elements,
|
||||||
|
dex_priority_elements +
|
||||||
|
env->GetArrayLength(dex_priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> parameter_types_;
|
||||||
|
jlong *parameter_types_elements = nullptr;
|
||||||
|
if (parameter_types) {
|
||||||
|
parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(parameter_types, nullptr);
|
||||||
|
parameter_types_.assign(parameter_types_elements,
|
||||||
|
parameter_types_elements +
|
||||||
|
env->GetArrayLength(parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> contains_parameter_types_;
|
||||||
|
jlong *contains_parameter_types_elements = nullptr;
|
||||||
|
if (contains_parameter_types) {
|
||||||
|
contains_parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(contains_parameter_types, nullptr);
|
||||||
|
contains_parameter_types_.assign(
|
||||||
|
contains_parameter_types_elements,
|
||||||
|
contains_parameter_types_elements +
|
||||||
|
env->GetArrayLength(contains_parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto out = helper->FindMethodSettingField(
|
||||||
|
field_index, return_type, parameter_count, parameter_shorty_ ? parameter_shorty_ : "",
|
||||||
|
declaring_class, contains_parameter_types_, contains_parameter_types_,
|
||||||
|
dex_priority_, find_first);
|
||||||
|
|
||||||
|
if (parameter_shorty_)
|
||||||
|
env->ReleaseStringUTFChars(parameter_shorty, parameter_shorty_);
|
||||||
|
if (dex_priority_elements)
|
||||||
|
env->ReleaseIntArrayElements(dex_priority, dex_priority_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(parameter_types, parameter_types_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (contains_parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(contains_parameter_types,
|
||||||
|
contains_parameter_types_elements, JNI_ABORT);
|
||||||
|
auto res = env->NewLongArray(static_cast<int>(out.size()));
|
||||||
|
auto res_element = env->GetLongArrayElements(res, nullptr);
|
||||||
|
for (size_t i = 0; i < out.size(); ++i) {
|
||||||
|
res_element[i] = out[i];
|
||||||
|
}
|
||||||
|
env->ReleaseLongArrayElements(res, res_element, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
extern "C" JNIEXPORT jlongArray JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_findMethodGettingField(
|
||||||
|
JNIEnv *env, jobject thiz, jlong field_index, jlong return_type,
|
||||||
|
jshort parameter_count, jstring parameter_shorty, jlong declaring_class,
|
||||||
|
jlongArray parameter_types, jlongArray contains_parameter_types,
|
||||||
|
jintArray dex_priority, jboolean find_first) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return nullptr;
|
||||||
|
auto parameter_shorty_ =
|
||||||
|
parameter_shorty ? env->GetStringUTFChars(parameter_shorty, nullptr)
|
||||||
|
: nullptr;
|
||||||
|
std::vector<size_t> dex_priority_;
|
||||||
|
jint *dex_priority_elements = nullptr;
|
||||||
|
if (dex_priority) {
|
||||||
|
dex_priority_elements = env->GetIntArrayElements(dex_priority, nullptr);
|
||||||
|
dex_priority_.assign(dex_priority_elements,
|
||||||
|
dex_priority_elements +
|
||||||
|
env->GetArrayLength(dex_priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> parameter_types_;
|
||||||
|
jlong *parameter_types_elements = nullptr;
|
||||||
|
if (parameter_types) {
|
||||||
|
parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(parameter_types, nullptr);
|
||||||
|
parameter_types_.assign(parameter_types_elements,
|
||||||
|
parameter_types_elements +
|
||||||
|
env->GetArrayLength(parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> contains_parameter_types_;
|
||||||
|
jlong *contains_parameter_types_elements = nullptr;
|
||||||
|
if (contains_parameter_types) {
|
||||||
|
contains_parameter_types_elements =
|
||||||
|
env->GetLongArrayElements(contains_parameter_types, nullptr);
|
||||||
|
contains_parameter_types_.assign(
|
||||||
|
contains_parameter_types_elements,
|
||||||
|
contains_parameter_types_elements +
|
||||||
|
env->GetArrayLength(contains_parameter_types));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto out = helper->FindMethodGettingField(
|
||||||
|
field_index, return_type, parameter_count, parameter_shorty_ ? parameter_shorty_ : "",
|
||||||
|
declaring_class, contains_parameter_types_, contains_parameter_types_,
|
||||||
|
dex_priority_, find_first);
|
||||||
|
|
||||||
|
if (parameter_shorty_)
|
||||||
|
env->ReleaseStringUTFChars(parameter_shorty, parameter_shorty_);
|
||||||
|
if (dex_priority_elements)
|
||||||
|
env->ReleaseIntArrayElements(dex_priority, dex_priority_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(parameter_types, parameter_types_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
if (contains_parameter_types_elements)
|
||||||
|
env->ReleaseLongArrayElements(contains_parameter_types,
|
||||||
|
contains_parameter_types_elements, JNI_ABORT);
|
||||||
|
auto res = env->NewLongArray(static_cast<int>(out.size()));
|
||||||
|
auto res_element = env->GetLongArrayElements(res, nullptr);
|
||||||
|
for (size_t i = 0; i < out.size(); ++i) {
|
||||||
|
res_element[i] = out[i];
|
||||||
|
}
|
||||||
|
env->ReleaseLongArrayElements(res, res_element, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
extern "C" JNIEXPORT jlongArray JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_findField(JNIEnv *env, jobject thiz,
|
||||||
|
jlong type,
|
||||||
|
jintArray dex_priority,
|
||||||
|
jboolean find_first) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
std::vector<size_t> dex_priority_;
|
||||||
|
jint *dex_priority_elements = nullptr;
|
||||||
|
if (dex_priority) {
|
||||||
|
dex_priority_elements = env->GetIntArrayElements(dex_priority, nullptr);
|
||||||
|
dex_priority_.assign(dex_priority_elements,
|
||||||
|
dex_priority_elements +
|
||||||
|
env->GetArrayLength(dex_priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto out = helper->FindField(type, dex_priority_, find_first);
|
||||||
|
|
||||||
|
if (dex_priority_elements)
|
||||||
|
env->ReleaseIntArrayElements(dex_priority, dex_priority_elements,
|
||||||
|
JNI_ABORT);
|
||||||
|
|
||||||
|
auto res = env->NewLongArray(static_cast<int>(out.size()));
|
||||||
|
auto res_element = env->GetLongArrayElements(res, nullptr);
|
||||||
|
for (size_t i = 0; i < out.size(); ++i) {
|
||||||
|
res_element[i] = out[i];
|
||||||
|
}
|
||||||
|
env->ReleaseLongArrayElements(res, res_element, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jobject JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_decodeMethodIndex(JNIEnv *env,
|
||||||
|
jobject thiz,
|
||||||
|
jlong method_index) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return nullptr;
|
||||||
|
auto out = helper->DecodeMethod(method_index);
|
||||||
|
auto cl = env->GetObjectField(thiz, class_loader_field);
|
||||||
|
auto clazz = LoadClass(env, cl, out.declaring_class.name);
|
||||||
|
env->DeleteLocalRef(cl);
|
||||||
|
std::string sig;
|
||||||
|
sig.reserve(4096);
|
||||||
|
sig += "(";
|
||||||
|
for (const auto ¶m : out.parameters) {
|
||||||
|
sig += param.name;
|
||||||
|
}
|
||||||
|
sig += ")";
|
||||||
|
sig += out.return_type.name;
|
||||||
|
auto *method = env->GetMethodID(clazz, out.name.data(), sig.data());
|
||||||
|
if ((*env).ExceptionCheck()) {
|
||||||
|
(*env).ExceptionClear();
|
||||||
|
}
|
||||||
|
if (!method) {
|
||||||
|
method = env->GetStaticMethodID(clazz, out.name.data(), sig.data());
|
||||||
|
}
|
||||||
|
return env->ToReflectedMethod(clazz, method, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jobject JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_decodeFieldIndex(JNIEnv *env,
|
||||||
|
jobject thiz,
|
||||||
|
jlong field_index) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return nullptr;
|
||||||
|
auto out = helper->DecodeField(field_index);
|
||||||
|
auto cl = env->GetObjectField(thiz, class_loader_field);
|
||||||
|
auto clazz = LoadClass(env, cl, out.declaring_class.name);
|
||||||
|
env->DeleteLocalRef(cl);
|
||||||
|
return env->ToReflectedField(
|
||||||
|
clazz, env->GetFieldID(clazz, out.name.data(), out.type.name.data()),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_encodeClassIndex(JNIEnv *env,
|
||||||
|
jobject thiz,
|
||||||
|
jclass clazz) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
return helper->CreateClassIndex(GetClassDescriptor(env, clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_encodeFieldIndex(JNIEnv *env,
|
||||||
|
jobject thiz,
|
||||||
|
jobject field) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return -1;
|
||||||
|
auto java_name = (jstring)env->CallObjectMethod(field, get_name_method);
|
||||||
|
auto clazz = (jclass)env->CallObjectMethod(field, get_declaring_class_method);
|
||||||
|
auto name = env->GetStringUTFChars(java_name, nullptr);
|
||||||
|
auto res = helper->CreateFieldIndex(name, GetClassDescriptor(env, clazz));
|
||||||
|
env->ReleaseStringUTFChars(java_name, name);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_encodeMethodIndex(JNIEnv *env,
|
||||||
|
jobject thiz,
|
||||||
|
jobject method) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return -1;
|
||||||
|
auto java_name = (jstring)env->CallObjectMethod(method, get_name_method);
|
||||||
|
auto clazz =
|
||||||
|
(jclass)env->CallObjectMethod(method, get_declaring_class_method);
|
||||||
|
auto name = env->GetStringUTFChars(java_name, nullptr);
|
||||||
|
auto params =
|
||||||
|
(jobjectArray)env->CallObjectMethod(method, get_parameters_method);
|
||||||
|
auto param_len = env->GetArrayLength(params);
|
||||||
|
std::vector<std::string> param_descriptors;
|
||||||
|
param_descriptors.reserve(param_len);
|
||||||
|
for (size_t i = 0; i < param_len; ++i) {
|
||||||
|
auto param = (jclass)env->GetObjectArrayElement(params, i);
|
||||||
|
param_descriptors.emplace_back(GetClassDescriptor(env, param));
|
||||||
|
env->DeleteLocalRef(param);
|
||||||
|
}
|
||||||
|
std::vector<std::string_view> params_name;
|
||||||
|
params_name.reserve(param_descriptors.size());
|
||||||
|
for (const auto &descriptor : param_descriptors) {
|
||||||
|
params_name.emplace_back(descriptor);
|
||||||
|
}
|
||||||
|
auto res = helper->CreateMethodIndex(name, GetClassDescriptor(env, clazz),
|
||||||
|
params_name);
|
||||||
|
env->ReleaseStringUTFChars(java_name, name);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jclass JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_decodeClassIndex(JNIEnv *env,
|
||||||
|
jobject thiz,
|
||||||
|
jlong class_index) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return nullptr;
|
||||||
|
auto out = helper->DecodeClass(class_index);
|
||||||
|
auto cl = env->GetObjectField(thiz, class_loader_field);
|
||||||
|
auto res = LoadClass(env, cl, out.name);
|
||||||
|
env->DeleteLocalRef(cl);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_close(JNIEnv *env, jobject thiz) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
env->SetLongField(thiz, token_field, jlong(0));
|
||||||
|
delete helper;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint JNICALL BILI_JNI_OnLoad(JavaVM *vm, void *) {
|
||||||
|
JNIEnv *env = nullptr;
|
||||||
|
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
jclass helper = env->FindClass("me/iacn/biliroaming/utils/DexHelper");
|
||||||
|
token_field = env->GetFieldID(helper, "token", "J");
|
||||||
|
class_loader_field =
|
||||||
|
env->GetFieldID(helper, "classLoader", "Ljava/lang/ClassLoader;");
|
||||||
|
auto class_loader = env->FindClass("java/lang/ClassLoader");
|
||||||
|
load_class_method = env->GetMethodID(
|
||||||
|
class_loader, "loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;");
|
||||||
|
auto member = env->FindClass("java/lang/reflect/Member");
|
||||||
|
get_declaring_class_method =
|
||||||
|
env->GetMethodID(member, "getDeclaringClass", "()Ljava/lang/Class;");
|
||||||
|
get_name_method = env->GetMethodID(member, "getName", "()Ljava/lang/String;");
|
||||||
|
auto executable = env->FindClass("java/lang/reflect/Executable");
|
||||||
|
get_parameters_method =
|
||||||
|
env->GetMethodID(executable, "getParameterTypes", "()[Ljava/lang/Class;");
|
||||||
|
auto clazz = env->FindClass("java/lang/Class");
|
||||||
|
get_class_name_method =
|
||||||
|
env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");
|
||||||
|
auto dex_class_loader = env->FindClass("dalvik/system/BaseDexClassLoader");
|
||||||
|
path_list_field = env->GetFieldID(dex_class_loader, "pathList",
|
||||||
|
"Ldalvik/system/DexPathList;");
|
||||||
|
auto dex_path_list = env->FindClass("dalvik/system/DexPathList");
|
||||||
|
element_field = env->GetFieldID(dex_path_list, "dexElements",
|
||||||
|
"[Ldalvik/system/DexPathList$Element;");
|
||||||
|
auto element = env->FindClass("dalvik/system/DexPathList$Element");
|
||||||
|
dex_file_field =
|
||||||
|
env->GetFieldID(element, "dexFile", "Ldalvik/system/DexFile;");
|
||||||
|
auto dex_file = env->FindClass("dalvik/system/DexFile");
|
||||||
|
cookie_field = env->GetFieldID(dex_file, "mCookie", "Ljava/lang/Object;");
|
||||||
|
return JNI_VERSION_1_4;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_me_iacn_biliroaming_utils_DexHelper_createFullCache(JNIEnv *env, jobject thiz) {
|
||||||
|
auto *helper =
|
||||||
|
reinterpret_cast<DexHelper *>(env->GetLongField(thiz, token_field));
|
||||||
|
if (!helper)
|
||||||
|
return;
|
||||||
|
helper->CreateFullCache();
|
||||||
|
}
|
||||||
29
app/src/main/cpp/logging.h
Normal file
29
app/src/main/cpp/logging.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _LOGGING_H
|
||||||
|
#define _LOGGING_H
|
||||||
|
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
#ifndef LOG_TAG
|
||||||
|
#define LOG_TAG "SimplicityTools"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LOG_DISABLED
|
||||||
|
#define LOGD(...)
|
||||||
|
#define LOGV(...)
|
||||||
|
#define LOGI(...)
|
||||||
|
#define LOGW(...)
|
||||||
|
#define LOGE(...)
|
||||||
|
#else
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||||
|
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _LOGGING_H
|
||||||
9
app/src/main/cpp/native.cpp
Normal file
9
app/src/main/cpp/native.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include <jni.h>
|
||||||
|
#include "logging.h"
|
||||||
|
#include "native.h"
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||||
|
LOGD("%s", "JNI_OnLoad");
|
||||||
|
BILI_JNI_OnLoad(vm, reserved);
|
||||||
|
return JNI_VERSION_1_6;
|
||||||
|
}
|
||||||
10
app/src/main/cpp/native.h
Normal file
10
app/src/main/cpp/native.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by Owner on 2022/3/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FUCKCOOLAPKR_NATIVE_H
|
||||||
|
#define FUCKCOOLAPKR_NATIVE_H
|
||||||
|
|
||||||
|
extern "C" jint BILI_JNI_OnLoad(JavaVM *vm, void *reserved);
|
||||||
|
|
||||||
|
#endif //FUCKCOOLAPKR_NATIVE_H
|
||||||
21
app/src/main/cpp/native_api.h
Normal file
21
app/src/main/cpp/native_api.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef XPOSEDTEMPLATE_NATIVE_API_H
|
||||||
|
#define XPOSEDTEMPLATE_NATIVE_API_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
typedef int (*HookFunType)(void *func, void *replace, void **backup);
|
||||||
|
|
||||||
|
typedef int (*UnhookFunType)(void *func);
|
||||||
|
|
||||||
|
typedef void (*NativeOnModuleLoaded)(const char *name, void *handle);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t version;
|
||||||
|
HookFunType hookFunc;
|
||||||
|
UnhookFunType unhookFunc;
|
||||||
|
} NativeAPIEntries;
|
||||||
|
|
||||||
|
typedef NativeOnModuleLoaded (*NativeInit)(const NativeAPIEntries *entries);
|
||||||
|
|
||||||
|
#endif //XPOSEDTEMPLATE_NATIVE_API_H
|
||||||
@@ -2,19 +2,33 @@ package com.lt2333.simplicitytools.hook.app
|
|||||||
|
|
||||||
import com.lt2333.simplicitytools.hook.app.securitycenter.LockOneHundred
|
import com.lt2333.simplicitytools.hook.app.securitycenter.LockOneHundred
|
||||||
import com.lt2333.simplicitytools.hook.app.securitycenter.RemoveMacroBlacklist
|
import com.lt2333.simplicitytools.hook.app.securitycenter.RemoveMacroBlacklist
|
||||||
|
import com.lt2333.simplicitytools.hook.app.securitycenter.ShowBatteryTemperature
|
||||||
import com.lt2333.simplicitytools.hook.app.securitycenter.SkipWaitingTime
|
import com.lt2333.simplicitytools.hook.app.securitycenter.SkipWaitingTime
|
||||||
|
import com.lt2333.simplicitytools.util.log
|
||||||
import de.robv.android.xposed.IXposedHookLoadPackage
|
import de.robv.android.xposed.IXposedHookLoadPackage
|
||||||
import de.robv.android.xposed.XposedBridge
|
import de.robv.android.xposed.XposedBridge
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam
|
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam
|
||||||
|
import me.iacn.biliroaming.utils.DexHelper
|
||||||
|
|
||||||
class SecurityCenter : IXposedHookLoadPackage {
|
class SecurityCenter : IXposedHookLoadPackage {
|
||||||
|
|
||||||
|
var dexHelper: DexHelper? = null
|
||||||
|
|
||||||
override fun handleLoadPackage(lpparam: LoadPackageParam) {
|
override fun handleLoadPackage(lpparam: LoadPackageParam) {
|
||||||
XposedBridge.log("Simplicitytools: 成功 Hook "+javaClass.simpleName)
|
XposedBridge.log("Simplicitytools: 成功 Hook "+javaClass.simpleName)
|
||||||
|
try {
|
||||||
|
System.loadLibrary("DexBuilder")
|
||||||
|
dexHelper = DexHelper.getInstance(lpparam.classLoader)
|
||||||
|
} catch (e: UnsatisfiedLinkError) {
|
||||||
|
log("DexBuilder 加载失败")
|
||||||
|
}
|
||||||
//跳过 5/10秒等待时间
|
//跳过 5/10秒等待时间
|
||||||
SkipWaitingTime().handleLoadPackage(lpparam)
|
SkipWaitingTime().handleLoadPackage(lpparam)
|
||||||
//锁定 100分
|
//锁定 100分
|
||||||
LockOneHundred().handleLoadPackage(lpparam)
|
LockOneHundred().handleLoadPackage(lpparam)
|
||||||
//去除自动连招黑名单
|
//去除自动连招黑名单
|
||||||
RemoveMacroBlacklist().handleLoadPackage(lpparam)
|
RemoveMacroBlacklist().handleLoadPackage(lpparam)
|
||||||
|
//显示电池温度
|
||||||
|
ShowBatteryTemperature(dexHelper).handleLoadPackage(lpparam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.lt2333.simplicitytools.hook.app.securitycenter
|
||||||
|
|
||||||
|
import com.lt2333.simplicitytools.util.log
|
||||||
|
import de.robv.android.xposed.IXposedHookLoadPackage
|
||||||
|
import de.robv.android.xposed.XC_MethodReplacement
|
||||||
|
import de.robv.android.xposed.XposedBridge
|
||||||
|
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||||
|
import me.iacn.biliroaming.utils.DexHelper
|
||||||
|
|
||||||
|
class ShowBatteryTemperature(private val dexHelper: DexHelper?): IXposedHookLoadPackage {
|
||||||
|
|
||||||
|
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||||
|
if (dexHelper == null) {
|
||||||
|
log("DexHelper为null,hook ShowBatteryTemperature 失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val methodIndex = dexHelper.findMethodUsingString(
|
||||||
|
"isBatteryLifeFunctionSupported",
|
||||||
|
true,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
-1,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
).firstOrNull()
|
||||||
|
if (methodIndex == null) {
|
||||||
|
log("ShowBatteryTemperature 无法定位方法")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val method = dexHelper.decodeMethodIndex(methodIndex)
|
||||||
|
log(method)
|
||||||
|
XposedBridge.hookMethod(method, XC_MethodReplacement.returnConstant(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ import de.robv.android.xposed.XC_MethodReplacement
|
|||||||
import de.robv.android.xposed.XposedBridge
|
import de.robv.android.xposed.XposedBridge
|
||||||
import de.robv.android.xposed.XposedHelpers
|
import de.robv.android.xposed.XposedHelpers
|
||||||
import de.robv.android.xposed.callbacks.XC_LayoutInflated
|
import de.robv.android.xposed.callbacks.XC_LayoutInflated
|
||||||
|
import me.iacn.biliroaming.utils.DexHelper
|
||||||
|
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
import java.lang.reflect.Member
|
import java.lang.reflect.Member
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|||||||
87
app/src/main/java/me/iacn/biliroaming/utils/DexHelper.java
Normal file
87
app/src/main/java/me/iacn/biliroaming/utils/DexHelper.java
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package me.iacn.biliroaming.utils;
|
||||||
|
|
||||||
|
import com.lt2333.simplicitytools.util.KotlinXposedHelperKt;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Member;
|
||||||
|
|
||||||
|
import dalvik.system.BaseDexClassLoader;
|
||||||
|
|
||||||
|
public class DexHelper implements AutoCloseable, Closeable {
|
||||||
|
public static final int NO_CLASS_INDEX = -1;
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
private final long token;
|
||||||
|
private static DexHelper instance;
|
||||||
|
|
||||||
|
public static DexHelper getInstance(ClassLoader classLoader) {
|
||||||
|
synchronized (DexHelper.class) {
|
||||||
|
if (instance != null) return instance;
|
||||||
|
BaseDexClassLoader loader = KotlinXposedHelperKt.findDexClassLoader(classLoader);
|
||||||
|
if (loader == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
instance = new DexHelper(loader);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DexHelper(ClassLoader classLoader) {
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
token = load(classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public native long[] findMethodUsingString(
|
||||||
|
String str, boolean matchPrefix, long returnType, short parameterCount,
|
||||||
|
String parameterShorty, long declaringClass, long[] parameterTypes,
|
||||||
|
long[] containsParameterTypes, int[] dexPriority, boolean findFirst);
|
||||||
|
|
||||||
|
public native long[] findMethodInvoking(long methodIndex, long returnType,
|
||||||
|
short parameterCount, String parameterShorty,
|
||||||
|
long declaringClass, long[] parameterTypes,
|
||||||
|
long[] containsParameterTypes,
|
||||||
|
int[] dexPriority, boolean findFirst);
|
||||||
|
|
||||||
|
public native long[] findMethodInvoked(long methodIndex, long returnType,
|
||||||
|
short parameterCount, String parameterShorty,
|
||||||
|
long declaringClass, long[] parameterTypes,
|
||||||
|
long[] containsParameterTypes,
|
||||||
|
int[] dexPriority, boolean findFirst);
|
||||||
|
|
||||||
|
public native long[] findMethodSettingField(
|
||||||
|
long fieldIndex, long returnType, short parameterCount,
|
||||||
|
String parameterShorty, long declaringClass, long[] parameterTypes,
|
||||||
|
long[] containsParameterTypes, int[] dexPriority, boolean findFirst);
|
||||||
|
|
||||||
|
public native long[] findMethodGettingField(
|
||||||
|
long fieldIndex, long returnType, short parameterCount,
|
||||||
|
String parameterShorty, long declaringClass, long[] parameterTypes,
|
||||||
|
long[] containsParameterTypes, int[] dexPriority, boolean findFirst);
|
||||||
|
|
||||||
|
public native long[] findField(long type, int[] dexPriority, boolean findFirst);
|
||||||
|
|
||||||
|
public native Member decodeMethodIndex(long methodIndex);
|
||||||
|
|
||||||
|
public native long encodeMethodIndex(Member method);
|
||||||
|
|
||||||
|
public native Field decodeFieldIndex(long fieldIndex);
|
||||||
|
|
||||||
|
public native long encodeFieldIndex(Field field);
|
||||||
|
|
||||||
|
public native long encodeClassIndex(Class<?> clazz);
|
||||||
|
|
||||||
|
public native Class<?> decodeClassIndex(long classIndex);
|
||||||
|
|
||||||
|
public native void createFullCache();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native void close();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private native long load(ClassLoader classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user