AS3: Deobfuscation of identifier is now optional, acessed via Tools/Deobfuscation menu

This commit is contained in:
Jindra Pet��k
2012-12-24 10:06:14 +01:00
parent 96d91ceb10
commit 961166a3db
2 changed files with 102 additions and 45 deletions
+72 -41
View File
@@ -67,6 +67,7 @@ import com.jpexs.asdec.abc.usages.TypeNameMultinameUsage;
import com.jpexs.asdec.helpers.Helper; import com.jpexs.asdec.helpers.Helper;
import com.jpexs.asdec.helpers.Highlighting; import com.jpexs.asdec.helpers.Highlighting;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.regex.Pattern;
public class ABC { public class ABC {
@@ -83,34 +84,26 @@ public class ABC {
public long stringOffsets[]; public long stringOffsets[];
public static String IDENT_STRING = " "; public static String IDENT_STRING = " ";
public static final int MINORwithDECIMAL = 17; public static final int MINORwithDECIMAL = 17;
private int fixNamesStrategy = 0;
private final int STRATEGY_FIX_NAMES = 1;
private final int STRATEGY_IGNORE = 2;
public static final boolean AUTOINIT_STATIC_VARIABLES = false; public static final boolean AUTOINIT_STATIC_VARIABLES = false;
private void fixNameWithStrategy(int index) { public int deobfuscateIdentifiers()
if (fixNamesStrategy == 0) { {
if (!isValidName(index, false)) { int ret=0;
int val = JOptionPane.showOptionDialog(null, "Decompiler found unusual name '" + constants.constant_string[index] + "' for a variable/class which can cause problems when decompiling.\r\nDo you want the decompiler to fix it?", "Decompilation", 0, JOptionPane.INFORMATION_MESSAGE, null, new String[]{"Yes", "Yes to all", "No", "No to all"}, "Yes to all"); for(int i=1;i<constants.constant_multiname.length;i++)
if (val == JOptionPane.CLOSED_OPTION) { {
val = 2; //NO if(deobfuscateName(constants.constant_multiname[i].name_index))
} {
if ((val == 0) || (val == 1)) //YES,YES TO ALL ret++;
{
isValidName(index, true);
}
if (val == 1) //YES TO ALL
{
fixNamesStrategy = STRATEGY_FIX_NAMES;
}
if (val == 3) { //NO TO ALL
fixNamesStrategy = STRATEGY_IGNORE;
}
} }
} else if (fixNamesStrategy == STRATEGY_FIX_NAMES) {
isValidName(index, true);
} else if (fixNamesStrategy == STRATEGY_IGNORE) {
} }
for(int i=1;i<constants.constant_namespace.length;i++)
{
if(deobfuscateNameSpace(constants.constant_namespace[i].name_index))
{
ret++;
}
}
return ret;
} }
public ABC(InputStream is) throws IOException { public ABC(InputStream is) throws IOException {
@@ -167,7 +160,6 @@ public class ABC {
constants.constant_namespace = new Namespace[constant_namespace_pool_count]; constants.constant_namespace = new Namespace[constant_namespace_pool_count];
for (int i = 1; i < constant_namespace_pool_count; i++) { //index 0 not used. Values 1..n-1 for (int i = 1; i < constant_namespace_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_namespace[i] = ais.readNamespace(); constants.constant_namespace[i] = ais.readNamespace();
fixNameWithStrategy(constants.constant_namespace[i].name_index);
} }
//constant namespace set //constant namespace set
@@ -191,7 +183,6 @@ public class ABC {
constants.constant_multiname = new Multiname[constant_multiname_pool_count]; constants.constant_multiname = new Multiname[constant_multiname_pool_count];
for (int i = 1; i < constant_multiname_pool_count; i++) { //index 0 not used. Values 1..n-1 for (int i = 1; i < constant_multiname_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_multiname[i] = ais.readMultiname(); constants.constant_multiname[i] = ais.readMultiname();
fixNameWithStrategy(constants.constant_multiname[i].name_index);
} }
@@ -801,12 +792,15 @@ public class ABC {
"return", "super", "switch", "this", "throw", "true", "try", "typeof", "use", "var", /*"void",*/ "while", "return", "super", "switch", "this", "throw", "true", "try", "typeof", "use", "var", /*"void",*/ "while",
"with", "dynamic", "default", "final", "in"}; "with", "dynamic", "default", "final", "in"};
public int unknownCount = 0; public int unknownCount = 0;
public static final String validFirstCharacters="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
public static final String validNextCharacters=validFirstCharacters+"0123456789";
public boolean isValidName(int index, boolean autoFix) { public boolean deobfuscateNameSpace(int strIndex) {
if (index <= 0) { if (strIndex <= 0) {
return true; return false;
} }
String s = constants.constant_string[index]; String s = constants.constant_string[strIndex];
boolean isValid = true; boolean isValid = true;
boolean isReserved = false; boolean isReserved = false;
for (String rw : reservedWords) { for (String rw : reservedWords) {
@@ -815,6 +809,45 @@ public class ABC {
isReserved = true; isReserved = true;
break; break;
} }
}
if (isValid) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) > 127) {
isValid = false;
break;
}
}
}
if (!isValid) {
if (isReserved) {
constants.constant_string[strIndex] = "name_" + s.replace(" ", "_");
} else {
unknownCount++;
constants.constant_string[strIndex] = "_name" + unknownCount;
}
}
return !isValid;
}
public boolean deobfuscateName(int strIndex) {
if (strIndex <= 0) {
return false;
}
String s = constants.constant_string[strIndex];
boolean isValid = true;
boolean isReserved = false;
for (String rw : reservedWords) {
if (rw.equals(s.trim())) {
isValid = false;
isReserved = true;
break;
}
}
Pattern pat=Pattern.compile("^["+Pattern.quote(validFirstCharacters) +"]"+"["+Pattern.quote(validFirstCharacters+validNextCharacters) +"]*$");
if(!pat.matcher(s).matches()){
isValid=false;
} }
if (isValid) { if (isValid) {
for (int i = 0; i < s.length(); i++) { for (int i = 0; i < s.length(); i++) {
@@ -825,17 +858,15 @@ public class ABC {
} }
} }
if (!isValid) { if (!isValid) {
if (autoFix) { if (isReserved) {
if (isReserved) { constants.constant_string[strIndex] = "name_" + s.replace(" ", "_");
constants.constant_string[index] = "name_" + s.replace(" ", "_"); } else {
} else { unknownCount++;
unknownCount++; constants.constant_string[strIndex] = "_name" + unknownCount;
constants.constant_string[index] = "_name" + unknownCount; }
}
}
} }
return isValid; return !isValid;
} }
private void checkMultinameUsedInMethod(int multinameIndex, int methodInfo, List<MultinameUsage> ret, int classIndex, int traitIndex, boolean isStatic, boolean isInitializer,Traits traits,int parentTraitIndex) { private void checkMultinameUsedInMethod(int multinameIndex, int methodInfo, List<MultinameUsage> ret, int classIndex, int traitIndex, boolean isStatic, boolean isInitializer,Traits traits,int parentTraitIndex) {
@@ -152,7 +152,7 @@ public class MainFrame extends JFrame implements ActionListener, ItemListener {
//DefaultTableColumnModel colModel = (DefaultTableColumnModel) constantTable.getColumnModel(); //DefaultTableColumnModel colModel = (DefaultTableColumnModel) constantTable.getColumnModel();
//colModel.getColumn(0).setMaxWidth(50); //colModel.getColumn(0).setMaxWidth(50);
} }
public void switchAbc(int index) { public void switchAbc(int index) {
listIndex = index; listIndex = index;
this.abc = list.get(listIndex).abc; this.abc = list.get(listIndex).abc;
@@ -291,12 +291,21 @@ public class MainFrame extends JFrame implements ActionListener, ItemListener {
menuFile.add(miClose); menuFile.add(miClose);
menuBar.add(menuFile); menuBar.add(menuFile);
JMenu menuOptions = new JMenu("Options"); JMenu menuDeobfuscation = new JMenu("Deobfuscation");
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);
menuOptions.add(miSubLimiter);
menuBar.add(menuOptions); JMenuItem miRenameIdentifiers=new JMenuItem("Rename identifiers");
miRenameIdentifiers.setActionCommand("RENAMEIDENTIFIERS");
miRenameIdentifiers.addActionListener(this);
menuDeobfuscation.add(miSubLimiter);
menuDeobfuscation.add(miRenameIdentifiers);
//menuBar.add(menuOptions);
JMenu menuTools = new JMenu("Tools"); JMenu menuTools = new JMenu("Tools");
JMenuItem miProxy = new JMenuItem("Proxy"); JMenuItem miProxy = new JMenuItem("Proxy");
@@ -304,6 +313,8 @@ public class MainFrame extends JFrame implements ActionListener, ItemListener {
miProxy.setIcon(new ImageIcon(View.loadImage("com/jpexs/asdec/gui/graphics/proxy16.png"))); miProxy.setIcon(new ImageIcon(View.loadImage("com/jpexs/asdec/gui/graphics/proxy16.png")));
miProxy.addActionListener(this); miProxy.addActionListener(this);
menuTools.add(miProxy); menuTools.add(miProxy);
menuTools.add(menuDeobfuscation);
menuBar.add(menuTools); menuBar.add(menuTools);
JMenu menuHelp = new JMenu("Help"); JMenu menuHelp = new JMenu("Help");
@@ -420,6 +431,21 @@ public class MainFrame extends JFrame implements ActionListener, ItemListener {
} }
} }
if(e.getActionCommand().equals("RENAMEIDENTIFIERS")){
int pocet=0;
Main.startWork("Renaming identifiers...");
for (DoABCTag tag : list) {
pocet+=tag.abc.deobfuscateIdentifiers();
}
JOptionPane.showMessageDialog(null, "Identifiers renamed: "+pocet);
reload();
Main.stopWork();
}
}
public void reload(){
switchAbc(listIndex);
} }
public void itemStateChanged(ItemEvent e) { public void itemStateChanged(ItemEvent e) {