[core] Fix resource hook on S (#377)
This commit is contained in:
parent
88f1f693c6
commit
aa98da59da
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
#include <cstdint>
|
||||
|
||||
// @ApiSensitive(Level.MIDDLE)
|
||||
|
|
@ -27,6 +28,45 @@ namespace android {
|
|||
|
||||
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 {
|
||||
RES_NULL_TYPE = 0x0000,
|
||||
RES_STRING_POOL_TYPE = 0x0001,
|
||||
|
|
@ -98,6 +138,46 @@ namespace android {
|
|||
uint32_t mStringPoolSize; // number of uint16_t
|
||||
const uint32_t *mStyles;
|
||||
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_RESTART ResXMLParser_restart = nullptr;
|
||||
static TYPE_GET_ATTR_NAME_ID ResXMLParser_getAttributeNameID = nullptr;
|
||||
static TYPE_STRING_AT ResStringPool_stringAt = nullptr;
|
||||
|
||||
static bool PrepareSymbols() {
|
||||
ScopedDlHandle fw_handle(kLibFwPath.c_str());
|
||||
|
|
@ -66,13 +65,12 @@ namespace lspd {
|
|||
"_ZNK7android12ResXMLParser18getAttributeNameIDEm")))) {
|
||||
return false;
|
||||
}
|
||||
return (ResStringPool_stringAt = fw_handle.DlSym<TYPE_STRING_AT>(
|
||||
LP_SELECT("_ZNK7android13ResStringPool8stringAtEjPj",
|
||||
"_ZNK7android13ResStringPool8stringAtEmPm"))) != nullptr;
|
||||
return android::ResStringPool::setup(fw_handle.Get());
|
||||
}
|
||||
|
||||
LSP_DEF_NATIVE_METHOD(jboolean, ResourcesHook, initXResourcesNative) {
|
||||
classXResources = Context::GetInstance()->FindClassFromCurrentLoader(env, kXResourcesClassName);
|
||||
classXResources = Context::GetInstance()->FindClassFromCurrentLoader(env,
|
||||
kXResourcesClassName);
|
||||
if (!classXResources) {
|
||||
LOGE("Error while loading XResources class '%s':", kXResourcesClassName);
|
||||
return JNI_FALSE;
|
||||
|
|
@ -109,9 +107,11 @@ namespace lspd {
|
|||
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;
|
||||
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>",
|
||||
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||
DexBuilder dex_file;
|
||||
|
|
@ -120,15 +120,17 @@ namespace lspd {
|
|||
auto current_thread = art::Thread::Current();
|
||||
ClassBuilder xresource_builder{
|
||||
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{
|
||||
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()};
|
||||
|
||||
auto dex_buffer = env->NewDirectByteBuffer(const_cast<void*>(image.ptr()), image.size());
|
||||
auto dex_buffer = env->NewDirectByteBuffer(const_cast<void *>(image.ptr()), image.size());
|
||||
return JNI_NewObject(env, in_memory_classloader, initMid,
|
||||
dex_buffer, parent);
|
||||
}
|
||||
|
|
@ -161,15 +163,13 @@ namespace lspd {
|
|||
// only replace attribute name IDs for app packages
|
||||
if (attrNameID >= 0 && (size_t) attrNameID < mTree.mNumResIds &&
|
||||
dtohl(mResIds[attrNameID]) >= 0x7f000000) {
|
||||
size_t attNameLen;
|
||||
const char16_t *attrName = ResStringPool_stringAt(&(mTree.mStrings),
|
||||
attrNameID,
|
||||
&attNameLen);
|
||||
auto attrName = mTree.mStrings.stringAt(attrNameID);
|
||||
jint attrResID = env->CallStaticIntMethod(classXResources,
|
||||
methodXResourcesTranslateAttrId,
|
||||
env->NewString(
|
||||
(const jchar *) attrName,
|
||||
attNameLen), origRes);
|
||||
(const jchar *) attrName.data_,
|
||||
attrName.length_),
|
||||
origRes);
|
||||
if (env->ExceptionCheck())
|
||||
goto leave;
|
||||
|
||||
|
|
@ -209,8 +209,10 @@ namespace lspd {
|
|||
static JNINativeMethod gMethods[] = {
|
||||
LSP_NATIVE_METHOD(ResourcesHook, initXResourcesNative, "()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, rewriteXmlReferencesNative,"(JLandroid/content/res/XResources;Landroid/content/res/Resources;)V")
|
||||
LSP_NATIVE_METHOD(ResourcesHook, buildDummyClassLoader,
|
||||
"(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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue