mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-04 01:24:24 +00:00
AS3 deobfuscation - remove traps
This commit is contained in:
@@ -70,10 +70,18 @@ public class ABC {
|
||||
}
|
||||
}
|
||||
|
||||
public int removeTraps() {
|
||||
int rem=0;
|
||||
for(MethodBody body:bodies){
|
||||
rem+=body.removeTraps(constants);
|
||||
}
|
||||
return rem;
|
||||
}
|
||||
|
||||
public int removeDeadCode() {
|
||||
int rem=0;
|
||||
for(MethodBody body:bodies){
|
||||
rem+=body.removeDeadCode();
|
||||
rem+=body.removeDeadCode(constants);
|
||||
}
|
||||
return rem;
|
||||
}
|
||||
@@ -579,9 +587,9 @@ public class ABC {
|
||||
}
|
||||
public static final String[] reservedWords = {
|
||||
"as", "break", "case", "catch", "class", "const", "continue", "default", "delete", "do", "each", "else",
|
||||
"extends", "false", "finally", "for", "function", "if", "implements", "import", "in", "instanceof",
|
||||
"interface", "internal", "is", "native", "new", "null", "package", "private", "protected", "public",
|
||||
"return", "super", "switch", "this", "throw", "true", "try", "typeof", "use", "var", /*"void",*/ "while",
|
||||
"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"};
|
||||
public static final String validFirstCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
|
||||
public static final String validNextCharacters = validFirstCharacters + "0123456789";
|
||||
|
||||
@@ -36,10 +36,13 @@ import com.jpexs.asdec.abc.avm2.instructions.other.*;
|
||||
import com.jpexs.asdec.abc.avm2.instructions.stack.*;
|
||||
import com.jpexs.asdec.abc.avm2.instructions.types.*;
|
||||
import com.jpexs.asdec.abc.avm2.instructions.xml.*;
|
||||
import com.jpexs.asdec.abc.avm2.parser.ASM3Parser;
|
||||
import com.jpexs.asdec.abc.avm2.parser.ParseException;
|
||||
import com.jpexs.asdec.abc.avm2.treemodel.*;
|
||||
import com.jpexs.asdec.abc.avm2.treemodel.clauses.*;
|
||||
import com.jpexs.asdec.abc.avm2.treemodel.operations.AndTreeItem;
|
||||
import com.jpexs.asdec.abc.avm2.treemodel.operations.OrTreeItem;
|
||||
import com.jpexs.asdec.abc.gui.DialogMissingSymbolHandler;
|
||||
import com.jpexs.asdec.abc.types.ABCException;
|
||||
import com.jpexs.asdec.abc.types.MethodBody;
|
||||
import com.jpexs.asdec.abc.types.MethodInfo;
|
||||
@@ -729,8 +732,24 @@ public class AVM2Code {
|
||||
ret += "exceptiontarget " + e + ":";
|
||||
}
|
||||
}
|
||||
ret += Highlighting.hilighOffset("", ofs) + ins.toStringNoAddress(constants, new ArrayList<String>()) + "\n";
|
||||
if (ins.replaceWith != null) {
|
||||
for (AVM2Instruction ins2 : ins.replaceWith) {
|
||||
if (ins2.isIgnored()) {
|
||||
continue;
|
||||
}
|
||||
if (ins2.definition instanceof JumpIns) {
|
||||
ret += "jump ofs" + Helper.formatAddress(pos2adr(ins2.operands[0])) + "\n";
|
||||
} else {
|
||||
ret += Highlighting.hilighOffset("", ofs) + ins2.toStringNoAddress(constants, new ArrayList<String>()) + "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!ins.isIgnored()) {
|
||||
ret += Highlighting.hilighOffset("", ofs) + ins.toStringNoAddress(constants, new ArrayList<String>()) + "\n";
|
||||
}
|
||||
}
|
||||
ofs += ins.getBytes().length;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -767,6 +786,10 @@ public class AVM2Code {
|
||||
return posCache.get(pos).intValue();
|
||||
}
|
||||
|
||||
public void invalidateCache() {
|
||||
cacheActual = false;
|
||||
}
|
||||
|
||||
private static String listToString(List<TreeItem> stack, ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
|
||||
String ret = "";
|
||||
for (int d = 0; d < stack.size(); d++) {
|
||||
@@ -978,11 +1001,14 @@ public class AVM2Code {
|
||||
return pos2adr(fixIPAfterDebugLine(adr2pos(addr)));
|
||||
}
|
||||
|
||||
private ConvertOutput toSource(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, Stack<TreeItem> scopeStack, ABC abc, ConstantPool constants, MethodInfo method_info[], MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) throws ConvertException {
|
||||
private ConvertOutput toSource(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, Stack<TreeItem> scopeStack, ABC abc, ConstantPool constants, MethodInfo method_info[], MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, boolean visited[]) throws ConvertException {
|
||||
boolean debugMode = DEBUG_MODE;
|
||||
if (debugMode) {
|
||||
System.out.println("OPEN SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString());
|
||||
}
|
||||
if (visited == null) {
|
||||
visited = new boolean[code.size()];
|
||||
}
|
||||
//if(true) return "";
|
||||
toSourceCount++;
|
||||
if (toSourceLimit > 0) {
|
||||
@@ -1061,7 +1087,7 @@ public class AVM2Code {
|
||||
if (swins.operands.length >= 3) {
|
||||
if (swins.operands[0] == swins.getBytes().length) {
|
||||
if (adr2pos(pos2adr(f) + swins.operands[2]) < finStart) {
|
||||
finallyCommands = toSource(isStatic, classIndex, localRegs, stack, scopeStack, abc, constants, method_info, body, finStart, f - 1, localRegNames, fullyQualifiedNames).output;
|
||||
finallyCommands = toSource(isStatic, classIndex, localRegs, stack, scopeStack, abc, constants, method_info, body, finStart, f - 1, localRegNames, fullyQualifiedNames, visited).output;
|
||||
returnPos = f + 1;
|
||||
break;
|
||||
}
|
||||
@@ -1086,10 +1112,10 @@ public class AVM2Code {
|
||||
}
|
||||
Stack<TreeItem> substack = new Stack<TreeItem>();
|
||||
substack.add(new ExceptionTreeItem(catchedExceptions.get(e)));
|
||||
catchedCommands.add(toSource(isStatic, classIndex, localRegs, substack, new Stack<TreeItem>(), abc, constants, method_info, body, adr2pos(fixAddrAfterDebugLine(catchedExceptions.get(e).target)), eendpos, localRegNames, fullyQualifiedNames).output);
|
||||
catchedCommands.add(toSource(isStatic, classIndex, localRegs, substack, new Stack<TreeItem>(), abc, constants, method_info, body, adr2pos(fixAddrAfterDebugLine(catchedExceptions.get(e).target)), eendpos, localRegNames, fullyQualifiedNames, visited).output);
|
||||
}
|
||||
|
||||
List<TreeItem> tryCommands = toSource(isStatic, classIndex, localRegs, stack, scopeStack, abc, constants, method_info, body, ip, endpos - 1, localRegNames, fullyQualifiedNames).output;
|
||||
List<TreeItem> tryCommands = toSource(isStatic, classIndex, localRegs, stack, scopeStack, abc, constants, method_info, body, ip, endpos - 1, localRegNames, fullyQualifiedNames, visited).output;
|
||||
|
||||
|
||||
output.add(new TryTreeItem(tryCommands, catchedExceptions, catchedCommands, finallyCommands));
|
||||
@@ -1107,6 +1133,11 @@ public class AVM2Code {
|
||||
unknownJumps.remove(new Integer(ip));
|
||||
throw new UnknownJumpException(stack, ip, output);
|
||||
}
|
||||
if (visited[ip]) {
|
||||
Logger.getLogger(AVM2Code.class.getName()).warning("Code already visited");
|
||||
break;
|
||||
}
|
||||
visited[ip] = true;
|
||||
AVM2Instruction ins = code.get(ip);
|
||||
|
||||
if ((ip + 8 < code.size())) { //return in finally clause
|
||||
@@ -1152,13 +1183,12 @@ public class AVM2Code {
|
||||
}
|
||||
|
||||
if (ins.definition instanceof JumpIns) { //Ifs with multiple conditions
|
||||
int secondAddr = addr + ins.getBytes().length;
|
||||
int jumpAddr = secondAddr + ins.operands[0];
|
||||
int jumpPos = adr2pos(jumpAddr);
|
||||
if (ins.operands[0] == 0) {
|
||||
ip++;
|
||||
} else if (ins.operands[0] > 0) {
|
||||
int secondAddr = addr + ins.getBytes().length;
|
||||
int jumpAddr = secondAddr + ins.operands[0];
|
||||
int jumpPos = adr2pos(jumpAddr);//
|
||||
|
||||
if (finallyJumps.contains(jumpPos)) {
|
||||
if (code.get(ip + 1).definition instanceof LabelIns) {
|
||||
if (code.get(ip + 2).definition instanceof PopIns) {
|
||||
@@ -1254,7 +1284,7 @@ public class AVM2Code {
|
||||
throw new ConvertException("Unknown pattern: no setlocal before lookupswitch", switchPos);
|
||||
}
|
||||
loopList.add(new Loop(ip, switchPos + 1));
|
||||
Stack<TreeItem> substack = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, jumpPos, evalTo - 1, localRegNames, fullyQualifiedNames).stack;
|
||||
Stack<TreeItem> substack = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, jumpPos, evalTo - 1, localRegNames, fullyQualifiedNames, visited).stack;
|
||||
TreeItem switchedValue = substack.pop();
|
||||
//output.add("loop" + (switchPos + 1) + ":");
|
||||
int switchBreak = switchPos + 1;
|
||||
@@ -1289,7 +1319,7 @@ public class AVM2Code {
|
||||
|
||||
|
||||
if (evalTo > -1) {
|
||||
substack = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, curPos, evalTo - 1, localRegNames, fullyQualifiedNames).stack;
|
||||
substack = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, curPos, evalTo - 1, localRegNames, fullyQualifiedNames, visited).stack;
|
||||
casesList.add(substack.pop());
|
||||
}
|
||||
int substart = adr2pos(code.get(switchPos).operands[2 + casePos] + pos2adr(switchPos));
|
||||
@@ -1301,7 +1331,7 @@ public class AVM2Code {
|
||||
if (evalTo == -1) {
|
||||
subend--;
|
||||
}
|
||||
List commands = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, substart, subend, localRegNames, fullyQualifiedNames).output;
|
||||
List commands = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, substart, subend, localRegNames, fullyQualifiedNames, visited).output;
|
||||
if ((evalTo == -1) && (casePos + 1 < code.get(switchPos).operands.length - 2)) {
|
||||
if (commands.size() == 1) {
|
||||
commands.remove(0);
|
||||
@@ -1345,7 +1375,7 @@ public class AVM2Code {
|
||||
loopList.add(currentLoop);
|
||||
|
||||
|
||||
ConvertOutput co = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, jumpPos, adr2pos(afterBackJumpAddr) - 2, localRegNames, fullyQualifiedNames);
|
||||
ConvertOutput co = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, jumpPos, adr2pos(afterBackJumpAddr) - 2, localRegNames, fullyQualifiedNames, visited);
|
||||
Stack<TreeItem> substack = co.stack;
|
||||
backJumpIns.definition.translate(isStatic, classIndex, localRegs, substack, scopeStack, constants, backJumpIns, method_info, output, body, abc, localRegNames, fullyQualifiedNames);
|
||||
|
||||
@@ -1354,7 +1384,7 @@ public class AVM2Code {
|
||||
boolean isFor = false;
|
||||
List<TreeItem> finalExpression = new ArrayList<TreeItem>();
|
||||
try {
|
||||
subins = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, adr2pos(secondAddr) + 1/*label*/, jumpPos - 1, localRegNames, fullyQualifiedNames).output;
|
||||
subins = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, adr2pos(secondAddr) + 1/*label*/, jumpPos - 1, localRegNames, fullyQualifiedNames, visited).output;
|
||||
} catch (UnknownJumpException uje) {
|
||||
if ((uje.ip >= start) && (uje.ip <= end)) {
|
||||
currentLoop.loopContinue = uje.ip;
|
||||
@@ -1379,7 +1409,7 @@ public class AVM2Code {
|
||||
}
|
||||
}
|
||||
}
|
||||
finalExpression = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, uje.ip, jumpPos - 1, localRegNames, fullyQualifiedNames).output;
|
||||
finalExpression = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, uje.ip, jumpPos - 1, localRegNames, fullyQualifiedNames, visited).output;
|
||||
isFor = true;
|
||||
} else {
|
||||
throw new ConvertException("Unknown pattern: jump to nowhere", ip);
|
||||
@@ -1533,7 +1563,7 @@ public class AVM2Code {
|
||||
if (((GetLocalTypeIns) code.get(t).definition).getRegisterId(code.get(t)) == reg) {
|
||||
if (code.get(t + 1).definition instanceof KillIns) {
|
||||
if (code.get(t + 1).operands[0] == reg) {
|
||||
ConvertOutput assignment = toSource(isStatic, classIndex, localRegs, stack, scopeStack, abc, constants, method_info, body, ip + 2, t - 1, localRegNames, fullyQualifiedNames);
|
||||
ConvertOutput assignment = toSource(isStatic, classIndex, localRegs, stack, scopeStack, abc, constants, method_info, body, ip + 2, t - 1, localRegNames, fullyQualifiedNames, visited);
|
||||
stack.push(assignment.output.remove(assignment.output.size() - 1));
|
||||
ip = t + 2;
|
||||
continue iploop;
|
||||
@@ -1568,9 +1598,9 @@ public class AVM2Code {
|
||||
addr = addr + ins.getBytes().length + insAfter.getBytes().length + insAfter.operands[0];
|
||||
nextPos = adr2pos(addr) - 1;
|
||||
if (isAnd) {
|
||||
stack.add(new AndTreeItem(insAfter, stack.pop(), toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, ip + 3, nextPos, localRegNames, fullyQualifiedNames).stack.pop()));
|
||||
stack.add(new AndTreeItem(insAfter, stack.pop(), toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, ip + 3, nextPos, localRegNames, fullyQualifiedNames, visited).stack.pop()));
|
||||
} else {
|
||||
stack.add(new OrTreeItem(insAfter, stack.pop(), toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, ip + 3, nextPos, localRegNames, fullyQualifiedNames).stack.pop()));
|
||||
stack.add(new OrTreeItem(insAfter, stack.pop(), toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, ip + 3, nextPos, localRegNames, fullyQualifiedNames, visited).stack.pop()));
|
||||
}
|
||||
ins = code.get(nextPos + 1);
|
||||
ip = nextPos + 1;
|
||||
@@ -1627,13 +1657,13 @@ public class AVM2Code {
|
||||
}
|
||||
}
|
||||
}
|
||||
ConvertOutput onTrue = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, ip + 1, targetIns - 1 - ((hasElse || hasReturn) ? 1 : 0), localRegNames, fullyQualifiedNames);
|
||||
ConvertOutput onTrue = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, ip + 1, targetIns - 1 - ((hasElse || hasReturn) ? 1 : 0), localRegNames, fullyQualifiedNames, visited);
|
||||
ip = targetIns;
|
||||
ConvertOutput onFalse = new ConvertOutput(new Stack<TreeItem>(), new ArrayList<TreeItem>());
|
||||
if (hasElse) {
|
||||
int finalAddr = targetAddr + code.get(targetIns - 1).operands[0];
|
||||
int finalIns = adr2pos(finalAddr);
|
||||
onFalse = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, targetIns, finalIns - 1, localRegNames, fullyQualifiedNames);
|
||||
onFalse = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, targetIns, finalIns - 1, localRegNames, fullyQualifiedNames, visited);
|
||||
ip = finalIns;
|
||||
}
|
||||
if ((onTrue.stack.size() > 0) && (onFalse != null) && (onFalse.stack.size() > 0)) {
|
||||
@@ -1730,7 +1760,7 @@ public class AVM2Code {
|
||||
ignoredIns = new ArrayList<Integer>();
|
||||
HashMap<Integer, TreeItem> localRegs = new HashMap<Integer, TreeItem>();
|
||||
try {
|
||||
return toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), new Stack<TreeItem>(), abc, constants, method_info, body, 0, code.size() - 1, localRegNames, fullyQualifiedNames).output;
|
||||
return toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), new Stack<TreeItem>(), abc, constants, method_info, body, 0, code.size() - 1, localRegNames, fullyQualifiedNames, null).output;
|
||||
} catch (ConvertException ex) {
|
||||
return new ArrayList<TreeItem>();
|
||||
}
|
||||
@@ -1819,7 +1849,7 @@ public class AVM2Code {
|
||||
}
|
||||
|
||||
try {
|
||||
list = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, 0, code.size() - 1, localRegNames, fullyQualifiedNames).output;
|
||||
list = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), scopeStack, abc, constants, method_info, body, 0, code.size() - 1, localRegNames, fullyQualifiedNames, null).output;
|
||||
if (initTraits != null) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
TreeItem ti = list.get(i);
|
||||
@@ -2101,7 +2131,7 @@ public class AVM2Code {
|
||||
}
|
||||
|
||||
code.remove(pos);
|
||||
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
public void insertInstruction(int pos, AVM2Instruction instruction) {
|
||||
@@ -2145,67 +2175,16 @@ public class AVM2Code {
|
||||
code.add(pos, instruction);
|
||||
}
|
||||
|
||||
private void removeFreeBlocks(ConstantPool constants, MethodBody body) throws ConvertException {
|
||||
List<Long> offsets = new ArrayList<Long>();
|
||||
for (AVM2Instruction ins : code) {
|
||||
offsets.addAll(ins.getOffsets());
|
||||
}
|
||||
for (ABCException ex : body.exceptions) {
|
||||
offsets.add((long) ex.start);
|
||||
offsets.add((long) ex.end);
|
||||
offsets.add((long) ex.target);
|
||||
}
|
||||
|
||||
int clearedCount = 0;
|
||||
loopip:
|
||||
for (int ip = 0; ip < code.size(); ip++) {
|
||||
AVM2Instruction ins = code.get(ip);
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
int secondAddr = pos2adr(ip + 1);
|
||||
int jumpAddr = secondAddr + ins.operands[0];
|
||||
int jumpPos = adr2pos(jumpAddr);
|
||||
if (jumpPos <= ip) {
|
||||
continue;
|
||||
}
|
||||
if (jumpPos > code.size()) {
|
||||
continue;
|
||||
}
|
||||
for (int k = ip + 1; k < jumpPos; k++) {
|
||||
if (offsets.contains((long) pos2adr(k))) {
|
||||
continue loopip;
|
||||
}
|
||||
}
|
||||
for (int k = ip; k < jumpPos; k++) {
|
||||
removeInstruction(ip, body);
|
||||
clearedCount++;
|
||||
}
|
||||
offsets.clear();
|
||||
for (AVM2Instruction ins2 : code) {
|
||||
offsets.addAll(ins2.getOffsets());
|
||||
}
|
||||
for (ABCException ex : body.exceptions) {
|
||||
offsets.add((long) ex.start);
|
||||
offsets.add((long) ex.end);
|
||||
offsets.add((long) ex.target);
|
||||
}
|
||||
ip--;
|
||||
//ip=jumpPos;
|
||||
}
|
||||
}
|
||||
if (clearedCount > 0) {
|
||||
//System.out.println("Cleared " + clearedCount + " lines of code TO:");
|
||||
//System.out.println(toASMSource(constants));
|
||||
//System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearSecureSWF(ConstantPool constants, MethodBody body) throws ConvertException {
|
||||
|
||||
public int removePushTrueFalseTraps(ConstantPool constants, MethodBody body) throws ConvertException {
|
||||
removeDeadCode(constants, body);
|
||||
boolean isSecure = true;
|
||||
if (code.size() > 4) {
|
||||
AVM2Instruction first = code.get(0);
|
||||
AVM2Instruction second = code.get(1);
|
||||
boolean firstValue = false;
|
||||
boolean secondValue = false;
|
||||
boolean isSecure = true;
|
||||
if (first.definition instanceof PushFalseIns) {
|
||||
firstValue = false;
|
||||
} else if (first.definition instanceof PushTrueIns) {
|
||||
@@ -2222,16 +2201,30 @@ public class AVM2Code {
|
||||
isSecure = false;
|
||||
}
|
||||
if (isSecure) {
|
||||
AVM2Instruction third = code.get(2);
|
||||
int pos = 2;
|
||||
AVM2Instruction third = code.get(pos);
|
||||
if (third.definition instanceof SwapIns) {
|
||||
pos++;
|
||||
boolean dup = firstValue;
|
||||
firstValue = secondValue;
|
||||
secondValue = dup;
|
||||
third.ignored = true;
|
||||
}
|
||||
while (third.definition instanceof JumpIns) {
|
||||
pos = adr2pos(pos2adr(pos) + third.getBytes().length + third.operands[0]);
|
||||
third = code.get(pos);
|
||||
}
|
||||
AVM2Instruction firstSet = code.get(pos);
|
||||
AVM2Instruction secondSet = code.get(pos + 1);
|
||||
while (firstSet.definition instanceof JumpIns) {
|
||||
pos = adr2pos(pos2adr(pos) + firstSet.getBytes().length + firstSet.operands[0]);
|
||||
firstSet = code.get(pos);
|
||||
}
|
||||
pos++;
|
||||
AVM2Instruction secondSet = code.get(pos);
|
||||
while (secondSet.definition instanceof JumpIns) {
|
||||
pos = adr2pos(pos2adr(pos) + secondSet.getBytes().length + secondSet.operands[0]);
|
||||
secondSet = code.get(pos);
|
||||
}
|
||||
int trueIndex = -1;
|
||||
int falseIndex = -1;
|
||||
if (firstSet.definition instanceof SetLocalTypeIns) {
|
||||
@@ -2247,24 +2240,19 @@ public class AVM2Code {
|
||||
if (isSecure) {
|
||||
if (secondSet.definition instanceof SetLocalTypeIns) {
|
||||
if (firstValue == true) {
|
||||
trueIndex = ((SetLocalTypeIns) secondSet.definition).getRegisterId(firstSet);
|
||||
trueIndex = ((SetLocalTypeIns) secondSet.definition).getRegisterId(secondSet);
|
||||
}
|
||||
if (firstValue == false) {
|
||||
falseIndex = ((SetLocalTypeIns) secondSet.definition).getRegisterId(firstSet);
|
||||
falseIndex = ((SetLocalTypeIns) secondSet.definition).getRegisterId(secondSet);
|
||||
}
|
||||
|
||||
//Yes, secure
|
||||
pos += 2;
|
||||
for (int i = 0; i < pos; i++) {
|
||||
code.get(i).ignored = true;
|
||||
//removeInstruction(0, body);
|
||||
}
|
||||
System.out.println("trueIndex:" + trueIndex);
|
||||
System.out.println("falseIndex:" + falseIndex);
|
||||
secondSet.ignored = true;
|
||||
firstSet.ignored = true;
|
||||
first.ignored = true;
|
||||
second.ignored = true;
|
||||
boolean found;
|
||||
do {
|
||||
found = false;
|
||||
for (int ip = pos; ip < code.size(); ip++) {
|
||||
for (int ip = 0; ip < code.size(); ip++) {
|
||||
if (code.get(ip).ignored) {
|
||||
continue;
|
||||
}
|
||||
@@ -2275,10 +2263,10 @@ public class AVM2Code {
|
||||
Stack<Boolean> myStack = new Stack<Boolean>();
|
||||
do {
|
||||
AVM2Instruction ins = code.get(ip);
|
||||
if (ins.ignored) {
|
||||
ip++;
|
||||
continue;
|
||||
} else if (ins.definition instanceof GetLocalTypeIns) {
|
||||
/*if (ins.ignored) {
|
||||
ip++;
|
||||
continue;
|
||||
} else*/ if (ins.definition instanceof GetLocalTypeIns) {
|
||||
regIndex = ((GetLocalTypeIns) ins.definition).getRegisterId(ins);
|
||||
if (regIndex == trueIndex) {
|
||||
myStack.push(true);
|
||||
@@ -2319,21 +2307,19 @@ public class AVM2Code {
|
||||
} else if (ins.definition instanceof JumpIns) {
|
||||
ip = adr2pos(pos2adr(ip + 1) + code.get(ip).operands[0]);
|
||||
} else {
|
||||
ip++;
|
||||
}
|
||||
|
||||
} while (myStack.size() > 0);
|
||||
|
||||
/*for(int rem=code.size();rem>=0;rem--){
|
||||
if(code.get(rem).ignored){
|
||||
code.remove(rem);
|
||||
}
|
||||
} */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} while (found);
|
||||
removeIgnored(body);
|
||||
removeDeadCode(constants, body);
|
||||
} else {
|
||||
//isSecure = false;
|
||||
}
|
||||
@@ -2342,10 +2328,13 @@ public class AVM2Code {
|
||||
}
|
||||
}
|
||||
}
|
||||
int ret=isSecure ? 1 : 0;
|
||||
ret+=visitCodeTrap(body, new int[code.size()]);
|
||||
removeIgnored(body);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void clearCode(ConstantPool constants, MethodBody body) throws ConvertException {
|
||||
|
||||
public int removePushByteTraps(ConstantPool constants, MethodBody body) throws ConvertException {
|
||||
if (code.size() > 3) {
|
||||
if (code.get(0).definition instanceof PushByteIns) {
|
||||
if (code.get(1).definition instanceof PushByteIns) {
|
||||
@@ -2356,16 +2345,25 @@ public class AVM2Code {
|
||||
for (int i = 0; i < targetPos; i++) {
|
||||
removeInstruction(0, body);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
removeFreeBlocks(constants, body);
|
||||
//clearSecureSWF(constants, body);
|
||||
|
||||
|
||||
public int removeTraps(ConstantPool constants, MethodBody body) {
|
||||
int ret = 0;
|
||||
try {
|
||||
ret += removePushByteTraps(constants, body);
|
||||
ret += removePushTrueFalseTraps(constants, body);
|
||||
} catch (ConvertException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
restoreControlFlow(constants, body);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void handleRegister(CodeStats stats, int reg) {
|
||||
@@ -2464,19 +2462,30 @@ public class AVM2Code {
|
||||
return stats;
|
||||
}
|
||||
|
||||
private void visitCode(int ip, boolean visited[]) {
|
||||
while ((ip < visited.length) && (!visited[ip])) {
|
||||
visited[ip] = true;
|
||||
private void visitCode(int ip, int visited[]) {
|
||||
while (ip < visited.length) {
|
||||
visited[ip]++;
|
||||
if (visited[ip] > 1) {
|
||||
break;
|
||||
}
|
||||
AVM2Instruction ins = code.get(ip);
|
||||
if (ins.definition instanceof ThrowIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof ReturnValueIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof ReturnVoidIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof LookupSwitchIns) {
|
||||
try {
|
||||
for(int i=2;i<ins.operands.length;i++){
|
||||
try {
|
||||
for (int i = 2; i < ins.operands.length; i++) {
|
||||
visitCode(adr2pos(pos2adr(ip) + ins.operands[i]), visited);
|
||||
}
|
||||
ip = adr2pos(pos2adr(ip) + ins.operands[0]);
|
||||
continue;
|
||||
} catch (ConvertException ex) {
|
||||
|
||||
}
|
||||
}
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
@@ -2497,10 +2506,9 @@ public class AVM2Code {
|
||||
};
|
||||
}
|
||||
|
||||
public int removeDeadCode(MethodBody body) {
|
||||
boolean visited[] = new boolean[code.size()];
|
||||
private void visitCode(MethodBody body, int visited[]) {
|
||||
for (int i = 0; i < visited.length; i++) {
|
||||
visited[i] = false;
|
||||
visited[i] = 0;
|
||||
}
|
||||
visitCode(0, visited);
|
||||
for (ABCException e : body.exceptions) {
|
||||
@@ -2511,9 +2519,218 @@ public class AVM2Code {
|
||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int visitCodeTrap(int ip, int visited[],AVM2Instruction prev) {
|
||||
int ret=0;
|
||||
while (ip < visited.length) {
|
||||
visited[ip]++;
|
||||
if (visited[ip] > 1) {
|
||||
break;
|
||||
}
|
||||
AVM2Instruction ins = code.get(ip);
|
||||
if (ins.definition instanceof ThrowIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof ReturnValueIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof ReturnVoidIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof LookupSwitchIns) {
|
||||
try {
|
||||
for (int i = 2; i < ins.operands.length; i++) {
|
||||
ret+=visitCodeTrap(adr2pos(pos2adr(ip) + ins.operands[i]), visited,prev);
|
||||
}
|
||||
ip = adr2pos(pos2adr(ip) + ins.operands[0]);
|
||||
prev=ins;
|
||||
continue;
|
||||
} catch (ConvertException ex) {
|
||||
}
|
||||
}
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
try {
|
||||
ip = adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
|
||||
prev=ins;
|
||||
continue;
|
||||
} catch (ConvertException ex) {
|
||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
} else if (ins.definition instanceof IfTypeIns) {
|
||||
if ((prev != null) && ins.definition instanceof IfTrueIns) {
|
||||
if (prev.definition instanceof PushTrueIns) {
|
||||
prev.ignored = true;
|
||||
ins.definition = new JumpIns();
|
||||
ip--;
|
||||
ret++;
|
||||
continue;
|
||||
} else if (prev.definition instanceof PushFalseIns) {
|
||||
prev.ignored = true;
|
||||
ins.ignored = true;
|
||||
ret++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((prev != null) && ins.definition instanceof IfFalseIns) {
|
||||
if (prev.definition instanceof PushFalseIns) {
|
||||
prev.ignored = true;
|
||||
ins.definition = new JumpIns();
|
||||
ip--;
|
||||
ret++;
|
||||
continue;
|
||||
} else if (prev.definition instanceof PushTrueIns) {
|
||||
prev.ignored = true;
|
||||
ins.ignored = true;
|
||||
ret++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
ret+=visitCodeTrap(adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]), visited,prev);
|
||||
} catch (ConvertException ex) {
|
||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
ip++;
|
||||
prev=ins;
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int visitCodeTrap(MethodBody body, int visited[]) {
|
||||
int ret=0;
|
||||
for (int i = 0; i < visited.length; i++) {
|
||||
visited[i] = 0;
|
||||
}
|
||||
ret+=visitCodeTrap(0, visited,null);
|
||||
for (ABCException e : body.exceptions) {
|
||||
try {
|
||||
ret+=visitCodeTrap(adr2pos(e.start), visited,null);
|
||||
ret+=visitCodeTrap(adr2pos(e.target), visited,null);
|
||||
} catch (ConvertException ex) {
|
||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void restoreControlFlow(int ip, int visited[], int visited2[], HashMap<Integer, List<AVM2Instruction>> appended) throws ConvertException {
|
||||
List<AVM2Instruction> buf = new ArrayList<AVM2Instruction>();
|
||||
boolean cont = false;
|
||||
int continueip = 0;
|
||||
AVM2Instruction prev = null;
|
||||
for (; ip < visited.length; ip++) {
|
||||
AVM2Instruction ins = code.get(ip);
|
||||
if (visited2[ip] > 0) {
|
||||
break;
|
||||
}
|
||||
visited2[ip]++;
|
||||
if (visited[ip] > 1) {
|
||||
if (cont) {
|
||||
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{ip}, new byte[0]));
|
||||
}
|
||||
cont = false;
|
||||
}
|
||||
if (ins.definition instanceof LookupSwitchIns) {
|
||||
|
||||
if (cont) {
|
||||
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{ip}, new byte[0]));
|
||||
}
|
||||
cont = false;
|
||||
restoreControlFlow(adr2pos(pos2adr(ip) + ins.operands[0]), visited, visited2, appended);
|
||||
for (int i = 2; i < ins.operands.length; i++) {
|
||||
restoreControlFlow(adr2pos(pos2adr(ip) + ins.operands[i]), visited, visited2, appended);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
int newip = adr2pos(pos2adr(ip + 1) + ins.operands[0]);
|
||||
if ((newip < visited.length) && (visited[newip] == 1)) {
|
||||
if (!cont) {
|
||||
continueip = ip;
|
||||
buf = new ArrayList<AVM2Instruction>();
|
||||
appended.put(continueip, buf);
|
||||
}
|
||||
cont = true;
|
||||
} else {
|
||||
if (cont) {
|
||||
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{newip}, new byte[0]));
|
||||
}
|
||||
cont = false;
|
||||
}
|
||||
ip = newip - 1;
|
||||
} else if (ins.definition instanceof IfTypeIns) {
|
||||
int newip = adr2pos(pos2adr(ip + 1) + ins.operands[0]);
|
||||
if (cont) {
|
||||
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{ip}, new byte[0]));
|
||||
}
|
||||
cont = false;
|
||||
restoreControlFlow(newip, visited, visited2, appended);
|
||||
} else if ((ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ThrowIns)) {
|
||||
if (cont) {
|
||||
buf.add(ins);
|
||||
}
|
||||
break;
|
||||
} else if (cont) {
|
||||
buf.add(ins);
|
||||
}
|
||||
prev = ins;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void restoreControlFlow(ConstantPool constants, MethodBody body) {
|
||||
try {
|
||||
int visited[] = new int[code.size()];
|
||||
int visited2[] = new int[code.size()];
|
||||
visitCode(body, visited);
|
||||
HashMap<Integer, List<AVM2Instruction>> appended = new HashMap<Integer, List<AVM2Instruction>>();
|
||||
restoreControlFlow(0, visited, visited2, appended);
|
||||
for (ABCException e : body.exceptions) {
|
||||
try {
|
||||
restoreControlFlow(adr2pos(e.start), visited, visited2, appended);
|
||||
restoreControlFlow(adr2pos(e.target), visited, visited2, appended);
|
||||
} catch (ConvertException ex) {
|
||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
for (int ip : appended.keySet()) {
|
||||
code.get(ip).replaceWith = appended.get(ip);
|
||||
}
|
||||
} catch (ConvertException cex) {
|
||||
}
|
||||
try {
|
||||
String src = Highlighting.stripHilights(toASMSource(constants, body));
|
||||
FileOutputStream fos = new FileOutputStream("src.txt");
|
||||
fos.write(src.getBytes());
|
||||
fos.close();
|
||||
AVM2Code acode = ASM3Parser.parse(new ByteArrayInputStream(src.getBytes()), constants, null, body);
|
||||
this.code = acode.code;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (ParseException ex) {
|
||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
invalidateCache();
|
||||
removeDeadCode(constants, body);
|
||||
}
|
||||
|
||||
private void removeIgnored(MethodBody body) {
|
||||
for (int rem = code.size() - 1; rem >= 0; rem--) {
|
||||
if (code.get(rem).ignored) {
|
||||
removeInstruction(rem, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int removeDeadCode(ConstantPool constants, MethodBody body) {
|
||||
int visited[] = new int[code.size()];
|
||||
|
||||
visitCode(body, visited);
|
||||
int cnt = 0;
|
||||
for (int i = visited.length - 1; i >= 0; i--) {
|
||||
if (!visited[i]) {
|
||||
if (visited[i] == 0) {
|
||||
removeInstruction(i, body);
|
||||
cnt++;
|
||||
}
|
||||
@@ -2526,7 +2743,7 @@ public class AVM2Code {
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +207,12 @@ public class AVM2Instruction {
|
||||
return " ;" + comment;
|
||||
}
|
||||
|
||||
public boolean isIgnored() {
|
||||
return ignored;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String toString(ConstantPool constants, List<String> fullyQualifiedNames) {
|
||||
String s = Helper.formatAddress(offset) + " " + Helper.padSpaceRight(Helper.byteArrToString(getBytes()), 30) + definition.instructionName;
|
||||
s += getParams(constants, fullyQualifiedNames) + getComment();
|
||||
@@ -218,4 +224,6 @@ public class AVM2Instruction {
|
||||
s += getParams(constants, fullyQualifiedNames) + getComment();
|
||||
return s;
|
||||
}
|
||||
|
||||
public List<AVM2Instruction> replaceWith;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener {
|
||||
oneList.add(list.get(index));
|
||||
this.abc = list.get(index).abc;
|
||||
classTree.setDoABCTags(oneList);
|
||||
}
|
||||
}
|
||||
updateConstList();
|
||||
}
|
||||
|
||||
@@ -319,7 +319,9 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener {
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
switchAbc(listIndex - 1);
|
||||
switchAbc(listIndex);
|
||||
decompiledTextArea.clearScriptCache();
|
||||
decompiledTextArea.reloadClass();
|
||||
}
|
||||
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
|
||||
@@ -74,7 +74,6 @@ public class ASMSourceEditorPane extends LineMarkedEditorPane implements CaretLi
|
||||
|
||||
public void graph() {
|
||||
Graph gr = new Graph(abc.bodies[bodyIndex].code);
|
||||
//(new GraphTreeFrame(gr)).setVisible(true);
|
||||
(new GraphFrame(gr, "")).setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -245,8 +245,12 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
}
|
||||
private List<DoABCTag> abcList;
|
||||
|
||||
public void setScript(ScriptInfo script, ABC abc, List<DoABCTag> abcList) {
|
||||
setText("//Please wait...");
|
||||
public void clearScriptCache()
|
||||
{
|
||||
bufferedClasses.clear();
|
||||
}
|
||||
|
||||
public void setScript(ScriptInfo script, ABC abc, List<DoABCTag> abcList) {
|
||||
if (script == null) {
|
||||
highlights = new ArrayList<Highlighting>();
|
||||
traitHighlights = new ArrayList<Highlighting>();
|
||||
@@ -254,6 +258,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
this.script = null;
|
||||
return;
|
||||
}
|
||||
setText("//Please wait...");
|
||||
|
||||
String hilightedCode;
|
||||
if (!bufferedClasses.containsKey(script)) {
|
||||
@@ -279,11 +284,13 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
}
|
||||
|
||||
public void reloadClass() {
|
||||
int ci=classIndex;
|
||||
if (bufferedClasses.containsKey(script)) {
|
||||
bufferedClasses.remove(script);
|
||||
}
|
||||
setScript(script, abc, abcList);
|
||||
setNoTrait();
|
||||
setClassIndex(classIndex);
|
||||
}
|
||||
|
||||
public int getClassIndex() {
|
||||
|
||||
@@ -127,9 +127,7 @@ public class DetailPanel extends JPanel implements ActionListener {
|
||||
if (cardMap.get(selectedCard) instanceof TraitDetail) {
|
||||
if (((TraitDetail) cardMap.get(selectedCard)).save()) {
|
||||
int lasttrait = abcPanel.decompiledTextArea.lastTraitIndex;
|
||||
int lastclass = abcPanel.decompiledTextArea.getClassIndex();
|
||||
abcPanel.decompiledTextArea.reloadClass();
|
||||
abcPanel.decompiledTextArea.setClassIndex(lastclass);
|
||||
abcPanel.decompiledTextArea.reloadClass();
|
||||
abcPanel.decompiledTextArea.gotoTrait(lasttrait);
|
||||
JOptionPane.showMessageDialog(this, "Trait Successfully saved");
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ import com.jpexs.asdec.abc.avm2.flowgraph.GraphPart;
|
||||
import com.jpexs.asdec.gui.View;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
@@ -42,33 +45,40 @@ public class GraphFrame extends JFrame {
|
||||
|
||||
public GraphPanel(Graph graph) {
|
||||
this.graph = graph;
|
||||
setPreferredSize(new Dimension((BLOCK_WIDTH + SPACE_HORIZONTAL) * getPartWidth(graph.head, new ArrayList<GraphPart>()), (BLOCK_HEIGHT + SPACE_VERTICAL) * getPartHeight(graph.head, new ArrayList<GraphPart>())));
|
||||
setPreferredSize(new Dimension((BLOCK_WIDTH + SPACE_HORIZONTAL) * getPartWidth(graph.head, new HashSet<GraphPart>()), (BLOCK_HEIGHT + SPACE_VERTICAL) * getPartHeight(graph.head, new ArrayList<GraphPart>())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
g.setColor(Color.black);
|
||||
paintPart(g, graph.head, 0, getPartWidth(graph.head, new ArrayList<GraphPart>()) * (BLOCK_WIDTH + SPACE_HORIZONTAL) / 2, new ArrayList<GraphPart>());
|
||||
paintPart(g, graph.head, 0, getPartWidth(graph.head, new HashSet<GraphPart>()) * (BLOCK_WIDTH + SPACE_HORIZONTAL) / 2, new HashMap<GraphPart,Point>());
|
||||
}
|
||||
|
||||
private void paintPart(Graphics g, GraphPart part, int y, int x, List<GraphPart> used) {
|
||||
List<GraphPart> l = new ArrayList<GraphPart>();
|
||||
l.addAll(used);
|
||||
int totalWidthParts = getPartWidth(part, l);
|
||||
private void paintPart(Graphics g, GraphPart part, int y, int x, HashMap<GraphPart,Point> used) {
|
||||
HashMap<GraphPart,Point> l = new HashMap<GraphPart,Point>();
|
||||
l.putAll(used);
|
||||
HashSet<GraphPart> hs=new HashSet<GraphPart>();
|
||||
hs.addAll(l.keySet());
|
||||
int totalWidthParts = getPartWidth(part, hs);
|
||||
int totalWidth = totalWidthParts * (BLOCK_WIDTH + SPACE_HORIZONTAL);
|
||||
g.drawRect(x - BLOCK_WIDTH / 2 - SPACE_HORIZONTAL / 2, y, BLOCK_WIDTH, BLOCK_HEIGHT);
|
||||
g.drawString(part.toString(), x - BLOCK_WIDTH / 2, y + BLOCK_HEIGHT);
|
||||
if (used.contains(part)) {
|
||||
|
||||
if (used.containsKey(part)) {
|
||||
g.setColor(Color.black);
|
||||
Point p=used.get(part);
|
||||
g.drawLine(x, y, p.x, p.y);
|
||||
return;
|
||||
}
|
||||
used.add(part);
|
||||
g.drawRect(x - BLOCK_WIDTH / 2 - SPACE_HORIZONTAL / 2, y, BLOCK_WIDTH, BLOCK_HEIGHT);
|
||||
g.drawString(part.toString(), x - BLOCK_WIDTH / 2, y + BLOCK_HEIGHT);
|
||||
|
||||
used.put(part,new Point(x,y));
|
||||
if (part.nextParts.size() > 0) {
|
||||
int cx = x - totalWidth / 2;
|
||||
for (int p = 0; p < part.nextParts.size(); p++) {
|
||||
l = new ArrayList<GraphPart>();
|
||||
l.addAll(used);
|
||||
int cellWidth = getPartWidth(part.nextParts.get(p), l) * (BLOCK_WIDTH + SPACE_HORIZONTAL);
|
||||
HashSet<GraphPart> k = new HashSet<GraphPart>();
|
||||
k.addAll(used.keySet());
|
||||
int cellWidth = getPartWidth(part.nextParts.get(p), k) * (BLOCK_WIDTH + SPACE_HORIZONTAL);
|
||||
g.setColor(Color.black);
|
||||
g.drawLine(x, y + BLOCK_HEIGHT, cx + cellWidth / 2, y + BLOCK_HEIGHT + SPACE_VERTICAL);
|
||||
paintPart(g, part.nextParts.get(p), y + BLOCK_HEIGHT + SPACE_VERTICAL, cx + cellWidth / 2, used);
|
||||
@@ -94,7 +104,7 @@ public class GraphFrame extends JFrame {
|
||||
return 1 + maxH;
|
||||
}
|
||||
|
||||
private int getPartWidth(GraphPart part, List<GraphPart> used) {
|
||||
private int getPartWidth(GraphPart part, HashSet<GraphPart> used) {
|
||||
|
||||
if (used.contains(part)) {
|
||||
return 1;
|
||||
|
||||
@@ -85,7 +85,7 @@ public class MethodCodePanel extends JPanel implements ActionListener {
|
||||
execButton.setActionCommand("EXEC");
|
||||
execButton.addActionListener(this);
|
||||
|
||||
//buttonsPan.add(graphButton);
|
||||
buttonsPanel.add(graphButton);
|
||||
// buttonsPanel.add(saveButton);
|
||||
// buttonsPan.add(execButton);
|
||||
|
||||
|
||||
@@ -48,8 +48,12 @@ public class MethodBody implements Cloneable {
|
||||
return s;
|
||||
}
|
||||
|
||||
public int removeDeadCode(){
|
||||
return code.removeDeadCode(this);
|
||||
public int removeDeadCode(ConstantPool constants){
|
||||
return code.removeDeadCode(constants,this);
|
||||
}
|
||||
|
||||
public int removeTraps(ConstantPool constants){
|
||||
return code.removeTraps(constants, this);
|
||||
}
|
||||
|
||||
public HashMap<Integer, String> getLocalRegNames(ABC abc) {
|
||||
|
||||
@@ -236,11 +236,20 @@ public class MainFrame extends JFrame implements ActionListener {
|
||||
miRemoveDeadCodeAll.setActionCommand("REMOVEDEADCODEALL");
|
||||
miRemoveDeadCodeAll.addActionListener(this);
|
||||
|
||||
JMenuItem miTraps = new JMenuItem("Remove traps");
|
||||
miTraps.setActionCommand("REMOVETRAPS");
|
||||
miTraps.addActionListener(this);
|
||||
|
||||
JMenuItem miTrapsAll = new JMenuItem("Remove all traps");
|
||||
miTrapsAll.setActionCommand("REMOVETRAPSALL");
|
||||
miTrapsAll.addActionListener(this);
|
||||
|
||||
menuDeobfuscation.add(miSubLimiter);
|
||||
menuDeobfuscation.add(miRenameIdentifiers);
|
||||
menuDeobfuscation.add(miRemoveDeadCode);
|
||||
menuDeobfuscation.add(miRemoveDeadCodeAll);
|
||||
menuDeobfuscation.add(miTraps);
|
||||
menuDeobfuscation.add(miTrapsAll);
|
||||
|
||||
|
||||
JMenu menuTools = new JMenu("Tools");
|
||||
@@ -594,6 +603,10 @@ public class MainFrame extends JFrame implements ActionListener {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean confirmExperimental() {
|
||||
return JOptionPane.showConfirmDialog(null, "Following procedure can damage SWF file which can be then unplayable.\r\nUSE IT ON YOUR OWN RISK. Do you want to continue?", "Warning", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION;
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (e.getActionCommand().equals("EXIT")) {
|
||||
setVisible(false);
|
||||
@@ -724,34 +737,64 @@ public class MainFrame extends JFrame implements ActionListener {
|
||||
}
|
||||
}
|
||||
|
||||
if (e.getActionCommand().startsWith("REMOVETRAPS")) {
|
||||
Main.startWork("Removing traps...");
|
||||
final boolean all = e.getActionCommand().endsWith("ALL");
|
||||
if ((!all) || confirmExperimental()) {
|
||||
new SwingWorker() {
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
int cnt = 0;
|
||||
if (all) {
|
||||
for (DoABCTag tag : abcPanel.list) {
|
||||
cnt += tag.abc.removeTraps();
|
||||
}
|
||||
} else {
|
||||
int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex();
|
||||
if (bi != -1) {
|
||||
cnt += abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants);
|
||||
}
|
||||
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abcPanel.abc);
|
||||
}
|
||||
Main.stopWork();
|
||||
JOptionPane.showMessageDialog(null, "Traps removed: " + cnt);
|
||||
abcPanel.reload();
|
||||
return true;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
if (e.getActionCommand().startsWith("REMOVEDEADCODE")) {
|
||||
Main.startWork("Removing dead code...");
|
||||
final boolean all = e.getActionCommand().endsWith("ALL");
|
||||
new SwingWorker() {
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
int cnt = 0;
|
||||
if (all) {
|
||||
for (DoABCTag tag : abcPanel.list) {
|
||||
cnt += tag.abc.removeDeadCode();
|
||||
if ((!all) || confirmExperimental()) {
|
||||
new SwingWorker() {
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
int cnt = 0;
|
||||
if (all) {
|
||||
for (DoABCTag tag : abcPanel.list) {
|
||||
cnt += tag.abc.removeDeadCode();
|
||||
}
|
||||
} else {
|
||||
int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex();
|
||||
if (bi != -1) {
|
||||
cnt += abcPanel.abc.bodies[bi].removeDeadCode(abcPanel.abc.constants);
|
||||
}
|
||||
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abcPanel.abc);
|
||||
}
|
||||
}else{
|
||||
int bi=abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex();
|
||||
if(bi!=-1){
|
||||
cnt += abcPanel.abc.bodies[bi].removeDeadCode();
|
||||
}
|
||||
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abcPanel.abc);
|
||||
Main.stopWork();
|
||||
JOptionPane.showMessageDialog(null, "Instructions removed: " + cnt);
|
||||
abcPanel.reload();
|
||||
return true;
|
||||
}
|
||||
Main.stopWork();
|
||||
JOptionPane.showMessageDialog(null, "Instructions removed: " + cnt);
|
||||
abcPanel.reload();
|
||||
return true;
|
||||
}
|
||||
}.execute();
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
if (e.getActionCommand().equals("RENAMEIDENTIFIERS")) {
|
||||
if (JOptionPane.showConfirmDialog(null, "Following procedure can damage SWF file which can be then unplayable.\r\nUSE IT ON YOUR OWN RISK. Do you want to continue?", "Warning", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) {
|
||||
if (confirmExperimental()) {
|
||||
|
||||
Main.startWork("Renaming identifiers...");
|
||||
new SwingWorker() {
|
||||
|
||||
Reference in New Issue
Block a user