[core] Fix resource hook on S (#377)
This commit is contained in:
parent
88f1f693c6
commit
aa98da59da
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <variant>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
// @ApiSensitive(Level.MIDDLE)
|
// @ApiSensitive(Level.MIDDLE)
|
||||||
|
|
@ -27,6 +28,45 @@ namespace android {
|
||||||
|
|
||||||
typedef int32_t status_t;
|
typedef int32_t status_t;
|
||||||
|
|
||||||
|
|
||||||
|
template<class E>
|
||||||
|
struct unexpected {
|
||||||
|
E val_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class E>
|
||||||
|
struct expected {
|
||||||
|
using value_type = T;
|
||||||
|
using error_type = E;
|
||||||
|
using unexpected_type = unexpected<E>;
|
||||||
|
std::variant<value_type, unexpected_type> var_;
|
||||||
|
|
||||||
|
constexpr bool has_value() const noexcept { return var_.index() == 0; }
|
||||||
|
|
||||||
|
constexpr const T &value() const &{ return std::get<T>(var_); }
|
||||||
|
|
||||||
|
constexpr T &value() &{ return std::get<T>(var_); }
|
||||||
|
|
||||||
|
constexpr const T *operator->() const { return std::addressof(value()); }
|
||||||
|
|
||||||
|
constexpr T *operator->() { return std::addressof(value()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class IOError {
|
||||||
|
// Used when reading a file residing on an IncFs file-system times out.
|
||||||
|
PAGES_MISSING = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TChar>
|
||||||
|
struct BasicStringPiece {
|
||||||
|
const TChar *data_;
|
||||||
|
size_t length_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using NullOrIOError = std::variant<std::nullopt_t, IOError>;
|
||||||
|
|
||||||
|
using StringPiece16 = BasicStringPiece<char16_t>;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RES_NULL_TYPE = 0x0000,
|
RES_NULL_TYPE = 0x0000,
|
||||||
RES_STRING_POOL_TYPE = 0x0001,
|
RES_STRING_POOL_TYPE = 0x0001,
|
||||||
|
|
@ -98,6 +138,46 @@ namespace android {
|
||||||
uint32_t mStringPoolSize; // number of uint16_t
|
uint32_t mStringPoolSize; // number of uint16_t
|
||||||
const uint32_t *mStyles;
|
const uint32_t *mStyles;
|
||||||
uint32_t mStylePoolSize; // number of uint32_t
|
uint32_t mStylePoolSize; // number of uint32_t
|
||||||
|
|
||||||
|
using stringAtRet = expected<StringPiece16, NullOrIOError>;
|
||||||
|
|
||||||
|
CREATE_MEM_FUNC_SYMBOL_ENTRY(stringAtRet, stringAtS, void *thiz, size_t idx) {
|
||||||
|
if (stringAtSSym) {
|
||||||
|
return stringAtSSym(thiz, idx);
|
||||||
|
}
|
||||||
|
return {.var_ = unexpected<NullOrIOError>{.val_ = std::nullopt}};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
CREATE_MEM_FUNC_SYMBOL_ENTRY(const char16_t*, stringAt, void *thiz, size_t idx,
|
||||||
|
size_t *u16len) {
|
||||||
|
if (stringAtSym) {
|
||||||
|
return stringAtSym(thiz, idx, u16len);
|
||||||
|
} else {
|
||||||
|
*u16len = 0u;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
StringPiece16 stringAt(size_t idx) const {
|
||||||
|
if (stringAtSym) {
|
||||||
|
size_t len;
|
||||||
|
const char16_t *str = stringAt(const_cast<ResStringPool *>(this), idx, &len);
|
||||||
|
return {str, len};
|
||||||
|
} else if (stringAtSSym) {
|
||||||
|
auto str = stringAtS(const_cast<ResStringPool *>(this), idx);
|
||||||
|
if (str.has_value()) {
|
||||||
|
return {str->data_, str->length_};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {nullptr, 0u};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool setup(void* handle) {
|
||||||
|
RETRIEVE_MEM_FUNC_SYMBOL(stringAt, LP_SELECT("_ZNK7android13ResStringPool8stringAtEjPj", "_ZNK7android13ResStringPool8stringAtEmPm"));
|
||||||
|
RETRIEVE_MEM_FUNC_SYMBOL(stringAtS, LP_SELECT("_ZNK7android13ResStringPool8stringAtEj", "_ZNK7android13ResStringPool8stringAtEm"));
|
||||||
|
return !stringAtSym || !stringAtSSym;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ namespace lspd {
|
||||||
static TYPE_NEXT ResXMLParser_next = nullptr;
|
static TYPE_NEXT ResXMLParser_next = nullptr;
|
||||||
static TYPE_RESTART ResXMLParser_restart = nullptr;
|
static TYPE_RESTART ResXMLParser_restart = nullptr;
|
||||||
static TYPE_GET_ATTR_NAME_ID ResXMLParser_getAttributeNameID = nullptr;
|
static TYPE_GET_ATTR_NAME_ID ResXMLParser_getAttributeNameID = nullptr;
|
||||||
static TYPE_STRING_AT ResStringPool_stringAt = nullptr;
|
|
||||||
|
|
||||||
static bool PrepareSymbols() {
|
static bool PrepareSymbols() {
|
||||||
ScopedDlHandle fw_handle(kLibFwPath.c_str());
|
ScopedDlHandle fw_handle(kLibFwPath.c_str());
|
||||||
|
|
@ -66,13 +65,12 @@ namespace lspd {
|
||||||
"_ZNK7android12ResXMLParser18getAttributeNameIDEm")))) {
|
"_ZNK7android12ResXMLParser18getAttributeNameIDEm")))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (ResStringPool_stringAt = fw_handle.DlSym<TYPE_STRING_AT>(
|
return android::ResStringPool::setup(fw_handle.Get());
|
||||||
LP_SELECT("_ZNK7android13ResStringPool8stringAtEjPj",
|
|
||||||
"_ZNK7android13ResStringPool8stringAtEmPm"))) != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jboolean, ResourcesHook, initXResourcesNative) {
|
LSP_DEF_NATIVE_METHOD(jboolean, ResourcesHook, initXResourcesNative) {
|
||||||
classXResources = Context::GetInstance()->FindClassFromCurrentLoader(env, kXResourcesClassName);
|
classXResources = Context::GetInstance()->FindClassFromCurrentLoader(env,
|
||||||
|
kXResourcesClassName);
|
||||||
if (!classXResources) {
|
if (!classXResources) {
|
||||||
LOGE("Error while loading XResources class '%s':", kXResourcesClassName);
|
LOGE("Error while loading XResources class '%s':", kXResourcesClassName);
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
|
|
@ -109,9 +107,11 @@ namespace lspd {
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jobject, ResourcesHook, buildDummyClassLoader, jobject parent, jobject resource_super_class, jobject typed_array_super_class) {
|
LSP_DEF_NATIVE_METHOD(jobject, ResourcesHook, buildDummyClassLoader, jobject parent,
|
||||||
|
jobject resource_super_class, jobject typed_array_super_class) {
|
||||||
using namespace startop::dex;
|
using namespace startop::dex;
|
||||||
static auto in_memory_classloader = (jclass)env->NewGlobalRef(env->FindClass( "dalvik/system/InMemoryDexClassLoader"));
|
static auto in_memory_classloader = (jclass) env->NewGlobalRef(
|
||||||
|
env->FindClass("dalvik/system/InMemoryDexClassLoader"));
|
||||||
static jmethodID initMid = JNI_GetMethodID(env, in_memory_classloader, "<init>",
|
static jmethodID initMid = JNI_GetMethodID(env, in_memory_classloader, "<init>",
|
||||||
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||||
DexBuilder dex_file;
|
DexBuilder dex_file;
|
||||||
|
|
@ -120,11 +120,13 @@ namespace lspd {
|
||||||
auto current_thread = art::Thread::Current();
|
auto current_thread = art::Thread::Current();
|
||||||
ClassBuilder xresource_builder{
|
ClassBuilder xresource_builder{
|
||||||
dex_file.MakeClass("xposed.dummy.XResourcesSuperClass")};
|
dex_file.MakeClass("xposed.dummy.XResourcesSuperClass")};
|
||||||
xresource_builder.setSuperClass(TypeDescriptor::FromDescriptor(art::mirror::Class(current_thread.DecodeJObject(resource_super_class)).GetDescriptor(&storage)));
|
xresource_builder.setSuperClass(TypeDescriptor::FromDescriptor(art::mirror::Class(
|
||||||
|
current_thread.DecodeJObject(resource_super_class)).GetDescriptor(&storage)));
|
||||||
|
|
||||||
ClassBuilder xtypearray_builder{
|
ClassBuilder xtypearray_builder{
|
||||||
dex_file.MakeClass("xposed.dummy.XTypedArraySuperClass")};
|
dex_file.MakeClass("xposed.dummy.XTypedArraySuperClass")};
|
||||||
xtypearray_builder.setSuperClass(TypeDescriptor::FromDescriptor(art::mirror::Class(current_thread.DecodeJObject(typed_array_super_class)).GetDescriptor(&storage)));
|
xtypearray_builder.setSuperClass(TypeDescriptor::FromDescriptor(art::mirror::Class(
|
||||||
|
current_thread.DecodeJObject(typed_array_super_class)).GetDescriptor(&storage)));
|
||||||
|
|
||||||
slicer::MemView image{dex_file.CreateImage()};
|
slicer::MemView image{dex_file.CreateImage()};
|
||||||
|
|
||||||
|
|
@ -161,15 +163,13 @@ namespace lspd {
|
||||||
// only replace attribute name IDs for app packages
|
// only replace attribute name IDs for app packages
|
||||||
if (attrNameID >= 0 && (size_t) attrNameID < mTree.mNumResIds &&
|
if (attrNameID >= 0 && (size_t) attrNameID < mTree.mNumResIds &&
|
||||||
dtohl(mResIds[attrNameID]) >= 0x7f000000) {
|
dtohl(mResIds[attrNameID]) >= 0x7f000000) {
|
||||||
size_t attNameLen;
|
auto attrName = mTree.mStrings.stringAt(attrNameID);
|
||||||
const char16_t *attrName = ResStringPool_stringAt(&(mTree.mStrings),
|
|
||||||
attrNameID,
|
|
||||||
&attNameLen);
|
|
||||||
jint attrResID = env->CallStaticIntMethod(classXResources,
|
jint attrResID = env->CallStaticIntMethod(classXResources,
|
||||||
methodXResourcesTranslateAttrId,
|
methodXResourcesTranslateAttrId,
|
||||||
env->NewString(
|
env->NewString(
|
||||||
(const jchar *) attrName,
|
(const jchar *) attrName.data_,
|
||||||
attNameLen), origRes);
|
attrName.length_),
|
||||||
|
origRes);
|
||||||
if (env->ExceptionCheck())
|
if (env->ExceptionCheck())
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
|
@ -209,8 +209,10 @@ namespace lspd {
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
LSP_NATIVE_METHOD(ResourcesHook, initXResourcesNative, "()Z"),
|
LSP_NATIVE_METHOD(ResourcesHook, initXResourcesNative, "()Z"),
|
||||||
LSP_NATIVE_METHOD(ResourcesHook, removeFinalFlagNative, "(Ljava/lang/Class;)Z"),
|
LSP_NATIVE_METHOD(ResourcesHook, removeFinalFlagNative, "(Ljava/lang/Class;)Z"),
|
||||||
LSP_NATIVE_METHOD(ResourcesHook, buildDummyClassLoader, "(Ljava/lang/ClassLoader;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
|
LSP_NATIVE_METHOD(ResourcesHook, buildDummyClassLoader,
|
||||||
LSP_NATIVE_METHOD(ResourcesHook, rewriteXmlReferencesNative,"(JLandroid/content/res/XResources;Landroid/content/res/Resources;)V")
|
"(Ljava/lang/ClassLoader;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
|
||||||
|
LSP_NATIVE_METHOD(ResourcesHook, rewriteXmlReferencesNative,
|
||||||
|
"(JLandroid/content/res/XResources;Landroid/content/res/Resources;)V")
|
||||||
};
|
};
|
||||||
|
|
||||||
void RegisterResourcesHook(JNIEnv *env) {
|
void RegisterResourcesHook(JNIEnv *env) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue