mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-17 15:48:08 +00:00
Issue #67 Renaming invalid identifiers to Type+Number
This commit is contained in:
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash;
|
||||
|
||||
import SevenZip.Compression.LZMA.Encoder;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.RenameType;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionGraphSource;
|
||||
@@ -559,10 +560,20 @@ public class SWF {
|
||||
|
||||
public final void addEventListener(EventListener listener) {
|
||||
listeners.add(listener);
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ABCContainerTag) {
|
||||
(((ABCContainerTag) t).getABC()).addEventListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void removeEventListener(EventListener listener) {
|
||||
listeners.remove(listener);
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ABCContainerTag) {
|
||||
(((ABCContainerTag) t).getABC()).removeEventListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void informListeners(String event, Object data) {
|
||||
@@ -1057,6 +1068,7 @@ public class SWF {
|
||||
private HashSet<String> allVariableNamesStr = new HashSet<>();
|
||||
private List<GraphSourceItem> allFunctions = new ArrayList<>();
|
||||
private HashMap<DirectValueTreeItem, ConstantPool> allStrings = new HashMap<>();
|
||||
private HashMap<DirectValueTreeItem, String> usageTypes = new HashMap<>();
|
||||
|
||||
private String fooString(String orig, boolean firstUppercase, int rndSize) {
|
||||
boolean exists;
|
||||
@@ -1098,7 +1110,7 @@ public class SWF {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String deobfuscateName(HashMap<String, String> namesMap, String s, boolean firstUppercase) {
|
||||
public String deobfuscateName(HashMap<String, String> namesMap, String s, boolean firstUppercase, String usageType, RenameType renameType) {
|
||||
boolean isValid = true;
|
||||
if (isReserved(s)) {
|
||||
isValid = false;
|
||||
@@ -1119,19 +1131,36 @@ public class SWF {
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValid) {
|
||||
if (namesMap.containsKey(s)) {
|
||||
return namesMap.get(s);
|
||||
} else {
|
||||
String ret = fooString(s, firstUppercase, DEFAULT_FOO_SIZE);
|
||||
Integer cnt = typeCounts.get(usageType);
|
||||
if (cnt == null) {
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
String ret;
|
||||
if (renameType == RenameType.TYPENUMBER) {
|
||||
|
||||
boolean found;
|
||||
do {
|
||||
found = false;
|
||||
cnt++;
|
||||
ret = usageType + "_" + cnt;
|
||||
found = allVariableNamesStr.contains(ret);
|
||||
} while (found);
|
||||
typeCounts.put(usageType, cnt);
|
||||
} else {
|
||||
ret = fooString(s, firstUppercase, DEFAULT_FOO_SIZE);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void getVariables(ConstantPool constantPool, List<Object> localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, ActionGraphSource code, int ip, int lastIp, HashMap<DirectValueTreeItem, ConstantPool> variables, List<GraphSourceItem> functions, HashMap<DirectValueTreeItem, ConstantPool> strings, List<Integer> visited) {
|
||||
private static void getVariables(ConstantPool constantPool, List<Object> localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, ActionGraphSource code, int ip, int lastIp, HashMap<DirectValueTreeItem, ConstantPool> variables, List<GraphSourceItem> functions, HashMap<DirectValueTreeItem, ConstantPool> strings, List<Integer> visited, HashMap<DirectValueTreeItem, String> usageTypes) {
|
||||
boolean debugMode = false;
|
||||
while ((ip > -1) && ip < code.size()) {
|
||||
if (visited.contains(ip)) {
|
||||
@@ -1149,6 +1178,7 @@ public class SWF {
|
||||
continue;
|
||||
}
|
||||
|
||||
String usageType = "name";
|
||||
GraphTargetItem name = null;
|
||||
if ((ins instanceof ActionGetVariable)
|
||||
|| (ins instanceof ActionGetMember)
|
||||
@@ -1160,6 +1190,21 @@ public class SWF {
|
||||
name = stack.peek();
|
||||
}
|
||||
|
||||
if ((ins instanceof ActionGetVariable) || (ins instanceof ActionDefineLocal2)) {
|
||||
usageType = "variable";
|
||||
}
|
||||
if (ins instanceof ActionGetMember) {
|
||||
usageType = "member";
|
||||
}
|
||||
if ((ins instanceof ActionNewMethod) || (ins instanceof ActionNewObject)) {
|
||||
usageType = "class";
|
||||
}
|
||||
if (ins instanceof ActionCallMethod) {
|
||||
usageType = "function"; //can there be method?
|
||||
}
|
||||
if (ins instanceof ActionCallFunction) {
|
||||
usageType = "function";
|
||||
}
|
||||
|
||||
if ((ins instanceof ActionDefineFunction) || (ins instanceof ActionDefineFunction2)) {
|
||||
functions.add(ins);
|
||||
@@ -1176,18 +1221,33 @@ public class SWF {
|
||||
ip = code.adr2pos(addr);
|
||||
addr += size;
|
||||
int nextip = code.adr2pos(addr);
|
||||
getVariables(variables, functions, strings, new ActionGraphSource(code.getActions().subList(ip, nextip), code.version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), 0);
|
||||
getVariables(variables, functions, strings, usageTypes, new ActionGraphSource(code.getActions().subList(ip, nextip), code.version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), 0);
|
||||
ip = nextip;
|
||||
}
|
||||
((GraphSourceItemContainer) ins).translateContainer(new ArrayList<List<GraphTargetItem>>(), stack, output, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
|
||||
List<List<GraphTargetItem>> r = new ArrayList<>();
|
||||
r.add(new ArrayList<GraphTargetItem>());
|
||||
r.add(new ArrayList<GraphTargetItem>());
|
||||
r.add(new ArrayList<GraphTargetItem>());
|
||||
((GraphSourceItemContainer) ins).translateContainer(r, stack, output, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
|
||||
ip++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ins instanceof ActionSetVariable) || (ins instanceof ActionSetMember) || (ins instanceof ActionDefineLocal)) {
|
||||
name = stack.get(stack.size() - 2);
|
||||
}
|
||||
|
||||
if ((ins instanceof ActionSetVariable) || (ins instanceof ActionDefineLocal)) {
|
||||
usageType = "variable";
|
||||
}
|
||||
|
||||
if (ins instanceof ActionSetMember) {
|
||||
usageType = "member";
|
||||
}
|
||||
|
||||
if (name instanceof DirectValueTreeItem) {
|
||||
variables.put((DirectValueTreeItem) name, constantPool);
|
||||
usageTypes.put((DirectValueTreeItem) name, usageType);
|
||||
}
|
||||
|
||||
//for..in return
|
||||
@@ -1230,7 +1290,7 @@ public class SWF {
|
||||
@SuppressWarnings("unchecked")
|
||||
Stack<GraphTargetItem> brStack = (Stack<GraphTargetItem>) stack.clone();
|
||||
if (b >= 0) {
|
||||
getVariables(constantPool, localData, brStack, output, code, b, ip, variables, functions, strings, visited);
|
||||
getVariables(constantPool, localData, brStack, output, code, b, ip, variables, functions, strings, visited, usageTypes);
|
||||
} else {
|
||||
if (debugMode) {
|
||||
System.out.println("Negative branch:" + b);
|
||||
@@ -1244,29 +1304,38 @@ public class SWF {
|
||||
};
|
||||
}
|
||||
|
||||
private static void getVariables(HashMap<DirectValueTreeItem, ConstantPool> variables, List<GraphSourceItem> functions, HashMap<DirectValueTreeItem, ConstantPool> strings, ActionGraphSource code, int addr) {
|
||||
private static void getVariables(HashMap<DirectValueTreeItem, ConstantPool> variables, List<GraphSourceItem> functions, HashMap<DirectValueTreeItem, ConstantPool> strings, HashMap<DirectValueTreeItem, String> usageType, ActionGraphSource code, int addr) {
|
||||
List<Object> localData = Helper.toList(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
|
||||
try {
|
||||
getVariables(null, localData, new Stack<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), code, code.adr2pos(addr), 0, variables, functions, strings, new ArrayList<Integer>());
|
||||
getVariables(null, localData, new Stack<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), code, code.adr2pos(addr), 0, variables, functions, strings, new ArrayList<Integer>(), usageType);
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, "Getting variables error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<DirectValueTreeItem, ConstantPool> getVariables(HashMap<DirectValueTreeItem, ConstantPool> variables, List<GraphSourceItem> functions, HashMap<DirectValueTreeItem, ConstantPool> strings, ASMSource src) {
|
||||
private HashMap<DirectValueTreeItem, ConstantPool> getVariables(HashMap<DirectValueTreeItem, ConstantPool> variables, List<GraphSourceItem> functions, HashMap<DirectValueTreeItem, ConstantPool> strings, HashMap<DirectValueTreeItem, String> usageType, ASMSource src) {
|
||||
HashMap<DirectValueTreeItem, ConstantPool> ret = new HashMap<>();
|
||||
List<Action> actions = src.getActions(version);
|
||||
actionsMap.put(src, actions);
|
||||
getVariables(variables, functions, strings, new ActionGraphSource(actions, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), 0);
|
||||
getVariables(variables, functions, strings, usageType, new ActionGraphSource(actions, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), 0);
|
||||
return ret;
|
||||
}
|
||||
private HashMap<ASMSource, List<Action>> actionsMap = new HashMap<>();
|
||||
|
||||
private void getVariables(List<Object> objs, String path) {
|
||||
List<String> processed = new ArrayList<>();
|
||||
for (Object o : objs) {
|
||||
if (o instanceof ASMSource) {
|
||||
informListeners("getVariables", path + "/" + o.toString());
|
||||
getVariables(allVariableNames, allFunctions, allStrings, (ASMSource) o);
|
||||
String infPath = path + "/" + o.toString();
|
||||
int pos = 1;
|
||||
String infPath2 = infPath;
|
||||
while (processed.contains(infPath2)) {
|
||||
pos++;
|
||||
infPath2 = infPath + "[" + pos + "]";
|
||||
}
|
||||
processed.add(infPath2);
|
||||
informListeners("getVariables", infPath2);
|
||||
getVariables(allVariableNames, allFunctions, allStrings, usageTypes, (ASMSource) o);
|
||||
}
|
||||
if (o instanceof Container) {
|
||||
getVariables(((Container) o).getSubItems(), path + "/" + o.toString());
|
||||
@@ -1274,11 +1343,11 @@ public class SWF {
|
||||
}
|
||||
}
|
||||
|
||||
public int deobfuscateAS3Identifiers() {
|
||||
public int deobfuscateAS3Identifiers(RenameType renameType) {
|
||||
HashMap<String, String> namesMap = new HashMap<>();
|
||||
for (Tag tag : tags) {
|
||||
if (tag instanceof ABCContainerTag) {
|
||||
((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(namesMap);
|
||||
((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(namesMap, renameType);
|
||||
}
|
||||
}
|
||||
for (Tag tag : tags) {
|
||||
@@ -1318,55 +1387,61 @@ public class SWF {
|
||||
}
|
||||
return namesMap.size();
|
||||
}
|
||||
HashMap<String, Integer> typeCounts = new HashMap<>();
|
||||
|
||||
public int deobfuscateAS2Identifiers() {
|
||||
public int deobfuscateAS2Identifiers(RenameType renameType) {
|
||||
actionsMap = new HashMap<>();
|
||||
allFunctions = new ArrayList<>();
|
||||
allVariableNames = new HashMap<>();
|
||||
allStrings = new HashMap<>();
|
||||
|
||||
List<Object> objs = new ArrayList<>();
|
||||
int ret = 0;
|
||||
objs.addAll(tags);
|
||||
getVariables(objs, "");
|
||||
informListeners("deobfuscate", "");
|
||||
int fc = 0;
|
||||
for (DirectValueTreeItem ti : allVariableNames.keySet()) {
|
||||
String name = ti.toStringNoH(allVariableNames.get(ti));
|
||||
allVariableNamesStr.add(name);
|
||||
}
|
||||
for (GraphSourceItem fun : allFunctions) {
|
||||
fc++;
|
||||
informListeners("deobfuscate", "function " + fc + "/" + allFunctions.size());
|
||||
if (fun instanceof ActionDefineFunction) {
|
||||
ActionDefineFunction f = (ActionDefineFunction) fun;
|
||||
String changed = deobfuscateName(deobfuscated, f.functionName, false);
|
||||
String changed = deobfuscateName(deobfuscated, f.functionName, false, "function", renameType);
|
||||
if (changed != null) {
|
||||
f.replacedFunctionName = changed;
|
||||
}
|
||||
}
|
||||
if (fun instanceof ActionDefineFunction2) {
|
||||
ActionDefineFunction2 f = (ActionDefineFunction2) fun;
|
||||
String changed = deobfuscateName(deobfuscated, f.functionName, false);
|
||||
String changed = deobfuscateName(deobfuscated, f.functionName, false, "function", renameType);
|
||||
if (changed != null) {
|
||||
f.replacedFunctionName = changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (DirectValueTreeItem ti : allVariableNames.keySet()) {
|
||||
String name = ti.toStringNoH(allVariableNames.get(ti));
|
||||
allVariableNamesStr.add(name);
|
||||
}
|
||||
//Ommit variables from all strings
|
||||
HashMap<DirectValueTreeItem, ConstantPool> stringsNoVar = new HashMap<>();
|
||||
|
||||
HashSet<String> stringsNoVarH = new HashSet<>();
|
||||
for (DirectValueTreeItem ti : allStrings.keySet()) {
|
||||
if (!allVariableNames.containsKey(ti)) {
|
||||
stringsNoVar.put(ti, allStrings.get(ti));
|
||||
stringsNoVarH.add(System.identityHashCode(allStrings.get(ti)) + "_" + ti.toStringNoH(allStrings.get(ti)));
|
||||
}
|
||||
}
|
||||
|
||||
int vc = 0;
|
||||
for (DirectValueTreeItem ti : allVariableNames.keySet()) {
|
||||
vc++;
|
||||
informListeners("deobfuscate", "variable " + vc + "/" + allVariableNames.size());
|
||||
String name = ti.toStringNoH(allVariableNames.get(ti));
|
||||
String changed = deobfuscateName(deobfuscated, name, false);
|
||||
String changed = deobfuscateName(deobfuscated, name, false, usageTypes.get(ti), renameType);
|
||||
if (changed != null) {
|
||||
boolean addNew = false;
|
||||
for (DirectValueTreeItem snv : stringsNoVar.keySet()) {
|
||||
if (stringsNoVar.get(snv) == allVariableNames.get(ti)) { //Same constantpool
|
||||
if (snv.toStringNoH(stringsNoVar.get(snv)).equals(name)) { //Same string
|
||||
addNew = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
String h = System.identityHashCode(allVariableNames.get(ti)) + "_" + name;
|
||||
if (stringsNoVarH.contains(h)) {
|
||||
addNew = true;
|
||||
}
|
||||
ActionPush pu = (ActionPush) ti.src;
|
||||
if (pu.replacement == null) {
|
||||
@@ -1376,6 +1451,12 @@ public class SWF {
|
||||
if (pu.replacement.get(ti.pos) instanceof ConstantIndex) {
|
||||
ConstantIndex ci = (ConstantIndex) pu.replacement.get(ti.pos);
|
||||
ConstantPool pool = allVariableNames.get(ti);
|
||||
if (pool == null) {
|
||||
continue;
|
||||
}
|
||||
if (pool.constants == null) {
|
||||
continue;
|
||||
}
|
||||
if (addNew) {
|
||||
pool.constants.add(changed);
|
||||
ci.index = pool.constants.size() - 1;
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.types.*;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
|
||||
@@ -33,6 +35,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -111,21 +114,90 @@ public class ABC {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void deobfuscateIdentifiers(HashMap<String, String> namesMap) {
|
||||
private void setStringUsageType(Map<Integer, String> ret, int strIndex, String usageType) {
|
||||
if (ret.containsKey(strIndex)) {
|
||||
if (!ret.get(strIndex).equals(usageType)) {
|
||||
ret.put(strIndex, "name");
|
||||
}
|
||||
} else {
|
||||
ret.put(strIndex, usageType);
|
||||
}
|
||||
}
|
||||
|
||||
private void getStringUsageTypes(Map<Integer, String> ret, Traits traits) {
|
||||
for (Trait t : traits.traits) {
|
||||
int strIndex = constants.constant_multiname[t.name_index].name_index;
|
||||
String usageType = "";
|
||||
if (t instanceof TraitClass) {
|
||||
TraitClass tc = (TraitClass) t;
|
||||
getStringUsageTypes(ret, class_info[tc.class_info].static_traits);
|
||||
getStringUsageTypes(ret, instance_info[tc.class_info].instance_traits);
|
||||
|
||||
if (instance_info[tc.class_info].name_index != 0) {
|
||||
setStringUsageType(ret, constants.constant_multiname[instance_info[tc.class_info].name_index].name_index, "class");
|
||||
}
|
||||
if (instance_info[tc.class_info].super_index != 0) {
|
||||
setStringUsageType(ret, constants.constant_multiname[instance_info[tc.class_info].super_index].name_index, "class");
|
||||
}
|
||||
|
||||
usageType = "class";
|
||||
}
|
||||
if (t instanceof TraitMethodGetterSetter) {
|
||||
TraitMethodGetterSetter tm = (TraitMethodGetterSetter) t;
|
||||
usageType = "method";
|
||||
MethodBody body = findBody(tm.method_info);
|
||||
if (body != null) {
|
||||
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);
|
||||
}
|
||||
usageType = "function";
|
||||
}
|
||||
if (t instanceof TraitSlotConst) {
|
||||
TraitSlotConst ts = (TraitSlotConst) t;
|
||||
if (ts.isVar()) {
|
||||
usageType = "var";
|
||||
}
|
||||
if (ts.isConst()) {
|
||||
usageType = "const";
|
||||
}
|
||||
}
|
||||
setStringUsageType(ret, strIndex, usageType);
|
||||
}
|
||||
}
|
||||
|
||||
public void getStringUsageTypes(Map<Integer, String> ret) {
|
||||
for (ScriptInfo script : script_info) {
|
||||
getStringUsageTypes(ret, script.traits);
|
||||
}
|
||||
}
|
||||
|
||||
public void deobfuscateIdentifiers(HashMap<String, String> namesMap, RenameType renameType) {
|
||||
Set<Integer> stringUsages = getStringUsages();
|
||||
Map<Integer, String> stringUsageTypes = new HashMap<>();
|
||||
informListeners("deobfuscate", "Getting usage types...");
|
||||
getStringUsageTypes(stringUsageTypes);
|
||||
for (int i = 1; i < instance_info.length; i++) {
|
||||
informListeners("deobfuscate", "class " + i + "/" + instance_info.length);
|
||||
if (instance_info[i].name_index != 0) {
|
||||
constants.constant_multiname[instance_info[i].name_index].name_index = deobfuscateName(stringUsages, namesMap, constants.constant_multiname[instance_info[i].name_index].name_index, true);
|
||||
constants.constant_multiname[instance_info[i].name_index].name_index = deobfuscateName(stringUsageTypes, stringUsages, namesMap, constants.constant_multiname[instance_info[i].name_index].name_index, true, renameType);
|
||||
}
|
||||
if (instance_info[i].super_index != 0) {
|
||||
constants.constant_multiname[instance_info[i].super_index].name_index = deobfuscateName(stringUsages, namesMap, constants.constant_multiname[instance_info[i].super_index].name_index, true);
|
||||
constants.constant_multiname[instance_info[i].super_index].name_index = deobfuscateName(stringUsageTypes, stringUsages, namesMap, constants.constant_multiname[instance_info[i].super_index].name_index, true, renameType);
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < constants.constant_multiname.length; i++) {
|
||||
constants.constant_multiname[i].name_index = deobfuscateName(stringUsages, namesMap, constants.constant_multiname[i].name_index, false);
|
||||
informListeners("deobfuscate", "name " + i + "/" + constants.constant_multiname.length);
|
||||
constants.constant_multiname[i].name_index = deobfuscateName(stringUsageTypes, stringUsages, namesMap, constants.constant_multiname[i].name_index, false, renameType);
|
||||
}
|
||||
for (int i = 1; i < constants.constant_namespace.length; i++) {
|
||||
constants.constant_namespace[i].name_index = deobfuscateNameSpace(stringUsages, namesMap, constants.constant_namespace[i].name_index);
|
||||
informListeners("deobfuscate", "namespace " + i + "/" + constants.constant_namespace.length);
|
||||
constants.constant_namespace[i].name_index = deobfuscateNameSpace(stringUsageTypes, stringUsages, namesMap, constants.constant_namespace[i].name_index, renameType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,7 +726,7 @@ public class ABC {
|
||||
"extends", "false", "finally", "for", "function", "get", "if", "implements", "import", "in", "instanceof",
|
||||
"interface", "internal", "is", "native", "new", "null", "override", "package", "private", "protected", "public",
|
||||
"return", "set", "super", "switch", "this", "throw", "true", "try", "typeof", "use", "var", /*"void",*/ "while",
|
||||
"with", "dynamic", "default", "final", "in"};
|
||||
"with", "dynamic", "default", "final", "in", "static"};
|
||||
public static final String validFirstCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
|
||||
public static final String validNextCharacters = validFirstCharacters + "0123456789";
|
||||
public static final String validNsCharacters = ".:$";
|
||||
@@ -663,26 +735,42 @@ public class ABC {
|
||||
private HashMap<String, String> deobfuscated = new HashMap<>();
|
||||
private Random rnd = new Random();
|
||||
private final int DEFAULT_FOO_SIZE = 10;
|
||||
private Map<String, Integer> usageTypesCount = new HashMap<>();
|
||||
|
||||
private String fooString(String orig, boolean firstUppercase, int rndSize) {
|
||||
private String fooString(String orig, boolean firstUppercase, int rndSize, String usageType, RenameType renameType) {
|
||||
boolean exists;
|
||||
String ret;
|
||||
int pos = 0;
|
||||
|
||||
if (usageType == null) {
|
||||
usageType = "name";
|
||||
}
|
||||
if (usageTypesCount.containsKey(usageType)) {
|
||||
pos = usageTypesCount.get(usageType);
|
||||
}
|
||||
|
||||
loopfoo:
|
||||
do {
|
||||
exists = false;
|
||||
int len = 3 + rnd.nextInt(rndSize - 3);
|
||||
ret = "";
|
||||
for (int i = 0; i < len; i++) {
|
||||
String c = "";
|
||||
if ((i % 2) == 0) {
|
||||
c = "" + fooCharacters.charAt(rnd.nextInt(fooCharacters.length()));
|
||||
} else {
|
||||
c = "" + fooJoinCharacters.charAt(rnd.nextInt(fooJoinCharacters.length()));
|
||||
if (renameType == RenameType.TYPENUMBER) {
|
||||
pos++;
|
||||
ret = usageType + "_" + pos;
|
||||
} else if (renameType == RenameType.RANDOMWORD) {
|
||||
int len = 3 + rnd.nextInt(rndSize - 3);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
String c = "";
|
||||
if ((i % 2) == 0) {
|
||||
c = "" + fooCharacters.charAt(rnd.nextInt(fooCharacters.length()));
|
||||
} else {
|
||||
c = "" + fooJoinCharacters.charAt(rnd.nextInt(fooJoinCharacters.length()));
|
||||
}
|
||||
if (i == 0 && firstUppercase) {
|
||||
c = c.toUpperCase();
|
||||
}
|
||||
ret += c;
|
||||
}
|
||||
if (i == 0 && firstUppercase) {
|
||||
c = c.toUpperCase();
|
||||
}
|
||||
ret += c;
|
||||
}
|
||||
for (int i = 1; i < constants.constant_string.length; i++) {
|
||||
if (constants.constant_string[i].equals(ret)) {
|
||||
@@ -702,6 +790,7 @@ public class ABC {
|
||||
continue;
|
||||
}
|
||||
} while (exists);
|
||||
usageTypesCount.put(usageType, pos);
|
||||
deobfuscated.put(orig, ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -738,7 +827,7 @@ public class ABC {
|
||||
return isValid;
|
||||
}
|
||||
|
||||
public int deobfuscateNameSpace(Set<Integer> stringUsages, HashMap<String, String> namesMap, int strIndex) {
|
||||
public int deobfuscateNameSpace(Map<Integer, String> stringUsageTypes, Set<Integer> stringUsages, HashMap<String, String> namesMap, int strIndex, RenameType renameType) {
|
||||
if (strIndex <= 0) {
|
||||
return strIndex;
|
||||
}
|
||||
@@ -761,7 +850,7 @@ public class ABC {
|
||||
ret += ".";
|
||||
}
|
||||
if (!isValidNSPart(parts[p])) {
|
||||
ret += fooString(constants.constant_string[strIndex], false, DEFAULT_FOO_SIZE);
|
||||
ret += fooString(constants.constant_string[strIndex], false, DEFAULT_FOO_SIZE, "package", renameType);
|
||||
} else {
|
||||
ret += parts[p];
|
||||
}
|
||||
@@ -779,7 +868,7 @@ public class ABC {
|
||||
return strIndex;
|
||||
}
|
||||
|
||||
public int deobfuscateName(Set<Integer> stringUsages, HashMap<String, String> namesMap, int strIndex, boolean firstUppercase) {
|
||||
public int deobfuscateName(Map<Integer, String> stringUsageTypes, Set<Integer> stringUsages, HashMap<String, String> namesMap, int strIndex, boolean firstUppercase, RenameType renameType) {
|
||||
if (strIndex <= 0) {
|
||||
return strIndex;
|
||||
}
|
||||
@@ -810,7 +899,7 @@ public class ABC {
|
||||
if (namesMap.containsKey(s)) {
|
||||
newname = namesMap.get(s);
|
||||
} else {
|
||||
newname = fooString(constants.constant_string[strIndex], firstUppercase, DEFAULT_FOO_SIZE);
|
||||
newname = fooString(constants.constant_string[strIndex], firstUppercase, DEFAULT_FOO_SIZE, stringUsageTypes.get(strIndex), renameType);
|
||||
}
|
||||
if (stringUsages.contains(strIndex)) { //this name is already referenced as String
|
||||
strIndex = constants.addString(s); //add new index
|
||||
|
||||
27
trunk/src/com/jpexs/decompiler/flash/abc/RenameType.java
Normal file
27
trunk/src/com/jpexs/decompiler/flash/abc/RenameType.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2013 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public enum RenameType {
|
||||
|
||||
TYPENUMBER,
|
||||
RANDOMWORD
|
||||
}
|
||||
@@ -213,10 +213,9 @@ public class DirectValueTreeItem extends TreeItem {
|
||||
if (!Objects.equals(this.constants, other.constants)) {
|
||||
return false;
|
||||
}
|
||||
if(other.pos!=this.pos){
|
||||
if (other.pos != this.pos) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -181,6 +181,12 @@ public class Main {
|
||||
if (event.equals("export")) {
|
||||
startWork((String) data);
|
||||
}
|
||||
if (event.equals("getVariables")) {
|
||||
startWork("Getting variables..." + (String) data);
|
||||
}
|
||||
if (event.equals("deobfuscate")) {
|
||||
startWork("Deobfuscating..." + (String) data);
|
||||
}
|
||||
}
|
||||
});
|
||||
return locswf;
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.FrameNode;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.TagNode;
|
||||
import com.jpexs.decompiler.flash.abc.RenameType;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.gui.ABCPanel;
|
||||
import com.jpexs.decompiler.flash.abc.gui.ClassesListTreeModel;
|
||||
@@ -1696,34 +1697,35 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
|
||||
|
||||
if (e.getActionCommand().equals("RENAMEIDENTIFIERS")) {
|
||||
if (confirmExperimental()) {
|
||||
final RenameType renameType = new RenameDialog().display();
|
||||
if (renameType != null) {
|
||||
Main.startWork("Renaming identifiers...");
|
||||
new SwingWorker() {
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
try {
|
||||
int cnt = 0;
|
||||
|
||||
Main.startWork("Renaming identifiers...");
|
||||
new SwingWorker() {
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
try {
|
||||
int cnt = 0;
|
||||
|
||||
if (abcPanel != null) {
|
||||
cnt = swf.deobfuscateAS3Identifiers();
|
||||
} else {
|
||||
cnt = swf.deobfuscateAS2Identifiers();
|
||||
if (abcPanel != null) {
|
||||
cnt = swf.deobfuscateAS3Identifiers(renameType);
|
||||
} else {
|
||||
cnt = swf.deobfuscateAS2Identifiers(renameType);
|
||||
}
|
||||
Main.stopWork();
|
||||
JOptionPane.showMessageDialog(null, "Identifiers renamed: " + cnt);
|
||||
if (abcPanel != null) {
|
||||
abcPanel.reload();
|
||||
}
|
||||
doFilter();
|
||||
reload(true);
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "message", ex);
|
||||
}
|
||||
Main.stopWork();
|
||||
JOptionPane.showMessageDialog(null, "Identifiers renamed: " + cnt);
|
||||
if (abcPanel != null) {
|
||||
abcPanel.reload();
|
||||
}
|
||||
doFilter();
|
||||
reload(true);
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "message", ex);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}.execute();
|
||||
|
||||
}.execute();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
111
trunk/src/com/jpexs/decompiler/flash/gui/RenameDialog.java
Normal file
111
trunk/src/com/jpexs/decompiler/flash/gui/RenameDialog.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2013 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.RenameType;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class RenameDialog extends JDialog implements ActionListener {
|
||||
|
||||
private JRadioButton typeNumberRadioButton = new JRadioButton("Type + Number (class_27, method_456,...)");
|
||||
private JRadioButton randomWordRadioButton = new JRadioButton("Random word (abada, kof, supo, kosuri,...)");
|
||||
private JButton okButton = new JButton("OK");
|
||||
private JButton cancelButton = new JButton("Cancel");
|
||||
private boolean confirmed = false;
|
||||
|
||||
public RenameType getRenameType() {
|
||||
if (!isConfirmed()) {
|
||||
return null;
|
||||
}
|
||||
if (typeNumberRadioButton.isSelected()) {
|
||||
return RenameType.TYPENUMBER;
|
||||
}
|
||||
return RenameType.RANDOMWORD;
|
||||
}
|
||||
|
||||
public RenameDialog() {
|
||||
setSize(300, 150);
|
||||
setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
group.add(typeNumberRadioButton);
|
||||
group.add(randomWordRadioButton);
|
||||
JPanel pan = new JPanel();
|
||||
pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS));
|
||||
pan.add(typeNumberRadioButton);
|
||||
pan.add(randomWordRadioButton);
|
||||
typeNumberRadioButton.setSelected(true);
|
||||
setLayout(new BorderLayout());
|
||||
add(pan, BorderLayout.CENTER);
|
||||
JPanel panButtons = new JPanel(new FlowLayout());
|
||||
panButtons.add(okButton);
|
||||
okButton.setActionCommand("OK");
|
||||
okButton.addActionListener(this);
|
||||
panButtons.add(cancelButton);
|
||||
cancelButton.setActionCommand("CANCEL");
|
||||
cancelButton.addActionListener(this);
|
||||
add(panButtons, BorderLayout.SOUTH);
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
View.centerScreen(this);
|
||||
View.setWindowIcon(this);
|
||||
setTitle("Rename Identifiers");
|
||||
getRootPane().setDefaultButton(okButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b) {
|
||||
if (b) {
|
||||
confirmed = false;
|
||||
}
|
||||
super.setVisible(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch (e.getActionCommand()) {
|
||||
case "OK":
|
||||
confirmed = true;
|
||||
setVisible(false);
|
||||
break;
|
||||
case "CANCEL":
|
||||
confirmed = false;
|
||||
setVisible(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConfirmed() {
|
||||
return confirmed;
|
||||
}
|
||||
|
||||
public RenameType display() {
|
||||
setVisible(true);
|
||||
return getRenameType();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user