Xml deobf 2.0
This commit is contained in:
@@ -99,7 +99,8 @@ public final class ResourcesLoader {
|
||||
jadxRef.getXmlParser().parse(inputStream));
|
||||
|
||||
case ARSC:
|
||||
return new ResTableParser().decodeFiles(inputStream);
|
||||
return new ResTableParser()
|
||||
.decodeFiles(inputStream);
|
||||
|
||||
case IMG:
|
||||
return ResContainer.singleImageFile(rf.getName(), inputStream);
|
||||
|
||||
@@ -119,6 +119,13 @@ public class CodeWriter {
|
||||
buf.append(code.buf);
|
||||
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() {
|
||||
addLine();
|
||||
|
||||
@@ -55,12 +55,16 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
private boolean isOneLine = true;
|
||||
private int namespaceDepth = 0;
|
||||
private int[] resourceIds;
|
||||
|
||||
private RootNode rootNode;
|
||||
private String appPackageName;
|
||||
|
||||
public BinaryXMLParser(RootNode root) {
|
||||
public BinaryXMLParser(RootNode rootNode) {
|
||||
this.rootNode = rootNode;
|
||||
try {
|
||||
readAndroidRStyleClass();
|
||||
// add application constants
|
||||
ConstStorage constStorage = root.getConstValues();
|
||||
ConstStorage constStorage = rootNode.getConstValues();
|
||||
Map<Object, FieldNode> constFields = constStorage.getGlobalConstFields();
|
||||
for (Map.Entry<Object, FieldNode> entry : constFields.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
@@ -248,6 +252,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
isOneLine = true;
|
||||
isLastEnd = false;
|
||||
currentTag = getValidTagAttributeName(getString(startNSName));
|
||||
currentTag = deobfClassName(currentTag);
|
||||
writer.startLine("<").add(currentTag);
|
||||
writer.attachSourceLine(elementBegLineNumber);
|
||||
int attributeStart = is.readInt16();
|
||||
@@ -298,16 +303,23 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
} else {
|
||||
writer.add(' ');
|
||||
}
|
||||
String shortNsName = null;
|
||||
if (attributeNS != -1) {
|
||||
writer.add(getAttributeNS(attributeNS)).add(':');
|
||||
shortNsName = getAttributeNS(attributeNS);
|
||||
writer.add(shortNsName).add(':');
|
||||
}
|
||||
String attrName = getValidTagAttributeName(getAttributeName(attributeName));
|
||||
writer.add(attrName).add("=\"");
|
||||
String decodedAttr = ManifestAttributes.getInstance().decode(attrName, attrValData);
|
||||
if (decodedAttr != null) {
|
||||
memorizePackageName(attrName, decodedAttr);
|
||||
if(isDeobfCandidateAttr(shortNsName, attrName)) {
|
||||
decodedAttr = deobfClassName(decodedAttr);
|
||||
}
|
||||
writer.add(StringUtils.escapeXML(decodedAttr));
|
||||
} else {
|
||||
decodeAttribute(attributeNS, attrValDataType, attrValData);
|
||||
decodeAttribute(attributeNS, attrValDataType, attrValData,
|
||||
shortNsName, attrName);
|
||||
}
|
||||
writer.add('"');
|
||||
}
|
||||
@@ -367,7 +379,9 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
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) {
|
||||
// reference custom processing
|
||||
String name = styleMap.get(attrValData);
|
||||
@@ -408,6 +422,10 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
}
|
||||
} else {
|
||||
String str = valuesParser.decodeValue(attrValDataType, attrValData);
|
||||
memorizePackageName(attrName, str);
|
||||
if(isDeobfCandidateAttr(shortNsName, attrName)) {
|
||||
str = deobfClassName(str);
|
||||
}
|
||||
writer.add(str != null ? StringUtils.escapeXML(str) : "null");
|
||||
}
|
||||
}
|
||||
@@ -465,4 +483,30 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user