AS3 automatic deobfuscation, better identifiers renaming

This commit is contained in:
Jindra Petk
2013-01-29 20:41:49 +01:00
parent c26a46139e
commit 5a422fd18f
9 changed files with 168 additions and 118 deletions

View File

@@ -71,48 +71,48 @@ public class ABC {
}
public int removeTraps() {
int rem=0;
for(MethodBody body:bodies){
rem+=body.removeTraps(constants);
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(constants);
int rem = 0;
for (MethodBody body : bodies) {
rem += body.removeDeadCode(constants);
}
return rem;
}
public void restoreControlFlow() {
for(MethodBody body:bodies){
for (MethodBody body : bodies) {
body.restoreControlFlow(constants);
}
}
public int deobfuscateIdentifiers() {
public int deobfuscateIdentifiers(HashMap<String, String> namesMap) {
int ret = 0;
for (int i = 1; i < instance_info.length; i++) {
if (instance_info[i].name_index != 0) {
if (deobfuscateName(constants.constant_multiname[instance_info[i].name_index].name_index, true)) {
if (deobfuscateName(namesMap, constants.constant_multiname[instance_info[i].name_index].name_index, true)) {
ret++;
}
}
if (instance_info[i].super_index != 0) {
if (deobfuscateName(constants.constant_multiname[instance_info[i].super_index].name_index, true)) {
if (deobfuscateName(namesMap, constants.constant_multiname[instance_info[i].super_index].name_index, true)) {
ret++;
}
}
}
for (int i = 1; i < constants.constant_multiname.length; i++) {
if (deobfuscateName(constants.constant_multiname[i].name_index, false)) {
if (deobfuscateName(namesMap, constants.constant_multiname[i].name_index, false)) {
ret++;
}
}
for (int i = 1; i < constants.constant_namespace.length; i++) {
if (deobfuscateNameSpace(constants.constant_namespace[i].name_index)) {
if (deobfuscateNameSpace(namesMap, constants.constant_namespace[i].name_index)) {
ret++;
}
}
@@ -593,9 +593,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", "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",
"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";
@@ -657,7 +657,7 @@ public class ABC {
return false;
}
public boolean deobfuscateNameSpace(int strIndex) {
public boolean deobfuscateNameSpace(HashMap<String, String> namesMap, int strIndex) {
if (strIndex <= 0) {
return false;
}
@@ -680,12 +680,17 @@ public class ABC {
isValid = false;
}
if (!isValid) {
constants.constant_string[strIndex] = fooString(constants.constant_string[strIndex], false, DEFAULT_FOO_SIZE);
if (namesMap.containsKey(s)) {
constants.constant_string[strIndex] = namesMap.get(s);
} else {
constants.constant_string[strIndex] = fooString(constants.constant_string[strIndex], false, DEFAULT_FOO_SIZE);
namesMap.put(s, constants.constant_string[strIndex]);
}
}
return !isValid;
}
public boolean deobfuscateName(int strIndex, boolean firstUppercase) {
public boolean deobfuscateName(HashMap<String, String> namesMap, int strIndex, boolean firstUppercase) {
if (strIndex <= 0) {
return false;
}
@@ -710,7 +715,12 @@ public class ABC {
}
if (!isValid) {
constants.constant_string[strIndex] = fooString(constants.constant_string[strIndex], firstUppercase, DEFAULT_FOO_SIZE);
if (namesMap.containsKey(s)) {
constants.constant_string[strIndex] = namesMap.get(s);
} else {
constants.constant_string[strIndex] = fooString(constants.constant_string[strIndex], firstUppercase, DEFAULT_FOO_SIZE);
namesMap.put(s, constants.constant_string[strIndex]);
}
}
return !isValid;
}

View File

@@ -61,7 +61,7 @@ import java.util.regex.Pattern;
import javax.swing.text.Highlighter;
import com.jpexs.asdec.abc.avm2.instructions.TagInstruction;
public class AVM2Code {
public class AVM2Code implements Serializable {
private static final boolean DEBUG_MODE = false;
public static int toSourceLimit = -1;
@@ -708,6 +708,10 @@ public class AVM2Code {
}
public String toASMSource(ConstantPool constants, MethodBody body) {
return toASMSource(constants, body, new ArrayList<Integer>());
}
public String toASMSource(ConstantPool constants, MethodBody body, List<Integer> outputMap) {
String ret = "";
for (int e = 0; e < body.exceptions.length; e++) {
ret += "exception " + e + " m[" + body.exceptions[e].name_index + "]\"" + Helper.escapeString(body.exceptions[e].getVarName(constants, new ArrayList<String>())) + "\" "
@@ -718,6 +722,7 @@ public class AVM2Code {
offsets.addAll(ins.getOffsets());
}
long ofs = 0;
int ip = 0;
for (AVM2Instruction ins : code) {
if (ins.labelname != null) {
ret += ins.labelname + ":";
@@ -736,28 +741,33 @@ public class AVM2Code {
}
}
if (ins.replaceWith != null) {
for (AVM2Instruction ins2 : ins.replaceWith) {
if (ins2.isIgnored()) {
continue;
}
if (ins2.definition instanceof TagInstruction) {
if (ins2.definition.instructionName.equals("appendjump")) {
ret += "jump ofs" + Helper.formatAddress(pos2adr(ins2.operands[0])) + "\n";
for (Object o : ins.replaceWith) {
if (o instanceof Integer) {
AVM2Instruction ins2 = code.get((Integer) o);
if (ins2.isIgnored()) {
continue;
}
if (ins2.definition.instructionName.equals("mark")) {
ret += "ofs" + Helper.formatAddress(pos2adr(ins2.operands[0])) + ":";
}
} else {
ret += Highlighting.hilighOffset("", ofs) + ins2.toStringNoAddress(constants, new ArrayList<String>()) + "\n";
outputMap.add((Integer) o);
} else if (o instanceof ControlFlowTag) {
ControlFlowTag cft = (ControlFlowTag) o;
if (cft.name.equals("appendjump")) {
ret += "jump ofs" + Helper.formatAddress(pos2adr(cft.value)) + "\n";
outputMap.add(-1);
}
if (cft.name.equals("mark")) {
ret += "ofs" + Helper.formatAddress(pos2adr(cft.value)) + ":";
}
}
}
} else {
if (!ins.isIgnored()) {
ret += Highlighting.hilighOffset("", ofs) + ins.toStringNoAddress(constants, new ArrayList<String>()) + "\n";
outputMap.add(ip);
}
}
ofs += ins.getBytes().length;
ip++;
}
return ret;
@@ -2622,8 +2632,19 @@ public class AVM2Code {
return ret;
}
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>();
private static class ControlFlowTag {
public String name;
public int value;
public ControlFlowTag(String name, int value) {
this.name = name;
this.value = value;
}
}
public void restoreControlFlow(int ip, HashMap<Integer, List<Integer>> refs, int visited2[], HashMap<Integer, List> appended) throws ConvertException {
List buf = new ArrayList();
boolean cont = false;
int continueip = 0;
AVM2Instruction prev = null;
@@ -2632,7 +2653,7 @@ public class AVM2Code {
if ((refs.containsKey(ip) && refs.get(ip).size() > 1) || (visited2[ip] > 0)) {
if (cont) {
buf.add(new AVM2Instruction(0, new TagInstruction("appendjump"), new int[]{ip}, new byte[0]));
buf.add(new ControlFlowTag("appendjump", ip));
}
cont = false;
if (visited2[ip] > 0) {
@@ -2643,7 +2664,7 @@ public class AVM2Code {
if (ins.definition instanceof LookupSwitchIns) {
if (cont) {
buf.add(new AVM2Instruction(0, new JumpIns(), new int[]{ip}, new byte[0]));
buf.add(new ControlFlowTag("appendjump", ip));
}
cont = false;
restoreControlFlow(adr2pos(pos2adr(ip) + ins.operands[0]), refs, visited2, appended);
@@ -2672,11 +2693,11 @@ public class AVM2Code {
}
}
refs.get(newip).clear();
buf.add(new AVM2Instruction(0, new TagInstruction("mark"), new int[]{newip}, new byte[0]));
buf.add(new ControlFlowTag("mark", newip));
cont = true;
} else {
if (cont) {
buf.add(new AVM2Instruction(0, new TagInstruction("appendjump"), new int[]{ip}, new byte[0]));
buf.add(new ControlFlowTag("appendjump", ip));
}
cont = false;
}
@@ -2685,17 +2706,17 @@ public class AVM2Code {
} else if (ins.definition instanceof IfTypeIns) {
int newip = adr2pos(pos2adr(ip + 1) + ins.operands[0]);
if (cont) {
buf.add(new AVM2Instruction(0, new TagInstruction("appendjump"), new int[]{ip}, new byte[0]));
buf.add(new ControlFlowTag("appendjump", ip));
}
cont = false;
restoreControlFlow(newip, refs, visited2, appended);
} else if ((ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ThrowIns)) {
if (cont) {
buf.add(ins);
buf.add(ip);
}
break;
} else if (cont) {
buf.add(ins);
buf.add(ip);
}
prev = ins;
}
@@ -2707,7 +2728,7 @@ public class AVM2Code {
HashMap<Integer, List<Integer>> refs = new HashMap<Integer, List<Integer>>();
int visited2[] = new int[code.size()];
visitCode(body, refs);
HashMap<Integer, List<AVM2Instruction>> appended = new HashMap<Integer, List<AVM2Instruction>>();
HashMap<Integer, List> appended = new HashMap<Integer, List>();
if (secondpass) {
restoreControlFlow(code.size() - 1, refs, visited2, appended);
} else {
@@ -2726,9 +2747,24 @@ public class AVM2Code {
}
} catch (ConvertException cex) {
}
invalidateCache();
try {
String src = Highlighting.stripHilights(toASMSource(constants, body));
AVM2Code acode = ASM3Parser.parse(new ByteArrayInputStream(src.getBytes()), constants, null, body);
List<Integer> outputMap = new ArrayList<Integer>();
String src = Highlighting.stripHilights(toASMSource(constants, body, outputMap));
AVM2Code acode = ASM3Parser.parse(new ByteArrayInputStream(src.getBytes()), constants, null, body);
for (int i = 0; i < acode.code.size(); i++) {
if (outputMap.size() > i) {
int tpos = outputMap.get(i);
if(tpos==-1){
}else if (code.get(tpos).mappedOffset >= 0) {
acode.code.get(i).mappedOffset = code.get(tpos).mappedOffset;
} else {
acode.code.get(i).mappedOffset = pos2adr(tpos);
}
}
}
this.code = acode.code;
} catch (IOException ex) {
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
@@ -2773,4 +2809,29 @@ public class AVM2Code {
}
return cnt;
}
public void markMappedOffsets(){
int ofs=0;
for(int i=0;i<code.size();i++){
code.get(i).mappedOffset=ofs;
ofs+=code.get(i).getBytes().length;
}
}
public AVM2Code deepCopy() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
AVM2Code copy = (AVM2Code) ois.readObject();
ois.close();
return copy;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}

View File

@@ -22,10 +22,11 @@ import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.helpers.Helper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class AVM2Instruction {
public class AVM2Instruction implements Serializable{
public InstructionDefinition definition;
public int operands[];
@@ -34,6 +35,7 @@ public class AVM2Instruction {
public String comment;
public boolean ignored = false;
public String labelname;
public long mappedOffset=-1;
public AVM2Instruction(long offset, InstructionDefinition definition, int[] operands, byte bytes[]) {
this.definition = definition;
@@ -226,5 +228,5 @@ public class AVM2Instruction {
return s;
}
public List<AVM2Instruction> replaceWith;
public List replaceWith;
}

View File

@@ -24,11 +24,12 @@ import com.jpexs.asdec.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.types.MethodInfo;
import com.jpexs.asdec.helpers.Highlighting;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class InstructionDefinition {
public class InstructionDefinition implements Serializable{
protected String hilighOffset(String text, long offset) {
return Highlighting.hilighOffset(text, offset);

View File

@@ -68,7 +68,11 @@ public abstract class TreeItem {
if (instruction == null) {
return str;
}
return Highlighting.hilighOffset(str, instruction.offset);
if(instruction.mappedOffset>=0){
return Highlighting.hilighOffset(str, instruction.mappedOffset);
}else{
return Highlighting.hilighOffset(str, instruction.offset);
}
}
public boolean isFalse() {

View File

@@ -102,7 +102,8 @@ public class ASMSourceEditorPane extends LineMarkedEditorPane implements CaretLi
@Override
public void setText(String t) {
disassembledHilights = Highlighting.getInstrHighlights(t);
super.setText(Highlighting.stripHilights(t));
t=Highlighting.stripHilights(t);
super.setText(t);
}
public void verify(ConstantPool constants, ABC abc) {

View File

@@ -41,11 +41,9 @@ import javax.swing.JSlider;
*/
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;
@@ -53,19 +51,19 @@ public class DeobfuscationDialog extends JDialog implements ActionListener {
public DeobfuscationDialog() {
setDefaultCloseOperation(HIDE_ON_CLOSE);
setSize(new Dimension(300, 270));
setTitle("About");
Container cp = getContentPane();
setTitle("PCode deobfuscation");
Container cp = getContentPane();
cp.setLayout(null);
codeProcessingLevel = new JSlider(JSlider.VERTICAL, 0, 3, 3);
codeProcessingLevel = new JSlider(JSlider.VERTICAL, 1, 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);
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_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"));
@@ -75,42 +73,22 @@ Container cp = getContentPane();
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);
codeProcessingLevel.setBounds(30, 25, getWidth() - 60, 125);
add(codeProcessingLevel);
processAllCheckbox.setBounds(50, 150, getWidth()-100, 25);
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.setActionCommand("OK");
okButton.setBounds(50, 200, 75, 25);
cancelButton.setBounds(145, 200, 75, 25);
cp.add(okButton);
@@ -134,11 +112,9 @@ Container cp = getContentPane();
@Override
public void setVisible(boolean b) {
if(b){
ok=false;
if (b) {
ok = false;
}
super.setVisible(b);
}
}

View File

@@ -27,6 +27,8 @@ import com.jpexs.asdec.helpers.Highlighting;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MethodBody implements Cloneable {
@@ -47,15 +49,16 @@ public class MethodBody implements Cloneable {
s += "\r\nCode:\r\n" + code.toString();
return s;
}
public int removeDeadCode(ConstantPool constants){
return code.removeDeadCode(constants,this);
public int removeDeadCode(ConstantPool constants) {
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);
}
@@ -85,19 +88,18 @@ public class MethodBody implements Cloneable {
return ret;
}
/*public String toString(boolean pcode, boolean isStatic, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack<TreeItem> scopeStack, boolean isStaticInitializer) {
return toString(pcode, isStatic, classIndex, abc, constants, method_info, scopeStack, isStaticInitializer,false);
}*/
public String toString(boolean pcode, boolean isStatic, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack<TreeItem> scopeStack, boolean isStaticInitializer, boolean hilight, List<String> fullyQualifiedNames, Traits initTraits) {
String s = "";
//s+="method_info="+method_info+" max_stack="+max_stack+" max_regs="+max_regs+" scope_depth="+scope_depth+" max_scope="+max_scope;
//s+="\r\nCode:\r\n"+
if (pcode) {
s += code.toASMSource(constants, this);
} else {
AVM2Code deobfuscated = null;
deobfuscated = code.deepCopy();
deobfuscated.markMappedOffsets();
deobfuscated.removeTraps(constants, this);
deobfuscated.restoreControlFlow(constants, this);
try {
s += code.toSource(isStatic, classIndex, abc, constants, method_info, this, hilight, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits);
s += deobfuscated.toSource(isStatic, classIndex, abc, constants, method_info, this, hilight, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits);
s = s.trim();
if (hilight) {
s = Highlighting.hilighMethod(s, this.method_info);
@@ -106,12 +108,6 @@ public class MethodBody implements Cloneable {
s = "//error:" + ex.toString();
}
}
//s+="----------- ORIGINAL ------------\r\n";
//s+=code.toString(constants);
/*s+="Exceptions:";
for(int i=0;i<exceptions.length;i++){
s+="\r\n"+exceptions[i].toString(constants);
}*/
return s;
}

View File

@@ -62,6 +62,7 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -226,7 +227,7 @@ public class MainFrame extends JFrame implements ActionListener {
JMenuItem miDeobfuscation = new JMenuItem("Deobfuscation...");
JMenuItem miDeobfuscation = new JMenuItem("PCode deobfuscation...");
miDeobfuscation.setActionCommand("DEOBFUSCATE");
miDeobfuscation.addActionListener(this);
@@ -263,11 +264,11 @@ public class MainFrame extends JFrame implements ActionListener {
miControlFlowAll.addActionListener(this);
//menuDeobfuscation.add(miSubLimiter);
//menuDeobfuscation.add(miDeobfuscate);
menuDeobfuscation.add(miDeobfuscation);
/*menuDeobfuscation.add(miDeobfuscate);
menuDeobfuscation.addSeparator();
menuDeobfuscation.addSeparator();*/
menuDeobfuscation.add(miRenameIdentifiers);
menuDeobfuscation.add(miRemoveDeadCode);
/*menuDeobfuscation.add(miRemoveDeadCode);
menuDeobfuscation.add(miRemoveDeadCodeAll);
menuDeobfuscation.add(miTraps);
menuDeobfuscation.add(miTrapsAll);
@@ -282,7 +283,7 @@ public class MainFrame extends JFrame implements ActionListener {
menuTools.add(miProxy);
//menuTools.add(menuDeobfuscation);
menuTools.add(miDeobfuscation);
menuTools.add(menuDeobfuscation);
menuBar.add(menuTools);
JMenu menuHelp = new JMenu("Help");
@@ -852,8 +853,9 @@ public class MainFrame extends JFrame implements ActionListener {
@Override
protected Object doInBackground() throws Exception {
int cnt = 0;
HashMap<String,String> namesMap=new HashMap<String,String>();
for (DoABCTag tag : abcPanel.list) {
cnt += tag.abc.deobfuscateIdentifiers();
cnt += tag.abc.deobfuscateIdentifiers(namesMap);
}
Main.stopWork();
JOptionPane.showMessageDialog(null, "Identifiers renamed: " + cnt);
@@ -878,9 +880,6 @@ public class MainFrame extends JFrame implements ActionListener {
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) {