Fixed #1972 AS3 Renaming invalid identifiers - various fixes

Fixed #1972 AS3 imports taken only from packages, not package internal
This commit is contained in:
Jindra Petřík
2023-02-14 22:10:17 +01:00
parent 45a7d36067
commit 08456da845
5 changed files with 124 additions and 55 deletions

View File

@@ -2690,9 +2690,23 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
}
public int deobfuscateAS3Identifiers(RenameType renameType) {
Map<Tag, Map<Integer, String>> stringUsageTypesMap = new HashMap<>();
Map<Tag, Set<Integer>> stringUsagesMap = new HashMap<>();
informListeners("deobfuscate", "Getting usages...");
for (Tag tag : getTags()) {
if (tag instanceof ABCContainerTag) {
((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(deobfuscated, renameType, true);
if (tag instanceof ABCContainerTag) {
Map<Integer, String> stringUsageTypes = new HashMap<>();
Set<Integer> stringUsages = ((ABCContainerTag)tag).getABC().getStringUsages();
((ABCContainerTag)tag).getABC().getStringUsageTypes(stringUsageTypes);
stringUsageTypesMap.put(tag, stringUsageTypes);
stringUsagesMap.put(tag, stringUsages);
}
}
for (Tag tag : getTags()) {
if (tag instanceof ABCContainerTag) {
((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(stringUsageTypesMap.get(tag),stringUsagesMap.get(tag), deobfuscated, renameType, true);
((ABCContainerTag) tag).getABC().constants.clearCachedMultinames();
((ABCContainerTag) tag).getABC().constants.clearCachedDottedChains();
tag.setModified(true);
@@ -2700,7 +2714,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
}
for (Tag tag : getTags()) {
if (tag instanceof ABCContainerTag) {
((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(deobfuscated, renameType, false);
((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(stringUsageTypesMap.get(tag),stringUsagesMap.get(tag), deobfuscated, renameType, false);
((ABCContainerTag) tag).getABC().constants.clearCachedMultinames();
((ABCContainerTag) tag).getABC().constants.clearCachedDottedChains();
tag.setModified(true);

View File

@@ -122,13 +122,13 @@ public class ABC implements Openable {
/* Map from multiname index of namespace value to namespace name**/
private Map<String, DottedChain> namespaceMap;
private String file;
private String fileTitle;
private OpenableList openableList;
private boolean isOpenable = false;
public ABC(ABCContainerTag tag) {
@@ -147,7 +147,7 @@ public class ABC implements Openable {
public SWF getSwf() {
return parentTag.getSwf();
}
public List<ABCContainerTag> getAbcTags() {
Openable openable = getOpenable();
if (openable instanceof SWF) {
@@ -259,6 +259,7 @@ public class ABC implements Openable {
public int removeTraps() throws InterruptedException {
return removeTraps(null);
}
public int removeTraps(DeobfuscationListener listener) throws InterruptedException {
int rem = 0;
for (int s = 0; s < script_info.size(); s++) {
@@ -289,10 +290,41 @@ public class ABC implements Openable {
}
return ret;
}
public void getTraitStringUsages(Set<Integer> ret, Traits traits) {
for (Trait t:traits.traits) {
if (t instanceof TraitClass) {
int ci = ((TraitClass)t).class_info;
getTraitStringUsages(ret, instance_info.get(ci).instance_traits);
getTraitStringUsages(ret, class_info.get(ci).static_traits);
}
if (t instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst)t;
if (tsc.value_kind == ValueKind.CONSTANT_Utf8) {
ret.add(tsc.value_index);
}
}
}
}
public Set<Integer> getStringUsages() {
Set<Integer> ret = new HashSet<>();
for (ScriptInfo si:script_info) {
getTraitStringUsages(ret, si.traits);
}
for (MethodInfo mi: method_info) {
if((mi.flags & MethodInfo.FLAG_HAS_OPTIONAL) == MethodInfo.FLAG_HAS_OPTIONAL) {
for (ValueKind vk : mi.optional) {
if (vk.value_kind == ValueKind.CONSTANT_Utf8) {
ret.add(vk.value_index);
}
}
}
}
for (MethodBody body : bodies) {
getTraitStringUsages(ret, body.traits);
for (AVM2Instruction ins : body.getCode().code) {
for (int i = 0; i < ins.definition.operands.length; i++) {
if (ins.definition.operands[i] == AVM2Code.DAT_STRING_INDEX) {
@@ -308,7 +340,11 @@ public class ABC implements Openable {
if (ret.containsKey(strIndex)) {
if (!"name".equals(usageType)) {
if (!ret.get(strIndex).equals(usageType)) {
ret.put(strIndex, "name");
if ("class".equals(usageType) || ret.get(strIndex).equals("class")) {
ret.put(strIndex, "class");
} else {
ret.put(strIndex, "name");
}
}
}
} else {
@@ -316,14 +352,14 @@ public class ABC implements Openable {
}
}
private void getStringUsageTypes(Map<Integer, String> ret, Traits traits, boolean classesOnly) {
private void getStringUsageTypes(Map<Integer, String> ret, Traits traits) {
for (Trait t : traits.traits) {
int strIndex = constants.getMultiname(t.name_index).name_index;
String usageType = "";
if (t instanceof TraitClass) {
TraitClass tc = (TraitClass) t;
getStringUsageTypes(ret, class_info.get(tc.class_info).static_traits, classesOnly);
getStringUsageTypes(ret, instance_info.get(tc.class_info).instance_traits, classesOnly);
getStringUsageTypes(ret, class_info.get(tc.class_info).static_traits);
getStringUsageTypes(ret, instance_info.get(tc.class_info).instance_traits);
if (instance_info.get(tc.class_info).name_index != 0) {
setStringUsageType(ret, constants.getMultiname(instance_info.get(tc.class_info).name_index).name_index, "class");
@@ -331,6 +367,9 @@ public class ABC implements Openable {
if (instance_info.get(tc.class_info).super_index != 0) {
setStringUsageType(ret, constants.getMultiname(instance_info.get(tc.class_info).super_index).name_index, "class");
}
for (int iface : instance_info.get(tc.class_info).interfaces) {
setStringUsageType(ret, constants.getMultiname(iface).name_index, "class");
}
usageType = "class";
}
@@ -339,14 +378,14 @@ public class ABC implements Openable {
usageType = "method";
MethodBody body = findBody(tm.method_info);
if (body != null) {
getStringUsageTypes(ret, body.traits, classesOnly);
getStringUsageTypes(ret, body.traits);
}
}
if (t instanceof TraitFunction) {
TraitFunction tf = (TraitFunction) t;
MethodBody body = findBody(tf.method_info);
if (body != null) {
getStringUsageTypes(ret, body.traits, classesOnly);
getStringUsageTypes(ret, body.traits);
}
usageType = "function";
}
@@ -359,15 +398,13 @@ public class ABC implements Openable {
usageType = "const";
}
}
if (usageType.equals("class") || (!classesOnly)) {
setStringUsageType(ret, strIndex, usageType);
}
setStringUsageType(ret, strIndex, usageType);
}
}
public void getStringUsageTypes(Map<Integer, String> ret, boolean classesOnly) {
public void getStringUsageTypes(Map<Integer, String> ret) {
for (ScriptInfo script : script_info) {
getStringUsageTypes(ret, script.traits, classesOnly);
getStringUsageTypes(ret, script.traits);
}
}
@@ -386,32 +423,40 @@ public class ABC implements Openable {
}
}
public void deobfuscateIdentifiers(HashMap<DottedChain, DottedChain> namesMap, RenameType renameType, boolean classesOnly) {
Set<Integer> stringUsages = getStringUsages();
public void deobfuscateIdentifiers(Map<Integer, String> stringUsageTypes, Set<Integer> stringUsages, HashMap<DottedChain, DottedChain> namesMap, RenameType renameType, boolean doClasses) {
Set<Integer> namespaceUsages = getNsStringUsages();
Map<Integer, String> stringUsageTypes = new HashMap<>();
informListeners("deobfuscate", "Getting usage types...");
getStringUsageTypes(stringUsageTypes, classesOnly);
AVM2Deobfuscation deobfuscation = getDeobfuscation();
for (int i = 0; i < instance_info.size(); i++) {
informListeners("deobfuscate", "class " + i + "/" + instance_info.size());
InstanceInfo insti = instance_info.get(i);
if (insti.name_index != 0) {
constants.getMultiname(insti.name_index).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(insti.name_index).name_index, true, renameType);
if (constants.getMultiname(insti.name_index).namespace_index != 0) {
constants.getNamespace(constants.getMultiname(insti.name_index).namespace_index).name_index
= deobfuscation.deobfuscatePackageName(stringUsageTypes, stringUsages, namesMap, constants.getNamespace(constants.getMultiname(insti.name_index).namespace_index).name_index, renameType);
if (doClasses) {
for (int i = 0; i < instance_info.size(); i++) {
informListeners("deobfuscate", "class " + i + "/" + instance_info.size());
InstanceInfo insti = instance_info.get(i);
if (insti.name_index != 0) {
constants.getMultiname(insti.name_index).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(insti.name_index).name_index, true, renameType);
if (constants.getMultiname(insti.name_index).namespace_index != 0) {
constants.getNamespace(constants.getMultiname(insti.name_index).namespace_index).name_index
= deobfuscation.deobfuscatePackageName(stringUsageTypes, stringUsages, namesMap, constants.getNamespace(constants.getMultiname(insti.name_index).namespace_index).name_index, renameType);
}
}
if (insti.super_index != 0) {
constants.getMultiname(insti.super_index).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(insti.super_index).name_index, true, renameType);
}
for (int iface : insti.interfaces) {
constants.getMultiname(iface).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(iface).name_index, true, renameType);
}
}
if (insti.super_index != 0) {
constants.getMultiname(insti.super_index).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(insti.super_index).name_index, true, renameType);
}
}
if (classesOnly) {
} else {
return;
}
for (int i = 1; i < constants.getMultinameCount(); i++) {
informListeners("deobfuscate", "name " + i + "/" + constants.getMultinameCount());
Multiname m = constants.getMultiname(i);
int strIndex = m.name_index;
if (m.kind == Multiname.MULTINAME && strIndex > 0 && "*".equals(constants.getString(strIndex))) {
continue;
}
constants.getMultiname(i).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(i).name_index, false, renameType);
}
for (int i = 1; i < constants.getNamespaceCount(); i++) {
@@ -436,7 +481,12 @@ public class ABC implements Openable {
String fullname = constants.getString(strIndex);
String pkg = "";
String name = fullname;
if (fullname.contains(".")) {
boolean hasFourDots = false;
if (fullname.contains("::")) {
pkg = fullname.substring(0, fullname.lastIndexOf("::"));
name = fullname.substring(fullname.lastIndexOf("::") + 2);
hasFourDots = true;
} else if (fullname.contains(".")) {
pkg = fullname.substring(0, fullname.lastIndexOf('.'));
name = fullname.substring(fullname.lastIndexOf('.') + 1);
}
@@ -450,7 +500,7 @@ public class ABC implements Openable {
name = constants.getString(nameStrIndex);
String fullChanged = "";
if (!pkg.isEmpty()) {
fullChanged = pkg + ".";
fullChanged = pkg + (hasFourDots ? "::" : ".");
}
fullChanged += name;
strIndex = constants.getStringId(fullChanged, true);
@@ -507,6 +557,7 @@ public class ABC implements Openable {
public ABC(ABCInputStream ais, SWF swf, ABCContainerTag tag) throws IOException {
this(ais, swf, tag, null, null);
}
public ABC(ABCInputStream ais, SWF swf, ABCContainerTag tag, String file, String fileTitle) throws IOException {
this.parentTag = tag;
this.file = file;
@@ -514,7 +565,7 @@ public class ABC implements Openable {
if (file != null || fileTitle != null) {
isOpenable = true;
}
try {
read(ais, swf);
} catch (IOException ie) {
@@ -526,7 +577,7 @@ public class ABC implements Openable {
SWFDecompilerPlugin.fireAbcParsed(this, swf);
}
private void read(ABCInputStream ais, SWF swf) throws IOException {
int minor_version = ais.readU16("minor_version");
int major_version = ais.readU16("major_version");
@@ -1039,7 +1090,7 @@ public class ABC implements Openable {
return abcMethodIndexing;
}
public void resetMethodIndexing() {
abcMethodIndexing = null;
}
@@ -2168,8 +2219,8 @@ public class ABC implements Openable {
@Override
public String getFile() {
return file;
}
}
@Override
public String getFileTitle() {
if (fileTitle != null) {
@@ -2185,7 +2236,7 @@ public class ABC implements Openable {
}
return new File(file).getName();
}
@Override
public String getShortPathTitle() {
if (openableList != null) {
@@ -2210,12 +2261,12 @@ public class ABC implements Openable {
}
return getFileTitle();
}
@Override
public boolean isModified() {
return getSwf().isModified(); //??
}
@Override
public void setOpenableList(OpenableList openableList) {
this.openableList = openableList;
@@ -2235,21 +2286,21 @@ public class ABC implements Openable {
@Override
public void saveTo(OutputStream os) throws IOException {
saveToStream(os);
}
}
@Override
public void setFile(String file) {
this.file = file;
fileTitle = null;
}
}
@Override
public void clearModified() {
getSwf().clearModified();
List<ABC> allAbcs = new ArrayList<>();
allAbcs.add(this);
List<ScriptPack> packs = getScriptPacks(null, allAbcs);
for(ScriptPack pack : packs) {
for (ScriptPack pack : packs) {
if (pack.isModified()) {
pack.clearModified();
}

View File

@@ -198,8 +198,10 @@ public class AVM2Deobfuscation {
newname = DottedChain.parseNoSuffix(str);
if (stringUsages.contains(strIndex) || namespaceUsages.contains(strIndex)) { // this name is already referenced as String
String usageType = stringUsageTypes.get(strIndex);
strIndex = constants.addString(s); // add new index
}
stringUsageTypes.put(strIndex, usageType);
}
constants.setString(strIndex, newname.toRawString());
if (!namesMap.containsKey(sChain)) {
namesMap.put(sChain, DottedChain.parseNoSuffix(constants.getString(strIndex)));

View File

@@ -50,7 +50,7 @@ public class DependencyParser {
if (parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, namespace_index, ignorePackage, name)) {
return;
} else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
} else if (ns.kind != Namespace.KIND_PACKAGE) { // && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
return;
}
newimport = newimport.addWithSuffix(name);