[core] Fix resource hook on S (#377)

This commit is contained in:
LoveSy 2021-03-20 01:23:01 +08:00 committed by GitHub
parent 88f1f693c6
commit aa98da59da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 142 additions and 60 deletions

View File

@ -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;
}
}; };

View File

@ -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) {