AS3 deobfuscation - remove dead code

This commit is contained in:
Jindra Pet��k
2013-01-27 09:52:49 +01:00
parent 030c7cf657
commit da00857837
6 changed files with 120 additions and 0 deletions
+8
View File
@@ -70,6 +70,14 @@ public class ABC {
}
}
public int removeDeadCode() {
int rem=0;
for(MethodBody body:bodies){
rem+=body.removeDeadCode();
}
return rem;
}
public int deobfuscateIdentifiers() {
int ret = 0;
for (int i = 1; i < instance_info.length; i++) {
@@ -2463,4 +2463,70 @@ public class AVM2Code {
}
return stats;
}
private void visitCode(int ip, boolean visited[]) {
while ((ip < visited.length) && (!visited[ip])) {
visited[ip] = true;
AVM2Instruction ins = code.get(ip);
if (ins.definition instanceof LookupSwitchIns) {
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) {
try {
ip = adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
continue;
} catch (ConvertException ex) {
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (ins.definition instanceof IfTypeIns) {
try {
visitCode(adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]), visited);
} catch (ConvertException ex) {
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
}
}
ip++;
};
}
public int removeDeadCode(MethodBody body) {
boolean visited[] = new boolean[code.size()];
for (int i = 0; i < visited.length; i++) {
visited[i] = false;
}
visitCode(0, visited);
for (ABCException e : body.exceptions) {
try {
visitCode(adr2pos(e.start), visited);
visitCode(adr2pos(e.target), visited);
} catch (ConvertException ex) {
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, null, ex);
}
}
int cnt = 0;
for (int i = visited.length - 1; i >= 0; i--) {
if (!visited[i]) {
removeInstruction(i, body);
cnt++;
}
}
for (int i = code.size() - 1; i >= 0; i--) {
AVM2Instruction ins = code.get(i);
if (ins.definition instanceof JumpIns) {
if (ins.operands[0] == 0) {
removeInstruction(i, body);
cnt++;
}
}
}
return cnt;
}
}
@@ -117,6 +117,7 @@ public class DetailPanel extends JPanel implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("EDITDETAIL")) {
setEditMode(true);
methodTraitPanel.methodCodePanel.focusEditor();
}
if (e.getActionCommand().equals("CANCELDETAIL")) {
setEditMode(false);
@@ -36,6 +36,10 @@ public class MethodCodePanel extends JPanel implements ActionListener {
private ASMSourceEditorPane sourceTextArea;
public JPanel buttonsPanel;
public void focusEditor(){
sourceTextArea.requestFocusInWindow();
}
public void setIgnoreCarret(boolean ignoreCarret) {
sourceTextArea.setIgnoreCarret(ignoreCarret);
}
@@ -47,6 +47,10 @@ public class MethodBody implements Cloneable {
s += "\r\nCode:\r\n" + code.toString();
return s;
}
public int removeDeadCode(){
return code.removeDeadCode(this);
}
public HashMap<Integer, String> getLocalRegNames(ABC abc) {
HashMap<Integer, String> ret = new HashMap<Integer, String>();
@@ -228,9 +228,19 @@ public class MainFrame extends JFrame implements ActionListener {
miRenameIdentifiers.setActionCommand("RENAMEIDENTIFIERS");
miRenameIdentifiers.addActionListener(this);
JMenuItem miRemoveDeadCode = new JMenuItem("Remove dead code");
miRemoveDeadCode.setActionCommand("REMOVEDEADCODE");
miRemoveDeadCode.addActionListener(this);
JMenuItem miRemoveDeadCodeAll = new JMenuItem("Remove all dead code");
miRemoveDeadCodeAll.setActionCommand("REMOVEDEADCODEALL");
miRemoveDeadCodeAll.addActionListener(this);
menuDeobfuscation.add(miSubLimiter);
menuDeobfuscation.add(miRenameIdentifiers);
menuDeobfuscation.add(miRemoveDeadCode);
menuDeobfuscation.add(miRemoveDeadCodeAll);
JMenu menuTools = new JMenu("Tools");
@@ -713,6 +723,33 @@ public class MainFrame extends JFrame implements ActionListener {
JOptionPane.showMessageDialog(null, "No new version available.");
}
}
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();
}
}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;
}
}.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) {