From e1aa9f6de4782cef111c5e16a55c55fc5ec1c5c7 Mon Sep 17 00:00:00 2001 From: nitram84 Date: Fri, 7 Apr 2023 14:58:33 +0200 Subject: [PATCH] fix(res): resolve custom attributes --- .../java/jadx/core/dex/nodes/RootNode.java | 7 ++++ .../jadx/core/xmlgen/ManifestAttributes.java | 38 ++++++++++++++++++- .../main/java/jadx/core/xmlgen/ResXmlGen.java | 4 +- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java index c641ea99b..c176bf7c5 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java @@ -43,6 +43,7 @@ import jadx.core.utils.Utils; import jadx.core.utils.android.AndroidResourcesUtils; import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.xmlgen.IResParser; +import jadx.core.xmlgen.ManifestAttributes; import jadx.core.xmlgen.ResDecoder; import jadx.core.xmlgen.ResourceStorage; import jadx.core.xmlgen.entry.ResourceEntry; @@ -174,12 +175,18 @@ public class RootNode { if (parser != null) { processResources(parser.getResStorage()); updateObfuscatedFiles(parser, resources); + updateManifestAttribMap(parser); } } catch (Exception e) { LOG.error("Failed to parse '.arsc' file", e); } } + private void updateManifestAttribMap(IResParser parser) { + ManifestAttributes manifestAttributes = ManifestAttributes.getInstance(); + manifestAttributes.updateAttributes(parser); + } + private @Nullable ResourceFile getResourceFile(List resources) { for (ResourceFile rf : resources) { if (rf.getType() == ResourceType.ARSC) { diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/ManifestAttributes.java b/jadx-core/src/main/java/jadx/core/xmlgen/ManifestAttributes.java index 283d1a035..7d9db9b1b 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/ManifestAttributes.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/ManifestAttributes.java @@ -17,6 +17,9 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import jadx.core.utils.exceptions.JadxRuntimeException; +import jadx.core.xmlgen.entry.RawNamedValue; +import jadx.core.xmlgen.entry.ResourceEntry; +import jadx.core.xmlgen.entry.ValuesParser; public class ManifestAttributes { private static final Logger LOG = LoggerFactory.getLogger(ManifestAttributes.class); @@ -52,6 +55,8 @@ public class ManifestAttributes { private final Map attrMap = new HashMap<>(); + private final Map appAttrMap = new HashMap<>(); + private static ManifestAttributes instance; public static ManifestAttributes getInstance() { @@ -168,7 +173,10 @@ public class ManifestAttributes { public String decode(String attrName, long value) { MAttr attr = attrMap.get(attrName); if (attr == null) { - return null; + attr = appAttrMap.get(attrName); + if (attr == null) { + return null; + } } if (attr.getType() == MAttrType.ENUM) { return attr.getValues().get(value); @@ -190,4 +198,32 @@ public class ManifestAttributes { } return null; } + + public void updateAttributes(IResParser parser) { + appAttrMap.clear(); + + ResourceStorage resStorage = parser.getResStorage(); + ValuesParser vp = new ValuesParser(parser.getStrings(), resStorage.getResourcesNames()); + + for (ResourceEntry ri : resStorage.getResources()) { + if (ri.getTypeName().equals("attr") && ri.getNamedValues().size() > 1) { + RawNamedValue first = ri.getNamedValues().get(0); + MAttrType attrTyp; + if (first.getRawValue().getData() == ValuesParser.ATTR_TYPE_FLAGS) { + attrTyp = MAttrType.FLAG; + } else if (first.getRawValue().getData() == ValuesParser.ATTR_TYPE_ENUM) { + attrTyp = MAttrType.ENUM; + } else { + continue; + } + MAttr attr = new MAttr(attrTyp); + for (int i = 1; i < ri.getNamedValues().size(); i++) { + RawNamedValue rv = ri.getNamedValues().get(i); + String value = vp.decodeNameRef(rv.getNameRef()); + attr.getValues().put((long) rv.getRawValue().getData(), value.startsWith("id.") ? value.substring(3) : value); + } + appAttrMap.put(ri.getKeyName(), attr); + } + } + } } diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java b/jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java index 1d6938976..b20733297 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java @@ -177,7 +177,7 @@ public class ResXmlGen { if (dataType == ParserConstants.TYPE_INT_DEC && nameStr != null) { try { int intVal = Integer.parseInt(valueStr); - String newVal = ManifestAttributes.getInstance().decode(nameStr.replace("android:attr.", ""), intVal); + String newVal = ManifestAttributes.getInstance().decode(nameStr.replace("android:", "").replace("attr.", ""), intVal); if (newVal != null) { valueStr = newVal; } @@ -188,7 +188,7 @@ public class ResXmlGen { if (dataType == ParserConstants.TYPE_INT_HEX && nameStr != null) { try { int intVal = Integer.decode(valueStr); - String newVal = ManifestAttributes.getInstance().decode(nameStr.replace("android:attr.", ""), intVal); + String newVal = ManifestAttributes.getInstance().decode(nameStr.replace("android:", "").replace("attr.", ""), intVal); if (newVal != null) { valueStr = newVal; }