Unverified Commit 1931e783 authored by skylot's avatar skylot Committed by GitHub

Merge pull request #290 from skylot/xml_deobf_2

Xml deobf 2.0
parents 4f02864e 90692d89
...@@ -99,7 +99,8 @@ public final class ResourcesLoader { ...@@ -99,7 +99,8 @@ public final class ResourcesLoader {
jadxRef.getXmlParser().parse(inputStream)); jadxRef.getXmlParser().parse(inputStream));
case ARSC: case ARSC:
return new ResTableParser().decodeFiles(inputStream); return new ResTableParser()
.decodeFiles(inputStream);
case IMG: case IMG:
return ResContainer.singleImageFile(rf.getName(), inputStream); return ResContainer.singleImageFile(rf.getName(), inputStream);
......
...@@ -119,6 +119,13 @@ public class CodeWriter { ...@@ -119,6 +119,13 @@ public class CodeWriter {
buf.append(code.buf); buf.append(code.buf);
return this; return this;
} }
public void updateContent(String newData) {
offset = newData.length();
buf = new StringBuilder(newData);
line = newData.split(NL).length + 1;
code = newData;
}
public CodeWriter newLine() { public CodeWriter newLine() {
addLine(); addLine();
......
...@@ -55,12 +55,16 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -55,12 +55,16 @@ public class BinaryXMLParser extends CommonBinaryParser {
private boolean isOneLine = true; private boolean isOneLine = true;
private int namespaceDepth = 0; private int namespaceDepth = 0;
private int[] resourceIds; private int[] resourceIds;
private RootNode rootNode;
private String appPackageName;
public BinaryXMLParser(RootNode root) { public BinaryXMLParser(RootNode rootNode) {
this.rootNode = rootNode;
try { try {
readAndroidRStyleClass(); readAndroidRStyleClass();
// add application constants // add application constants
ConstStorage constStorage = root.getConstValues(); ConstStorage constStorage = rootNode.getConstValues();
Map<Object, FieldNode> constFields = constStorage.getGlobalConstFields(); Map<Object, FieldNode> constFields = constStorage.getGlobalConstFields();
for (Map.Entry<Object, FieldNode> entry : constFields.entrySet()) { for (Map.Entry<Object, FieldNode> entry : constFields.entrySet()) {
Object key = entry.getKey(); Object key = entry.getKey();
...@@ -248,6 +252,7 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -248,6 +252,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
isOneLine = true; isOneLine = true;
isLastEnd = false; isLastEnd = false;
currentTag = getValidTagAttributeName(getString(startNSName)); currentTag = getValidTagAttributeName(getString(startNSName));
currentTag = deobfClassName(currentTag);
writer.startLine("<").add(currentTag); writer.startLine("<").add(currentTag);
writer.attachSourceLine(elementBegLineNumber); writer.attachSourceLine(elementBegLineNumber);
int attributeStart = is.readInt16(); int attributeStart = is.readInt16();
...@@ -298,16 +303,23 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -298,16 +303,23 @@ public class BinaryXMLParser extends CommonBinaryParser {
} else { } else {
writer.add(' '); writer.add(' ');
} }
String shortNsName = null;
if (attributeNS != -1) { if (attributeNS != -1) {
writer.add(getAttributeNS(attributeNS)).add(':'); shortNsName = getAttributeNS(attributeNS);
writer.add(shortNsName).add(':');
} }
String attrName = getValidTagAttributeName(getAttributeName(attributeName)); String attrName = getValidTagAttributeName(getAttributeName(attributeName));
writer.add(attrName).add("=\""); writer.add(attrName).add("=\"");
String decodedAttr = ManifestAttributes.getInstance().decode(attrName, attrValData); String decodedAttr = ManifestAttributes.getInstance().decode(attrName, attrValData);
if (decodedAttr != null) { if (decodedAttr != null) {
memorizePackageName(attrName, decodedAttr);
if(isDeobfCandidateAttr(shortNsName, attrName)) {
decodedAttr = deobfClassName(decodedAttr);
}
writer.add(StringUtils.escapeXML(decodedAttr)); writer.add(StringUtils.escapeXML(decodedAttr));
} else { } else {
decodeAttribute(attributeNS, attrValDataType, attrValData); decodeAttribute(attributeNS, attrValDataType, attrValData,
shortNsName, attrName);
} }
writer.add('"'); writer.add('"');
} }
...@@ -367,7 +379,9 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -367,7 +379,9 @@ public class BinaryXMLParser extends CommonBinaryParser {
return "NOT_FOUND_STR_0x" + Integer.toHexString(strId); return "NOT_FOUND_STR_0x" + Integer.toHexString(strId);
} }
private void decodeAttribute(int attributeNS, int attrValDataType, int attrValData) { private void decodeAttribute(int attributeNS, int attrValDataType, int attrValData,
String shortNsName, String attrName) {
if (attrValDataType == TYPE_REFERENCE) { if (attrValDataType == TYPE_REFERENCE) {
// reference custom processing // reference custom processing
String name = styleMap.get(attrValData); String name = styleMap.get(attrValData);
...@@ -408,6 +422,10 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -408,6 +422,10 @@ public class BinaryXMLParser extends CommonBinaryParser {
} }
} else { } else {
String str = valuesParser.decodeValue(attrValDataType, attrValData); String str = valuesParser.decodeValue(attrValDataType, attrValData);
memorizePackageName(attrName, str);
if(isDeobfCandidateAttr(shortNsName, attrName)) {
str = deobfClassName(str);
}
writer.add(str != null ? StringUtils.escapeXML(str) : "null"); writer.add(str != null ? StringUtils.escapeXML(str) : "null");
} }
} }
...@@ -465,4 +483,30 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -465,4 +483,30 @@ public class BinaryXMLParser extends CommonBinaryParser {
} }
return sb.toString(); return sb.toString();
} }
private String deobfClassName(String className) {
String newName = XmlDeobf.deobfClassName(rootNode, className,
appPackageName);
if(newName != null) {
return newName;
}
return className;
}
private boolean isDeobfCandidateAttr(String shortNsName, String attrName) {
String fullName;
if(shortNsName != null) {
fullName = shortNsName + ":" + attrName;
}
else {
return false;
}
return "android:name".equals(fullName);
}
private void memorizePackageName(String attrName, String attrValue) {
if("manifest".equals(currentTag) && "package".equals(attrName)) {
appPackageName = attrValue;
}
}
} }
package jadx.core.xmlgen;
import java.util.HashMap;
import java.util.Map;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
/*
* modifies android:name attributes and xml tags which are old class names
* but were changed during deobfuscation
*/
public class XmlDeobf {
private static final Map<String, String> deobfMap = new HashMap<>();
private XmlDeobf() {}
public static String deobfClassName(RootNode rootNode, String potencialClassName,
String packageName) {
if(packageName != null && potencialClassName.startsWith(".")) {
potencialClassName = packageName + potencialClassName;
}
return getNewClassName(rootNode, potencialClassName);
}
private static String getNewClassName(RootNode rootNode, String old) {
if(deobfMap.isEmpty()) {
for(ClassNode classNode : rootNode.getClasses(true)) {
if(classNode.getAlias() != null) {
String oldName = classNode.getClassInfo().getFullName();
String newName = classNode.getAlias().getFullName();
if(!oldName.equals(newName)) {
deobfMap.put(oldName, newName);
}
}
}
}
return deobfMap.get(old);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment