mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 00:10:59 +00:00
AS3 deobfuscation
This commit is contained in:
@@ -86,6 +86,12 @@ public class ABC {
|
|||||||
return rem;
|
return rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void restoreControlFlow() {
|
||||||
|
for(MethodBody body:bodies){
|
||||||
|
body.restoreControlFlow(constants);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int deobfuscateIdentifiers() {
|
public int deobfuscateIdentifiers() {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for (int i = 1; i < instance_info.length; i++) {
|
for (int i = 1; i < instance_info.length; i++) {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import java.util.logging.Logger;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import javax.swing.text.Highlighter;
|
import javax.swing.text.Highlighter;
|
||||||
|
import com.jpexs.asdec.abc.avm2.instructions.TagInstruction;
|
||||||
|
|
||||||
public class AVM2Code {
|
public class AVM2Code {
|
||||||
|
|
||||||
@@ -718,7 +719,9 @@ public class AVM2Code {
|
|||||||
}
|
}
|
||||||
long ofs = 0;
|
long ofs = 0;
|
||||||
for (AVM2Instruction ins : code) {
|
for (AVM2Instruction ins : code) {
|
||||||
if (offsets.contains(ofs)) {
|
if (ins.labelname != null) {
|
||||||
|
ret += ins.labelname + ":";
|
||||||
|
} else if (offsets.contains(ofs)) {
|
||||||
ret += "ofs" + Helper.formatAddress(ofs) + ":";
|
ret += "ofs" + Helper.formatAddress(ofs) + ":";
|
||||||
}
|
}
|
||||||
for (int e = 0; e < body.exceptions.length; e++) {
|
for (int e = 0; e < body.exceptions.length; e++) {
|
||||||
@@ -737,8 +740,13 @@ public class AVM2Code {
|
|||||||
if (ins2.isIgnored()) {
|
if (ins2.isIgnored()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ins2.definition instanceof JumpIns) {
|
if (ins2.definition instanceof TagInstruction) {
|
||||||
ret += "jump ofs" + Helper.formatAddress(pos2adr(ins2.operands[0])) + "\n";
|
if (ins2.definition.instructionName.equals("appendjump")) {
|
||||||
|
ret += "jump ofs" + Helper.formatAddress(pos2adr(ins2.operands[0])) + "\n";
|
||||||
|
}
|
||||||
|
if (ins2.definition.instructionName.equals("mark")) {
|
||||||
|
ret += "ofs" + Helper.formatAddress(pos2adr(ins2.operands[0])) + ":";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret += Highlighting.hilighOffset("", ofs) + ins2.toStringNoAddress(constants, new ArrayList<String>()) + "\n";
|
ret += Highlighting.hilighOffset("", ofs) + ins2.toStringNoAddress(constants, new ArrayList<String>()) + "\n";
|
||||||
}
|
}
|
||||||
@@ -1734,7 +1742,7 @@ public class AVM2Code {
|
|||||||
if (ex instanceof UnknownJumpException) {
|
if (ex instanceof UnknownJumpException) {
|
||||||
throw (UnknownJumpException) ex;
|
throw (UnknownJumpException) ex;
|
||||||
}
|
}
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
throw new ConvertException(ex.getClass().getSimpleName(), ip);
|
throw new ConvertException(ex.getClass().getSimpleName(), ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1933,7 +1941,7 @@ public class AVM2Code {
|
|||||||
|
|
||||||
s = listToString(list, constants, localRegNames, fullyQualifiedNames);
|
s = listToString(list, constants, localRegNames, fullyQualifiedNames);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
s = "/*\r\n * Decompilation error\r\n * Code may be obfuscated\r\n * Error Message: " + ex.getMessage() + "\r\n */";
|
s = "/*\r\n * Decompilation error\r\n * Code may be obfuscated\r\n * Error Message: " + ex.getMessage() + "\r\n */";
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -2175,8 +2183,6 @@ public class AVM2Code {
|
|||||||
code.add(pos, instruction);
|
code.add(pos, instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public int removePushTrueFalseTraps(ConstantPool constants, MethodBody body) throws ConvertException {
|
public int removePushTrueFalseTraps(ConstantPool constants, MethodBody body) throws ConvertException {
|
||||||
removeDeadCode(constants, body);
|
removeDeadCode(constants, body);
|
||||||
boolean isSecure = true;
|
boolean isSecure = true;
|
||||||
@@ -2328,8 +2334,8 @@ public class AVM2Code {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int ret=isSecure ? 1 : 0;
|
int ret = isSecure ? 1 : 0;
|
||||||
ret+=visitCodeTrap(body, new int[code.size()]);
|
ret += visitCodeTrap(body, new int[code.size()]);
|
||||||
removeIgnored(body);
|
removeIgnored(body);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -2358,11 +2364,11 @@ public class AVM2Code {
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
try {
|
try {
|
||||||
ret += removePushByteTraps(constants, body);
|
ret += removePushByteTraps(constants, body);
|
||||||
ret += removePushTrueFalseTraps(constants, body);
|
ret += removePushTrueFalseTraps(constants, body);
|
||||||
} catch (ConvertException ex) {
|
} catch (ConvertException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
restoreControlFlow(constants, body);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2462,10 +2468,11 @@ public class AVM2Code {
|
|||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitCode(int ip, int visited[]) {
|
private void visitCode(int ip, int lastIp, HashMap<Integer, List<Integer>> refs) {
|
||||||
while (ip < visited.length) {
|
while (ip < code.size()) {
|
||||||
visited[ip]++;
|
refs.get(ip).add(lastIp);
|
||||||
if (visited[ip] > 1) {
|
lastIp = ip;
|
||||||
|
if (refs.get(ip).size() > 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
AVM2Instruction ins = code.get(ip);
|
AVM2Instruction ins = code.get(ip);
|
||||||
@@ -2481,7 +2488,7 @@ public class AVM2Code {
|
|||||||
if (ins.definition instanceof LookupSwitchIns) {
|
if (ins.definition instanceof LookupSwitchIns) {
|
||||||
try {
|
try {
|
||||||
for (int i = 2; i < ins.operands.length; i++) {
|
for (int i = 2; i < ins.operands.length; i++) {
|
||||||
visitCode(adr2pos(pos2adr(ip) + ins.operands[i]), visited);
|
visitCode(adr2pos(pos2adr(ip) + ins.operands[i]), ip, refs);
|
||||||
}
|
}
|
||||||
ip = adr2pos(pos2adr(ip) + ins.operands[0]);
|
ip = adr2pos(pos2adr(ip) + ins.operands[0]);
|
||||||
continue;
|
continue;
|
||||||
@@ -2493,36 +2500,36 @@ public class AVM2Code {
|
|||||||
ip = adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
|
ip = adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
|
||||||
continue;
|
continue;
|
||||||
} catch (ConvertException ex) {
|
} catch (ConvertException ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
} else if (ins.definition instanceof IfTypeIns) {
|
} else if (ins.definition instanceof IfTypeIns) {
|
||||||
try {
|
try {
|
||||||
visitCode(adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]), visited);
|
visitCode(adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]), ip, refs);
|
||||||
} catch (ConvertException ex) {
|
} catch (ConvertException ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ip++;
|
ip++;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitCode(MethodBody body, int visited[]) {
|
private void visitCode(MethodBody body, HashMap<Integer, List<Integer>> refs) {
|
||||||
for (int i = 0; i < visited.length; i++) {
|
for (int i = 0; i < code.size(); i++) {
|
||||||
visited[i] = 0;
|
refs.put(i, new ArrayList<Integer>());
|
||||||
}
|
}
|
||||||
visitCode(0, visited);
|
visitCode(0, 0, refs);
|
||||||
for (ABCException e : body.exceptions) {
|
for (ABCException e : body.exceptions) {
|
||||||
try {
|
try {
|
||||||
visitCode(adr2pos(e.start), visited);
|
visitCode(adr2pos(e.start), adr2pos(e.start), refs);
|
||||||
visitCode(adr2pos(e.target), visited);
|
visitCode(adr2pos(e.target), adr2pos(e.target), refs);
|
||||||
} catch (ConvertException ex) {
|
} catch (ConvertException ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int visitCodeTrap(int ip, int visited[],AVM2Instruction prev) {
|
private int visitCodeTrap(int ip, int visited[], AVM2Instruction prev) {
|
||||||
int ret=0;
|
int ret = 0;
|
||||||
while (ip < visited.length) {
|
while (ip < visited.length) {
|
||||||
visited[ip]++;
|
visited[ip]++;
|
||||||
if (visited[ip] > 1) {
|
if (visited[ip] > 1) {
|
||||||
@@ -2541,10 +2548,10 @@ public class AVM2Code {
|
|||||||
if (ins.definition instanceof LookupSwitchIns) {
|
if (ins.definition instanceof LookupSwitchIns) {
|
||||||
try {
|
try {
|
||||||
for (int i = 2; i < ins.operands.length; i++) {
|
for (int i = 2; i < ins.operands.length; i++) {
|
||||||
ret+=visitCodeTrap(adr2pos(pos2adr(ip) + ins.operands[i]), visited,prev);
|
ret += visitCodeTrap(adr2pos(pos2adr(ip) + ins.operands[i]), visited, prev);
|
||||||
}
|
}
|
||||||
ip = adr2pos(pos2adr(ip) + ins.operands[0]);
|
ip = adr2pos(pos2adr(ip) + ins.operands[0]);
|
||||||
prev=ins;
|
prev = ins;
|
||||||
continue;
|
continue;
|
||||||
} catch (ConvertException ex) {
|
} catch (ConvertException ex) {
|
||||||
}
|
}
|
||||||
@@ -2552,10 +2559,10 @@ public class AVM2Code {
|
|||||||
if (ins.definition instanceof JumpIns) {
|
if (ins.definition instanceof JumpIns) {
|
||||||
try {
|
try {
|
||||||
ip = adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
|
ip = adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
|
||||||
prev=ins;
|
prev = ins;
|
||||||
continue;
|
continue;
|
||||||
} catch (ConvertException ex) {
|
} catch (ConvertException ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
} else if (ins.definition instanceof IfTypeIns) {
|
} else if (ins.definition instanceof IfTypeIns) {
|
||||||
if ((prev != null) && ins.definition instanceof IfTrueIns) {
|
if ((prev != null) && ins.definition instanceof IfTrueIns) {
|
||||||
@@ -2587,66 +2594,67 @@ public class AVM2Code {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ret+=visitCodeTrap(adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]), visited,prev);
|
ret += visitCodeTrap(adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]), visited, prev);
|
||||||
} catch (ConvertException ex) {
|
} catch (ConvertException ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ip++;
|
ip++;
|
||||||
prev=ins;
|
prev = ins;
|
||||||
};
|
};
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int visitCodeTrap(MethodBody body, int visited[]) {
|
private int visitCodeTrap(MethodBody body, int visited[]) {
|
||||||
int ret=0;
|
int ret = 0;
|
||||||
for (int i = 0; i < visited.length; i++) {
|
for (int i = 0; i < visited.length; i++) {
|
||||||
visited[i] = 0;
|
visited[i] = 0;
|
||||||
}
|
}
|
||||||
ret+=visitCodeTrap(0, visited,null);
|
ret += visitCodeTrap(0, visited, null);
|
||||||
for (ABCException e : body.exceptions) {
|
for (ABCException e : body.exceptions) {
|
||||||
try {
|
try {
|
||||||
ret+=visitCodeTrap(adr2pos(e.start), visited,null);
|
ret += visitCodeTrap(adr2pos(e.start), visited, null);
|
||||||
ret+=visitCodeTrap(adr2pos(e.target), visited,null);
|
ret += visitCodeTrap(adr2pos(e.target), visited, null);
|
||||||
} catch (ConvertException ex) {
|
} catch (ConvertException ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreControlFlow(int ip, int visited[], int visited2[], HashMap<Integer, List<AVM2Instruction>> appended) throws ConvertException {
|
public void restoreControlFlow(int ip, HashMap<Integer, List<Integer>> refs, int visited2[], HashMap<Integer, List<AVM2Instruction>> appended) throws ConvertException {
|
||||||
List<AVM2Instruction> buf = new ArrayList<AVM2Instruction>();
|
List<AVM2Instruction> buf = new ArrayList<AVM2Instruction>();
|
||||||
boolean cont = false;
|
boolean cont = false;
|
||||||
int continueip = 0;
|
int continueip = 0;
|
||||||
AVM2Instruction prev = null;
|
AVM2Instruction prev = null;
|
||||||
for (; ip < visited.length; ip++) {
|
for (; ip < code.size(); ip++) {
|
||||||
AVM2Instruction ins = code.get(ip);
|
AVM2Instruction ins = code.get(ip);
|
||||||
if (visited2[ip] > 0) {
|
|
||||||
break;
|
if ((refs.containsKey(ip) && refs.get(ip).size() > 1) || (visited2[ip] > 0)) {
|
||||||
}
|
|
||||||
visited2[ip]++;
|
|
||||||
if (visited[ip] > 1) {
|
|
||||||
if (cont) {
|
if (cont) {
|
||||||
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{ip}, new byte[0]));
|
buf.add(new AVM2Instruction(0, new TagInstruction("appendjump"), new int[]{ip}, new byte[0]));
|
||||||
}
|
}
|
||||||
cont = false;
|
cont = false;
|
||||||
|
if (visited2[ip] > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
visited2[ip]++;
|
||||||
if (ins.definition instanceof LookupSwitchIns) {
|
if (ins.definition instanceof LookupSwitchIns) {
|
||||||
|
|
||||||
if (cont) {
|
if (cont) {
|
||||||
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{ip}, new byte[0]));
|
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{ip}, new byte[0]));
|
||||||
}
|
}
|
||||||
cont = false;
|
cont = false;
|
||||||
restoreControlFlow(adr2pos(pos2adr(ip) + ins.operands[0]), visited, visited2, appended);
|
restoreControlFlow(adr2pos(pos2adr(ip) + ins.operands[0]), refs, visited2, appended);
|
||||||
for (int i = 2; i < ins.operands.length; i++) {
|
for (int i = 2; i < ins.operands.length; i++) {
|
||||||
restoreControlFlow(adr2pos(pos2adr(ip) + ins.operands[i]), visited, visited2, appended);
|
restoreControlFlow(adr2pos(pos2adr(ip) + ins.operands[i]), refs, visited2, appended);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ins.definition instanceof JumpIns) {
|
if (ins.definition instanceof JumpIns) {
|
||||||
int newip = adr2pos(pos2adr(ip + 1) + ins.operands[0]);
|
int newip = adr2pos(pos2adr(ip + 1) + ins.operands[0]);
|
||||||
if ((newip < visited.length) && (visited[newip] == 1)) {
|
if ((newip < code.size()) && (refs.containsKey(newip) && refs.get(newip).size() == 1)) {
|
||||||
if (!cont) {
|
if (!cont) {
|
||||||
continueip = ip;
|
continueip = ip;
|
||||||
buf = new ArrayList<AVM2Instruction>();
|
buf = new ArrayList<AVM2Instruction>();
|
||||||
@@ -2654,19 +2662,33 @@ public class AVM2Code {
|
|||||||
}
|
}
|
||||||
cont = true;
|
cont = true;
|
||||||
} else {
|
} else {
|
||||||
if (cont) {
|
if (ip == code.size() - 1) {
|
||||||
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{newip}, new byte[0]));
|
continueip = ip;
|
||||||
|
buf = new ArrayList<AVM2Instruction>();
|
||||||
|
appended.put(continueip, buf);
|
||||||
|
for (int i : refs.get(newip)) {
|
||||||
|
if (i != ip) {
|
||||||
|
code.get(i).labelname = "nolabel" + ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refs.get(newip).clear();
|
||||||
|
buf.add(new AVM2Instruction(0, new TagInstruction("mark"), new int[]{newip}, new byte[0]));
|
||||||
|
cont = true;
|
||||||
|
} else {
|
||||||
|
if (cont) {
|
||||||
|
buf.add(new AVM2Instruction(0, new TagInstruction("appendjump"), new int[]{ip}, new byte[0]));
|
||||||
|
}
|
||||||
|
cont = false;
|
||||||
}
|
}
|
||||||
cont = false;
|
|
||||||
}
|
}
|
||||||
ip = newip - 1;
|
ip = newip - 1;
|
||||||
} else if (ins.definition instanceof IfTypeIns) {
|
} else if (ins.definition instanceof IfTypeIns) {
|
||||||
int newip = adr2pos(pos2adr(ip + 1) + ins.operands[0]);
|
int newip = adr2pos(pos2adr(ip + 1) + ins.operands[0]);
|
||||||
if (cont) {
|
if (cont) {
|
||||||
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{ip}, new byte[0]));
|
buf.add(new AVM2Instruction(0, new TagInstruction("appendjump"), new int[]{ip}, new byte[0]));
|
||||||
}
|
}
|
||||||
cont = false;
|
cont = false;
|
||||||
restoreControlFlow(newip, visited, visited2, appended);
|
restoreControlFlow(newip, refs, visited2, appended);
|
||||||
} else if ((ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ThrowIns)) {
|
} else if ((ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ThrowIns)) {
|
||||||
if (cont) {
|
if (cont) {
|
||||||
buf.add(ins);
|
buf.add(ins);
|
||||||
@@ -2680,19 +2702,23 @@ public class AVM2Code {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreControlFlow(ConstantPool constants, MethodBody body) {
|
private void restoreControlFlowPass(ConstantPool constants, MethodBody body, boolean secondpass) {
|
||||||
try {
|
try {
|
||||||
int visited[] = new int[code.size()];
|
HashMap<Integer, List<Integer>> refs = new HashMap<Integer, List<Integer>>();
|
||||||
int visited2[] = new int[code.size()];
|
int visited2[] = new int[code.size()];
|
||||||
visitCode(body, visited);
|
visitCode(body, refs);
|
||||||
HashMap<Integer, List<AVM2Instruction>> appended = new HashMap<Integer, List<AVM2Instruction>>();
|
HashMap<Integer, List<AVM2Instruction>> appended = new HashMap<Integer, List<AVM2Instruction>>();
|
||||||
restoreControlFlow(0, visited, visited2, appended);
|
if (secondpass) {
|
||||||
for (ABCException e : body.exceptions) {
|
restoreControlFlow(code.size() - 1, refs, visited2, appended);
|
||||||
try {
|
} else {
|
||||||
restoreControlFlow(adr2pos(e.start), visited, visited2, appended);
|
restoreControlFlow(0, refs, visited2, appended);
|
||||||
restoreControlFlow(adr2pos(e.target), visited, visited2, appended);
|
for (ABCException e : body.exceptions) {
|
||||||
} catch (ConvertException ex) {
|
try {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
restoreControlFlow(adr2pos(e.start), refs, visited2, appended);
|
||||||
|
restoreControlFlow(adr2pos(e.target), refs, visited2, appended);
|
||||||
|
} catch (ConvertException ex) {
|
||||||
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int ip : appended.keySet()) {
|
for (int ip : appended.keySet()) {
|
||||||
@@ -2702,20 +2728,22 @@ public class AVM2Code {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
String src = Highlighting.stripHilights(toASMSource(constants, body));
|
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);
|
AVM2Code acode = ASM3Parser.parse(new ByteArrayInputStream(src.getBytes()), constants, null, body);
|
||||||
this.code = acode.code;
|
this.code = acode.code;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
} catch (ParseException ex) {
|
} catch (ParseException ex) {
|
||||||
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
|
||||||
}
|
}
|
||||||
invalidateCache();
|
invalidateCache();
|
||||||
removeDeadCode(constants, body);
|
removeDeadCode(constants, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void restoreControlFlow(ConstantPool constants, MethodBody body) {
|
||||||
|
restoreControlFlowPass(constants, body, false);
|
||||||
|
restoreControlFlowPass(constants, body, true);
|
||||||
|
}
|
||||||
|
|
||||||
private void removeIgnored(MethodBody body) {
|
private void removeIgnored(MethodBody body) {
|
||||||
for (int rem = code.size() - 1; rem >= 0; rem--) {
|
for (int rem = code.size() - 1; rem >= 0; rem--) {
|
||||||
if (code.get(rem).ignored) {
|
if (code.get(rem).ignored) {
|
||||||
@@ -2725,12 +2753,11 @@ public class AVM2Code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int removeDeadCode(ConstantPool constants, MethodBody body) {
|
public int removeDeadCode(ConstantPool constants, MethodBody body) {
|
||||||
int visited[] = new int[code.size()];
|
HashMap<Integer, List<Integer>> refs = new HashMap<Integer, List<Integer>>();
|
||||||
|
visitCode(body, refs);
|
||||||
visitCode(body, visited);
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (int i = visited.length - 1; i >= 0; i--) {
|
for (int i = code.size() - 1; i >= 0; i--) {
|
||||||
if (visited[i] == 0) {
|
if (refs.get(i).isEmpty()) {
|
||||||
removeInstruction(i, body);
|
removeInstruction(i, body);
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public class AVM2Instruction {
|
|||||||
public byte bytes[];
|
public byte bytes[];
|
||||||
public String comment;
|
public String comment;
|
||||||
public boolean ignored = false;
|
public boolean ignored = false;
|
||||||
|
public String labelname;
|
||||||
|
|
||||||
public AVM2Instruction(long offset, InstructionDefinition definition, int[] operands, byte bytes[]) {
|
public AVM2Instruction(long offset, InstructionDefinition definition, int[] operands, byte bytes[]) {
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-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.asdec.abc.avm2.instructions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author JPEXS
|
||||||
|
*/
|
||||||
|
public class TagInstruction extends InstructionDefinition {
|
||||||
|
|
||||||
|
public TagInstruction(String tagName) {
|
||||||
|
super(-1, tagName, new int[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener {
|
|||||||
public ABC abc;
|
public ABC abc;
|
||||||
public List<DoABCTag> list;
|
public List<DoABCTag> list;
|
||||||
public JComboBox abcComboBox;
|
public JComboBox abcComboBox;
|
||||||
public int listIndex = 0;
|
public int listIndex = -1;
|
||||||
public DecompiledEditorPane decompiledTextArea;
|
public DecompiledEditorPane decompiledTextArea;
|
||||||
public JScrollPane decompiledScrollPane;
|
public JScrollPane decompiledScrollPane;
|
||||||
public JSplitPane splitPaneDecompiledVSDetail;
|
public JSplitPane splitPaneDecompiledVSDetail;
|
||||||
@@ -175,7 +175,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener {
|
|||||||
|
|
||||||
this.list = list;
|
this.list = list;
|
||||||
if (list.size() > 0) {
|
if (list.size() > 0) {
|
||||||
this.abc = list.get(listIndex).abc;
|
this.abc = list.get(0).abc;
|
||||||
}
|
}
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-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.asdec.abc.gui;
|
||||||
|
|
||||||
|
import com.jpexs.asdec.gui.View;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSlider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author JPEXS
|
||||||
|
*/
|
||||||
|
public class DeobfuscationDialog extends JDialog implements ActionListener {
|
||||||
|
|
||||||
|
public JCheckBox renameIdentifiersCheckbox = new JCheckBox("Rename identifiers");
|
||||||
|
public JCheckBox processAllCheckbox = new JCheckBox("Process all classes");
|
||||||
|
public JSlider codeProcessingLevel;
|
||||||
|
public boolean ok = false;
|
||||||
|
public static final int LEVEL_NONE = 0;
|
||||||
|
public static final int LEVEL_REMOVE_DEAD_CODE = 1;
|
||||||
|
public static final int LEVEL_REMOVE_TRAPS = 2;
|
||||||
|
public static final int LEVEL_RESTORE_CONTROL_FLOW = 3;
|
||||||
|
|
||||||
|
public DeobfuscationDialog() {
|
||||||
|
setDefaultCloseOperation(HIDE_ON_CLOSE);
|
||||||
|
setSize(new Dimension(300, 270));
|
||||||
|
setTitle("About");
|
||||||
|
Container cp = getContentPane();
|
||||||
|
cp.setLayout(null);
|
||||||
|
codeProcessingLevel = new JSlider(JSlider.VERTICAL, 0, 3, 3);
|
||||||
|
codeProcessingLevel.setMajorTickSpacing(1);
|
||||||
|
codeProcessingLevel.setPaintTicks(true);
|
||||||
|
codeProcessingLevel.setMinorTickSpacing(1);
|
||||||
|
codeProcessingLevel.setSnapToTicks(true);
|
||||||
|
JLabel lab1=new JLabel("Code deobfuscation level:");
|
||||||
|
lab1.setBounds(30, 0, getWidth()-60, 25);
|
||||||
|
cp.add(lab1);
|
||||||
|
Hashtable labelTable = new Hashtable();
|
||||||
|
labelTable.put(new Integer(LEVEL_NONE), new JLabel("None"));
|
||||||
|
labelTable.put(new Integer(LEVEL_REMOVE_DEAD_CODE), new JLabel("Remove dead code"));
|
||||||
|
labelTable.put(new Integer(LEVEL_REMOVE_TRAPS), new JLabel("Remove traps"));
|
||||||
|
labelTable.put(new Integer(LEVEL_RESTORE_CONTROL_FLOW), new JLabel("Restore control flow"));
|
||||||
|
codeProcessingLevel.setLabelTable(labelTable);
|
||||||
|
|
||||||
|
codeProcessingLevel.setPaintLabels(true);
|
||||||
|
codeProcessingLevel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
codeProcessingLevel.setSize(300, 200);
|
||||||
|
|
||||||
|
renameIdentifiersCheckbox.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (renameIdentifiersCheckbox.isSelected()) {
|
||||||
|
processAllCheckbox.setSelected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
processAllCheckbox.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if(!processAllCheckbox.isSelected()){
|
||||||
|
renameIdentifiersCheckbox.setSelected(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
codeProcessingLevel.setBounds(30,25,getWidth()-60,125);
|
||||||
|
|
||||||
|
add(codeProcessingLevel);
|
||||||
|
processAllCheckbox.setBounds(50, 150, getWidth()-100, 25);
|
||||||
|
add(processAllCheckbox);
|
||||||
|
renameIdentifiersCheckbox.setBounds(50, 175, getWidth()-100, 25);
|
||||||
|
add(renameIdentifiersCheckbox);
|
||||||
|
|
||||||
|
processAllCheckbox.setSelected(true);
|
||||||
|
renameIdentifiersCheckbox.setSelected(true);
|
||||||
|
|
||||||
|
JButton cancelButton = new JButton("Cancel");
|
||||||
|
cancelButton.addActionListener(this);
|
||||||
|
cancelButton.setActionCommand("CANCEL");
|
||||||
|
JButton okButton = new JButton("OK");
|
||||||
|
okButton.addActionListener(this);
|
||||||
|
okButton.setActionCommand("OK");
|
||||||
|
okButton.setBounds(50, 200, 75, 25);
|
||||||
|
cancelButton.setBounds(145, 200, 75, 25);
|
||||||
|
cp.add(okButton);
|
||||||
|
cp.add(cancelButton);
|
||||||
|
setModal(true);
|
||||||
|
View.centerScreen(this);
|
||||||
|
View.setWindowIcon(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (e.getActionCommand().equals("OK")) {
|
||||||
|
ok = true;
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
if (e.getActionCommand().equals("CANCEL")) {
|
||||||
|
ok = false;
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(boolean b) {
|
||||||
|
if(b){
|
||||||
|
ok=false;
|
||||||
|
}
|
||||||
|
super.setVisible(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -51,6 +51,9 @@ public class MethodBody implements Cloneable {
|
|||||||
public int removeDeadCode(ConstantPool constants){
|
public int removeDeadCode(ConstantPool constants){
|
||||||
return code.removeDeadCode(constants,this);
|
return code.removeDeadCode(constants,this);
|
||||||
}
|
}
|
||||||
|
public void restoreControlFlow(ConstantPool constants) {
|
||||||
|
code.restoreControlFlow(constants, this);
|
||||||
|
}
|
||||||
|
|
||||||
public int removeTraps(ConstantPool constants){
|
public int removeTraps(ConstantPool constants){
|
||||||
return code.removeTraps(constants, this);
|
return code.removeTraps(constants, this);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.jpexs.asdec.Configuration;
|
|||||||
import com.jpexs.asdec.Main;
|
import com.jpexs.asdec.Main;
|
||||||
import com.jpexs.asdec.SWF;
|
import com.jpexs.asdec.SWF;
|
||||||
import com.jpexs.asdec.abc.gui.ABCPanel;
|
import com.jpexs.asdec.abc.gui.ABCPanel;
|
||||||
|
import com.jpexs.asdec.abc.gui.DeobfuscationDialog;
|
||||||
import com.jpexs.asdec.abc.gui.TreeLeafScript;
|
import com.jpexs.asdec.abc.gui.TreeLeafScript;
|
||||||
import com.jpexs.asdec.action.gui.ActionPanel;
|
import com.jpexs.asdec.action.gui.ActionPanel;
|
||||||
import com.jpexs.asdec.tags.DefineBitsJPEG2Tag;
|
import com.jpexs.asdec.tags.DefineBitsJPEG2Tag;
|
||||||
@@ -95,6 +96,7 @@ public class MainFrame extends JFrame implements ActionListener {
|
|||||||
public JLabel statusLabel = new JLabel("");
|
public JLabel statusLabel = new JLabel("");
|
||||||
public JPanel statusPanel = new JPanel();
|
public JPanel statusPanel = new JPanel();
|
||||||
public JProgressBar progressBar = new JProgressBar(0, 100);
|
public JProgressBar progressBar = new JProgressBar(0, 100);
|
||||||
|
private DeobfuscationDialog deobfuscationDialog;
|
||||||
|
|
||||||
public void setPercent(int percent) {
|
public void setPercent(int percent) {
|
||||||
progressBar.setValue(percent);
|
progressBar.setValue(percent);
|
||||||
@@ -220,6 +222,14 @@ public class MainFrame extends JFrame implements ActionListener {
|
|||||||
menuFile.add(miClose);
|
menuFile.add(miClose);
|
||||||
menuBar.add(menuFile);
|
menuBar.add(menuFile);
|
||||||
JMenu menuDeobfuscation = new JMenu("Deobfuscation");
|
JMenu menuDeobfuscation = new JMenu("Deobfuscation");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
JMenuItem miDeobfuscation = new JMenuItem("Deobfuscation...");
|
||||||
|
miDeobfuscation.setActionCommand("DEOBFUSCATE");
|
||||||
|
miDeobfuscation.addActionListener(this);
|
||||||
|
|
||||||
JCheckBoxMenuItem miSubLimiter = new JCheckBoxMenuItem("Enable sub limiter");
|
JCheckBoxMenuItem miSubLimiter = new JCheckBoxMenuItem("Enable sub limiter");
|
||||||
miSubLimiter.setActionCommand("SUBLIMITER");
|
miSubLimiter.setActionCommand("SUBLIMITER");
|
||||||
miSubLimiter.addActionListener(this);
|
miSubLimiter.addActionListener(this);
|
||||||
@@ -244,14 +254,26 @@ public class MainFrame extends JFrame implements ActionListener {
|
|||||||
miTrapsAll.setActionCommand("REMOVETRAPSALL");
|
miTrapsAll.setActionCommand("REMOVETRAPSALL");
|
||||||
miTrapsAll.addActionListener(this);
|
miTrapsAll.addActionListener(this);
|
||||||
|
|
||||||
menuDeobfuscation.add(miSubLimiter);
|
JMenuItem miControlFlow = new JMenuItem("Restore control flow");
|
||||||
|
miControlFlow.setActionCommand("RESTORECONTROLFLOW");
|
||||||
|
miControlFlow.addActionListener(this);
|
||||||
|
|
||||||
|
JMenuItem miControlFlowAll = new JMenuItem("Restore all control flow");
|
||||||
|
miControlFlowAll.setActionCommand("RESTORECONTROLFLOWALL");
|
||||||
|
miControlFlowAll.addActionListener(this);
|
||||||
|
|
||||||
|
//menuDeobfuscation.add(miSubLimiter);
|
||||||
|
//menuDeobfuscation.add(miDeobfuscate);
|
||||||
|
/*menuDeobfuscation.add(miDeobfuscate);
|
||||||
|
menuDeobfuscation.addSeparator();
|
||||||
menuDeobfuscation.add(miRenameIdentifiers);
|
menuDeobfuscation.add(miRenameIdentifiers);
|
||||||
menuDeobfuscation.add(miRemoveDeadCode);
|
menuDeobfuscation.add(miRemoveDeadCode);
|
||||||
menuDeobfuscation.add(miRemoveDeadCodeAll);
|
menuDeobfuscation.add(miRemoveDeadCodeAll);
|
||||||
menuDeobfuscation.add(miTraps);
|
menuDeobfuscation.add(miTraps);
|
||||||
menuDeobfuscation.add(miTrapsAll);
|
menuDeobfuscation.add(miTrapsAll);
|
||||||
|
menuDeobfuscation.add(miControlFlow);
|
||||||
|
menuDeobfuscation.add(miControlFlowAll);
|
||||||
|
*/
|
||||||
JMenu menuTools = new JMenu("Tools");
|
JMenu menuTools = new JMenu("Tools");
|
||||||
JMenuItem miProxy = new JMenuItem("Proxy");
|
JMenuItem miProxy = new JMenuItem("Proxy");
|
||||||
miProxy.setActionCommand("SHOWPROXY");
|
miProxy.setActionCommand("SHOWPROXY");
|
||||||
@@ -259,7 +281,8 @@ public class MainFrame extends JFrame implements ActionListener {
|
|||||||
miProxy.addActionListener(this);
|
miProxy.addActionListener(this);
|
||||||
menuTools.add(miProxy);
|
menuTools.add(miProxy);
|
||||||
|
|
||||||
menuTools.add(menuDeobfuscation);
|
//menuTools.add(menuDeobfuscation);
|
||||||
|
menuTools.add(miDeobfuscation);
|
||||||
menuBar.add(menuTools);
|
menuBar.add(menuTools);
|
||||||
|
|
||||||
JMenu menuHelp = new JMenu("Help");
|
JMenu menuHelp = new JMenu("Help");
|
||||||
@@ -305,7 +328,7 @@ public class MainFrame extends JFrame implements ActionListener {
|
|||||||
if (actionPanel.tagTree.getRowCount() > 1) {
|
if (actionPanel.tagTree.getRowCount() > 1) {
|
||||||
addTab(tabPane, actionPanel, "ActionScript", new ImageIcon(this.getClass().getClassLoader().getResource("com/jpexs/asdec/gui/graphics/as16.png")));
|
addTab(tabPane, actionPanel, "ActionScript", new ImageIcon(this.getClass().getClassLoader().getResource("com/jpexs/asdec/gui/graphics/as16.png")));
|
||||||
}
|
}
|
||||||
menuDeobfuscation.setEnabled(false);
|
miDeobfuscation.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shapes.isEmpty()) {
|
if (!shapes.isEmpty()) {
|
||||||
@@ -737,6 +760,34 @@ public class MainFrame extends JFrame implements ActionListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.getActionCommand().startsWith("RESTORECONTROLFLOW")) {
|
||||||
|
Main.startWork("Restoring control flow...");
|
||||||
|
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) {
|
||||||
|
tag.abc.restoreControlFlow();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex();
|
||||||
|
if (bi != -1) {
|
||||||
|
abcPanel.abc.bodies[bi].restoreControlFlow(abcPanel.abc.constants);
|
||||||
|
}
|
||||||
|
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abcPanel.abc);
|
||||||
|
}
|
||||||
|
Main.stopWork();
|
||||||
|
JOptionPane.showMessageDialog(null, "Control flow restored");
|
||||||
|
abcPanel.reload();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (e.getActionCommand().startsWith("REMOVETRAPS")) {
|
if (e.getActionCommand().startsWith("REMOVETRAPS")) {
|
||||||
Main.startWork("Removing traps...");
|
Main.startWork("Removing traps...");
|
||||||
final boolean all = e.getActionCommand().endsWith("ALL");
|
final boolean all = e.getActionCommand().endsWith("ALL");
|
||||||
@@ -815,5 +866,51 @@ public class MainFrame extends JFrame implements ActionListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.getActionCommand().startsWith("DEOBFUSCATE")) {
|
||||||
|
if(deobfuscationDialog==null){
|
||||||
|
deobfuscationDialog = new DeobfuscationDialog();
|
||||||
|
}
|
||||||
|
deobfuscationDialog.setVisible(true);
|
||||||
|
if (deobfuscationDialog.ok) {
|
||||||
|
Main.startWork("Deobfuscating...");
|
||||||
|
new SwingWorker() {
|
||||||
|
@Override
|
||||||
|
protected Object doInBackground() throws Exception {
|
||||||
|
if (deobfuscationDialog.processAllCheckbox.isSelected()) {
|
||||||
|
for (DoABCTag tag : abcPanel.list) {
|
||||||
|
if (deobfuscationDialog.renameIdentifiersCheckbox.isSelected()) {
|
||||||
|
tag.abc.deobfuscateIdentifiers();
|
||||||
|
}
|
||||||
|
if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_DEAD_CODE) {
|
||||||
|
tag.abc.removeDeadCode();
|
||||||
|
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_TRAPS) {
|
||||||
|
tag.abc.removeTraps();
|
||||||
|
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_RESTORE_CONTROL_FLOW) {
|
||||||
|
tag.abc.removeTraps();
|
||||||
|
tag.abc.restoreControlFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex();
|
||||||
|
if (bi != -1) {
|
||||||
|
if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_DEAD_CODE) {
|
||||||
|
abcPanel.abc.bodies[bi].removeDeadCode(abcPanel.abc.constants);
|
||||||
|
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_TRAPS) {
|
||||||
|
abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants);
|
||||||
|
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_RESTORE_CONTROL_FLOW) {
|
||||||
|
abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants);
|
||||||
|
abcPanel.abc.bodies[bi].restoreControlFlow(abcPanel.abc.constants);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abcPanel.abc);
|
||||||
|
}
|
||||||
|
Main.stopWork();
|
||||||
|
JOptionPane.showMessageDialog(null, "Deobfuscation complete");
|
||||||
|
abcPanel.reload();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user