Correct resources types' offsets

This commit is contained in:
solohsu 2019-04-22 22:44:52 +08:00
parent 8a2cdbe47e
commit 6e6327bec8
2 changed files with 98 additions and 87 deletions

View File

@ -97,34 +97,41 @@ jboolean XposedBridge_initXResourcesNative(JNIEnv *env, jclass) {
void XResources_rewriteXmlReferencesNative(JNIEnv *env, jclass, void XResources_rewriteXmlReferencesNative(JNIEnv *env, jclass,
jlong parserPtr, jobject origRes, jobject repRes) { jlong parserPtr, jobject origRes, jobject repRes) {
ResXMLParser* parser = (ResXMLParser*)parserPtr;
const ResXMLTree& mTree = parser->mTree;
uint32_t* mResIds = (uint32_t*)mTree.mResIds;
ResXMLTree_attrExt* tag;
int attrCount;
if (parser == NULL) ResXMLParser *parser = (ResXMLParser *) parserPtr;
if (parser == nullptr)
return; return;
const ResXMLTree &mTree = parser->mTree;
uint32_t *mResIds = (uint32_t *) mTree.mResIds;
ResXMLTree_attrExt *tag;
int attrCount;
do { do {
switch (ResXMLParser_next(parser)) { switch (ResXMLParser_next(parser)) {
case ResXMLParser::START_TAG: case ResXMLParser::START_TAG:
tag = (ResXMLTree_attrExt*)parser->mCurExt; tag = (ResXMLTree_attrExt *) parser->mCurExt;
attrCount = dtohs(tag->attributeCount); attrCount = dtohs(tag->attributeCount);
for (int idx = 0; idx < attrCount; idx++) { for (int idx = 0; idx < attrCount; idx++) {
ResXMLTree_attribute* attr = (ResXMLTree_attribute*) ResXMLTree_attribute *attr = (ResXMLTree_attribute *)
(((const uint8_t*)tag) (((const uint8_t *) tag)
+ dtohs(tag->attributeStart) + dtohs(tag->attributeStart)
+ (dtohs(tag->attributeSize)*idx)); + (dtohs(tag->attributeSize) * idx));
// find resource IDs for attribute names // find resource IDs for attribute names
int32_t attrNameID = ResXMLParser_getAttributeNameID(parser, idx); int32_t attrNameID = ResXMLParser_getAttributeNameID(parser, idx);
// only replace attribute name IDs for app packages // only replace attribute name IDs for app packages
if (attrNameID >= 0 && (size_t)attrNameID < mTree.mNumResIds && dtohl(mResIds[attrNameID]) >= 0x7f000000) { if (attrNameID >= 0 && (size_t) attrNameID < mTree.mNumResIds &&
dtohl(mResIds[attrNameID]) >= 0x7f000000) {
size_t attNameLen; size_t attNameLen;
const char16_t* attrName = ResStringPool_stringAt(&(mTree.mStrings), attrNameID, &attNameLen); const char16_t *attrName = ResStringPool_stringAt(&(mTree.mStrings),
jint attrResID = env->CallStaticIntMethod(classXResources, methodXResourcesTranslateAttrId, attrNameID, &attNameLen);
env->NewString((const jchar*)attrName, attNameLen), origRes); jint attrResID = env->CallStaticIntMethod(classXResources,
methodXResourcesTranslateAttrId,
env->NewString(
(const jchar *) attrName,
attNameLen), origRes);
if (env->ExceptionCheck()) if (env->ExceptionCheck())
goto leave; goto leave;
@ -139,7 +146,8 @@ void XResources_rewriteXmlReferencesNative(JNIEnv *env, jclass,
if (oldValue < 0x7f000000) if (oldValue < 0x7f000000)
continue; continue;
jint newValue = env->CallStaticIntMethod(classXResources, methodXResourcesTranslateResId, jint newValue = env->CallStaticIntMethod(classXResources,
methodXResourcesTranslateResId,
oldValue, origRes, repRes); oldValue, origRes, repRes);
if (env->ExceptionCheck()) if (env->ExceptionCheck())
goto leave; goto leave;

View File

@ -13,35 +13,37 @@ static constexpr const char *kLibFwPath = "/system/lib64/libandroidfw.so";
static constexpr const char *kLibFwPath = "/system/lib/libandroidfw.so"; static constexpr const char *kLibFwPath = "/system/lib/libandroidfw.so";
#endif #endif
jboolean XposedBridge_initXResourcesNative(JNIEnv* env, jclass); jboolean XposedBridge_initXResourcesNative(JNIEnv *env, jclass);
void XResources_rewriteXmlReferencesNative(JNIEnv* env, jclass,
void XResources_rewriteXmlReferencesNative(JNIEnv *env, jclass,
jlong parserPtr, jobject origRes, jobject repRes); jlong parserPtr, jobject origRes, jobject repRes);
typedef int32_t status_t;
enum { enum {
RES_NULL_TYPE = 0x0000, RES_NULL_TYPE = 0x0000,
RES_STRING_POOL_TYPE = 0x0001, RES_STRING_POOL_TYPE = 0x0001,
RES_TABLE_TYPE = 0x0002, RES_TABLE_TYPE = 0x0002,
RES_XML_TYPE = 0x0003, RES_XML_TYPE = 0x0003,
// Chunk types in RES_XML_TYPE // Chunk types in RES_XML_TYPE
RES_XML_FIRST_CHUNK_TYPE = 0x0100, RES_XML_FIRST_CHUNK_TYPE = 0x0100,
RES_XML_START_NAMESPACE_TYPE= 0x0100, RES_XML_START_NAMESPACE_TYPE = 0x0100,
RES_XML_END_NAMESPACE_TYPE = 0x0101, RES_XML_END_NAMESPACE_TYPE = 0x0101,
RES_XML_START_ELEMENT_TYPE = 0x0102, RES_XML_START_ELEMENT_TYPE = 0x0102,
RES_XML_END_ELEMENT_TYPE = 0x0103, RES_XML_END_ELEMENT_TYPE = 0x0103,
RES_XML_CDATA_TYPE = 0x0104, RES_XML_CDATA_TYPE = 0x0104,
RES_XML_LAST_CHUNK_TYPE = 0x017f, RES_XML_LAST_CHUNK_TYPE = 0x017f,
// This contains a uint32_t array mapping strings in the string // This contains a uint32_t array mapping strings in the string
// pool back to resource identifiers. It is optional. // pool back to resource identifiers. It is optional.
RES_XML_RESOURCE_MAP_TYPE = 0x0180, RES_XML_RESOURCE_MAP_TYPE = 0x0180,
// Chunk types in RES_TABLE_TYPE // Chunk types in RES_TABLE_TYPE
RES_TABLE_PACKAGE_TYPE = 0x0200, RES_TABLE_PACKAGE_TYPE = 0x0200,
RES_TABLE_TYPE_TYPE = 0x0201, RES_TABLE_TYPE_TYPE = 0x0201,
RES_TABLE_TYPE_SPEC_TYPE = 0x0202, RES_TABLE_TYPE_SPEC_TYPE = 0x0202,
RES_TABLE_LIBRARY_TYPE = 0x0203 RES_TABLE_LIBRARY_TYPE = 0x0203
}; };
struct ResXMLTree_node struct ResXMLTree_node {
{
void *header; void *header;
// Line number in original source file at which this element appeared. // Line number in original source file at which this element appeared.
uint32_t lineNumber; uint32_t lineNumber;
@ -51,8 +53,8 @@ struct ResXMLTree_node
class ResXMLTree; class ResXMLTree;
class ResXMLParser class ResXMLParser {
{
public: public:
enum event_code_t { enum event_code_t {
BAD_DOCUMENT = -1, BAD_DOCUMENT = -1,
@ -68,61 +70,63 @@ public:
TEXT = RES_XML_CDATA_TYPE TEXT = RES_XML_CDATA_TYPE
}; };
public: const ResXMLTree &mTree;
friend class ResXMLTree; event_code_t mEventCode;
const ResXMLTree_node *mCurNode;
event_code_t nextNode(); const void *mCurExt;
const ResXMLTree& mTree;
event_code_t mEventCode;
const ResXMLTree_node* mCurNode;
const void* mCurExt;
}; };
class ResStringPool class ResStringPool {
{
public: public:
int32_t mError; status_t mError;
void* mOwnedData; void *mOwnedData;
const void* mHeader; const void *mHeader;
size_t mSize; size_t mSize;
mutable pthread_mutex_t mDecodeLock; mutable pthread_mutex_t mDecodeLock;
const uint32_t* mEntries; const uint32_t *mEntries;
const uint32_t* mEntryStyles; const uint32_t *mEntryStyles;
const void* mStrings; const void *mStrings;
char16_t mutable** mCache; char16_t mutable **mCache;
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
}; };
class ResXMLTree : public ResXMLParser class ResXMLTree : public ResXMLParser {
{
public: public:
friend class ResXMLParser; void *mDynamicRefTable;
int32_t validateNode(const ResXMLTree_node* node) const; status_t mError;
void* mDynamicRefTable; void *mOwnedData;
int32_t mError; const void *mHeader;
void* mOwnedData; size_t mSize;
const void* mHeader; const uint8_t *mDataEnd;
size_t mSize; ResStringPool mStrings;
const uint8_t* mDataEnd; const uint32_t *mResIds;
ResStringPool mStrings; size_t mNumResIds;
const uint32_t* mResIds; const ResXMLTree_node *mRootNode;
size_t mNumResIds; const void *mRootExt;
const ResXMLTree_node* mRootNode; event_code_t mRootCode;
const void* mRootExt;
event_code_t mRootCode;
}; };
struct ResXMLTree_attrExt struct ResStringPool_ref {
{
// Index into the string pool table (uint32_t-offset from the indices
// immediately after ResStringPool_header) at which to find the location
// of the string data in the pool.
uint32_t index;
};
struct ResXMLTree_attrExt {
// String of the full namespace of this element. // String of the full namespace of this element.
void* ns; struct ResStringPool_ref ns;
// String name of this node if it is an ELEMENT; the raw // String name of this node if it is an ELEMENT; the raw
// character data if this is a CDATA node. // character data if this is a CDATA node.
void* name; struct ResStringPool_ref name;
// Byte offset from the start of this structure where the attributes start. // Byte offset from the start of this structure where the attributes start.
uint16_t attributeStart; uint16_t attributeStart;
@ -145,8 +149,8 @@ struct ResXMLTree_attrExt
uint16_t styleIndex; uint16_t styleIndex;
}; };
struct Res_value struct Res_value {
{
// Number of bytes in this structure. // Number of bytes in this structure.
uint16_t size; uint16_t size;
// Always set to 0. // Always set to 0.
@ -253,18 +257,17 @@ struct Res_value
// The data for this item, as interpreted according to dataType. // The data for this item, as interpreted according to dataType.
typedef uint32_t data_type; typedef uint32_t data_type;
data_type data; data_type data;
void copyFrom_dtoh(const Res_value& src);
}; };
struct ResXMLTree_attribute struct ResXMLTree_attribute {
{
// Namespace of this attribute. // Namespace of this attribute.
void* ns; struct ResStringPool_ref ns;
// Name of this attribute. // Name of this attribute.
void* name; struct ResStringPool_ref name;
// The original raw string value of this attribute. // The original raw string value of this attribute.
void* rawValue; struct ResStringPool_ref rawValue;
// Processesd typed value of this attribute. // Processesd typed value of this attribute.
struct Res_value typedValue; struct Res_value typedValue;