Issues #243,#326: improved deobfuscation

code formatting
This commit is contained in:
Jindra Pet��k
2013-08-11 09:44:33 +02:00
parent 089898980f
commit af5038287a
14 changed files with 164 additions and 46 deletions
@@ -119,13 +119,13 @@ public class Configuration {
}
public static Object setConfig(String cfg, Object value) {
if(cfg.equals("paralelSpeedUp")){
if (cfg.equals("paralelSpeedUp")) {
cfg = "parallelSpeedUp";
}
return config.put(cfg, value);
}
public static void unsetConfig(String cfg){
public static void unsetConfig(String cfg) {
config.remove(cfg);
}
@@ -146,7 +146,7 @@ public class Configuration {
if (replacementsFile != null) {
loadReplacements(replacementsFile);
}
if(containsConfig("paralelSpeedUp")){
if (containsConfig("paralelSpeedUp")) {
setConfig("parallelSpeedUp", getConfig("paralelSpeedUp"));
unsetConfig("paralelSpeedUp");
}
@@ -16,8 +16,10 @@
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.abc.avm2.model.NotCompileTimeAVM2Item;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionGraphSource;
import com.jpexs.decompiler.flash.action.StoreTypeAction;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.special.ActionEnd;
@@ -738,7 +740,7 @@ public class SWFInputStream extends InputStream {
method = 2;
goesPrev = readActionListAtPos(true, localData, stack, cpool, sis, rri, ip, retdups, ip);
}*/
goesPrev = readActionListAtPos(listeners, new ArrayList<GraphTargetItem>(), new HashMap<Long, List<GraphSourceItemContainer>>(), address, containerSWFOffset, localData, stack, cpool, sis, rri, ip, retdups, ip, endip, path, new HashMap<Integer, Integer>());
goesPrev = readActionListAtPos(listeners, new ArrayList<GraphTargetItem>(), new HashMap<Long, List<GraphSourceItemContainer>>(), address, containerSWFOffset, localData, stack, cpool, sis, rri, ip, retdups, ip, endip, path, new HashMap<Integer, Integer>(), false, new HashMap<Integer, HashMap<String, GraphTargetItem>>());
if (goesPrev) {
} else {
@@ -797,7 +799,7 @@ public class SWFInputStream extends InputStream {
}
@SuppressWarnings("unchecked")
private static boolean readActionListAtPos(List<DisassemblyListener> listeners, List<GraphTargetItem> output, HashMap<Long, List<GraphSourceItemContainer>> containers, long address, long containerSWFOffset, List<Object> localData, Stack<GraphTargetItem> stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List<Action> ret, int startIp, int endip, String path, Map<Integer, Integer> visited) throws IOException {
private static boolean readActionListAtPos(List<DisassemblyListener> listeners, List<GraphTargetItem> output, HashMap<Long, List<GraphSourceItemContainer>> containers, long address, long containerSWFOffset, List<Object> localData, Stack<GraphTargetItem> stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List<Action> ret, int startIp, int endip, String path, Map<Integer, Integer> visited, boolean indeterminate, Map<Integer, HashMap<String, GraphTargetItem>> decisionStates) throws IOException {
boolean debugMode = false;
boolean decideBranch = false;
@@ -907,6 +909,12 @@ public class SWFInputStream extends InputStream {
ActionIf aif = null;
boolean goaif = false;
if (!a.isIgnored()) {
String varname = null;
if (a instanceof StoreTypeAction) {
StoreTypeAction sta = (StoreTypeAction) a;
varname = sta.getVariableName(stack, cpool);
}
try {
if (a instanceof ActionIf) {
aif = (ActionIf) a;
@@ -983,6 +991,14 @@ public class SWFInputStream extends InputStream {
log.log(Level.SEVERE, "Disassembly exception", ex);
break;
}
HashMap<String, GraphTargetItem> vars = (HashMap<String, GraphTargetItem>) localData.get(1);
if (varname != null) {
GraphTargetItem varval = vars.get(varname);
if (varval != null && varval.isCompileTime() && indeterminate) {
vars.put(varname, new NotCompileTimeAVM2Item(null, varval));
}
}
}
int nopos = -1;
for (int i = 0; i < actionLen; i++) {
@@ -1023,7 +1039,7 @@ public class SWFInputStream extends InputStream {
} else {
localData2 = localData;
}
readActionListAtPos(listeners, output2, containers, address, containerSWFOffset, localData2, new Stack<GraphTargetItem>(), cpool, sis, rri, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited);
readActionListAtPos(listeners, output2, containers, address, containerSWFOffset, localData2, new Stack<GraphTargetItem>(), cpool, sis, rri, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates);
output2s.add(output2);
endAddr += size;
}
@@ -1050,13 +1066,34 @@ public class SWFInputStream extends InputStream {
rri.setPos(ip);
filePos = rri.getPos();
if (goaif) {
if (aif.ignoreUsed && aif.jumpUsed) {
break;
}
aif.ignoreUsed = true;
aif.jumpUsed = true;
indeterminate = true;
if (curVisited > 1) {
HashMap<String, GraphTargetItem> vars = (HashMap<String, GraphTargetItem>) localData.get(1);
boolean stateChanged = false;
if (decisionStates.containsKey(ip)) {
HashMap<String, GraphTargetItem> oldstate = decisionStates.get(ip);
if (oldstate.size() != vars.size()) {
stateChanged = true;
} else {
for (String k : vars.keySet()) {
if (!oldstate.containsKey(k)) {
stateChanged = true;
break;
}
if (!vars.get(k).isCompileTime() && oldstate.get(k).isCompileTime()) {
stateChanged = true;
break;
}
}
}
}
HashMap<String, GraphTargetItem> curstate = new HashMap<String, GraphTargetItem>();
curstate.putAll(vars);
decisionStates.put(ip, curstate);
if ((!stateChanged) && curVisited > 1) {
List<Integer> branches = new ArrayList<>();
branches.add(rri.getPos() + aif.getJumpOffset());
branches.add(rri.getPos());
@@ -1078,7 +1115,7 @@ public class SWFInputStream extends InputStream {
int oldPos = rri.getPos();
@SuppressWarnings("unchecked")
Stack<GraphTargetItem> substack = (Stack<GraphTargetItem>) stack.clone();
if (readActionListAtPos(listeners, output, containers, address, containerSWFOffset, prepareLocalBranch(localData), substack, cpool, sis, rri, rri.getPos() + aif.getJumpOffset(), ret, startIp, endip, path, visited)) {
if (readActionListAtPos(listeners, output, containers, address, containerSWFOffset, prepareLocalBranch(localData), substack, cpool, sis, rri, rri.getPos() + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates)) {
retv = true;
}
rri.setPos(oldPos);
@@ -1197,7 +1234,7 @@ public class SWFInputStream extends InputStream {
if (tag == null) {
break;
}
if(!parallel){
if (!parallel) {
tags.add(tag);
}
if (Configuration.dump_tags && level == 0) {
@@ -456,7 +456,7 @@ public class SWFOutputStream extends OutputStream {
}
return nBits;
}
public static int getNeededBitsU(int first, int... params) {
int nBits = 0;
nBits = enlargeBitCountU(nBits, first);
@@ -507,7 +507,7 @@ public class SWFOutputStream extends OutputStream {
}
return currentBitCount;
}
public static int enlargeBitCountU(int currentBitCount, int value) {
int neededNew = getNeededBitsU(value);
if (neededNew > currentBitCount) {
@@ -2061,6 +2061,7 @@ public class AVM2Code implements Serializable {
public boolean jumpUsed = false;
public boolean skipUsed = false;
public Set<Integer> casesUsed = new HashSet<>();
HashMap<Integer, GraphTargetItem> registers = new HashMap<>();
}
private static int getMostCommonIp(AVM2GraphSource code, List<Integer> branches) {
@@ -2208,13 +2209,13 @@ public class AVM2Code implements Serializable {
}
@SuppressWarnings("unchecked")
private static int removeTraps(HashMap<Integer, List<Integer>> refs, boolean secondPass, boolean useVisited, List<Object> localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, AVM2GraphSource code, int ip, HashMap<Integer, Integer> visited, HashMap<Integer, HashMap<Integer, GraphTargetItem>> visitedStates, HashMap<GraphSourceItem, Decision> decisions, String path) {
private static int removeTraps(HashMap<Integer, List<Integer>> refs, boolean secondPass, boolean indeterminate, List<Object> localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, AVM2GraphSource code, int ip, HashMap<Integer, Integer> visited, HashMap<Integer, HashMap<Integer, GraphTargetItem>> visitedStates, HashMap<GraphSourceItem, Decision> decisions, String path) {
boolean debugMode = false;
int ret = 0;
iploop:
while ((ip > -1) && ip < code.size()) {
if (useVisited) {
if (false) { //useVisited) {
if (visited.containsKey(ip)) {
break;
}
@@ -2275,8 +2276,9 @@ public class AVM2Code implements Serializable {
ip++;
continue;
}
if (debugMode) {
System.out.println((useVisited ? "useV " : "") + (secondPass ? "secondPass " : "") + "Visit " + ip + ": " + ins + " stack:" + Highlighting.stripHilights(stack.toString()));
System.out.println((indeterminate ? "useV " : "") + (secondPass ? "secondPass " : "") + "Visit " + ip + ": " + ins + " stack:" + Highlighting.stripHilights(stack.toString()));
HashMap<Integer, GraphTargetItem> registers = (HashMap<Integer, GraphTargetItem>) localData.get(2);
System.out.print("Registers:");
for (int reg : registers.keySet()) {
@@ -2316,6 +2318,20 @@ public class AVM2Code implements Serializable {
}
if (ins instanceof AVM2Instruction) {
AVM2Instruction ains = (AVM2Instruction) ins;
if (ains.definition instanceof SetLocalTypeIns) {
SetLocalTypeIns slt = (SetLocalTypeIns) ains.definition;
int regId = slt.getRegisterId(ains);
if (indeterminate) {
HashMap<Integer, GraphTargetItem> registers = (HashMap<Integer, GraphTargetItem>) localData.get(2);
GraphTargetItem regVal = registers.get(regId);
if (regVal.isCompileTime()) {
registers.put(regId, new NotCompileTimeAVM2Item(null, regVal));
}
}
}
}
if (ins.isExit()) {
break;
@@ -2389,10 +2405,29 @@ public class AVM2Code implements Serializable {
} else {
decisions.put(ins, dec);
}
HashMap<Integer, GraphTargetItem> registers = (HashMap<Integer, GraphTargetItem>) localData.get(2);
boolean regChanged = false;
if (!dec.registers.isEmpty()) {
if (dec.registers.size() != registers.size()) {
regChanged = true;
} else {
for (int reg : registers.keySet()) {
if (!dec.registers.containsKey(reg)) {
regChanged = true;
break;
}
if (!registers.get(reg).isCompileTime() && dec.registers.get(reg).isCompileTime()) {
regChanged = true;
break;
}
}
}
}
dec.registers.putAll(registers);
dec.jumpUsed = true;
dec.skipUsed = true;
if ((!(top instanceof HasNextAVM2Item) && curVisited > 1) || (curVisited > 2)) {
if (!regChanged && ((!(top instanceof HasNextAVM2Item) && curVisited > 1) || (curVisited > 2))) {
for (int b : branches) {
int visc = 0;
if (visited.containsKey(b)) {
@@ -2405,12 +2440,13 @@ public class AVM2Code implements Serializable {
}
break;
}
indeterminate = true;
}
for (int b : branches) {
Stack<GraphTargetItem> brStack = (Stack<GraphTargetItem>) stack.clone();
if (b >= 0) { //useVisited || (!ins.isJump())
ret += removeTraps(refs, secondPass, false, prepareBranchLocalData(localData), brStack, output, code, b, visited, visitedStates, decisions, path);
ret += removeTraps(refs, secondPass, indeterminate, prepareBranchLocalData(localData), brStack, output, code, b, visited, visitedStates, decisions, path);
} else {
if (debugMode) {
System.out.println("Negative branch:" + b);
@@ -0,0 +1,30 @@
/*
* Copyright (C) 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.decompiler.flash.action;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public interface StoreTypeAction {
public String getVariableName(Stack<GraphTargetItem> stack, ConstantPool cpool);
}
@@ -17,6 +17,7 @@
package com.jpexs.decompiler.flash.action.swf4;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.StoreTypeAction;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.flash.action.model.DecrementActionItem;
import com.jpexs.decompiler.flash.action.model.GetVariableActionItem;
@@ -34,7 +35,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class ActionSetVariable extends Action {
public class ActionSetVariable extends Action implements StoreTypeAction {
public ActionSetVariable() {
super(0x1D, 0);
@@ -119,4 +120,12 @@ public class ActionSetVariable extends Action {
output.add(ret);
}
@Override
public String getVariableName(Stack<GraphTargetItem> stack, ConstantPool cpool) {
if (stack.size() < 2) {
return null;
}
return Highlighting.stripHilights(stack.get(stack.size() - 2).toStringNoQuotes(cpool));
}
}
@@ -19,6 +19,8 @@ package com.jpexs.decompiler.flash.action.swf5;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.StoreTypeAction;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.flash.action.model.DecrementActionItem;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.IncrementActionItem;
@@ -37,7 +39,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class ActionStoreRegister extends Action {
public class ActionStoreRegister extends Action implements StoreTypeAction {
public int registerNumber;
@@ -130,4 +132,9 @@ public class ActionStoreRegister extends Action {
}
stack.push(new StoreRegisterActionItem(this, rn, value, define));
}
@Override
public String getVariableName(Stack<GraphTargetItem> stack, ConstantPool cpool) {
return "__register" + registerNumber;
}
}
@@ -36,8 +36,8 @@ public abstract class AppDialog extends JDialog {
public String translate(String key) {
return resourceBundle.getString(key);
}
public void updateLanguage(){
public void updateLanguage() {
resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()));
}
}
@@ -33,8 +33,8 @@ public abstract class AppFrame extends JFrame {
public String translate(String key) {
return resourceBundle.getString(key);
}
public void updateLanguage(){
public void updateLanguage() {
resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()));
}
}
@@ -43,8 +43,8 @@ public class AppStrings {
ResourceBundle b = ResourceBundle.getBundle(bundle);
return b.getString(key);
}
public static void updateLanguage(){
public static void updateLanguage() {
resourceBundle = ResourceBundle.getBundle(getResourcePath(MainFrame.class));
}
}
@@ -2268,7 +2268,6 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
@Override
public void run() {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
if (abcPanel.search(txt, searchDialog.ignoreCaseCheckBox.isSelected(), searchDialog.regexpCheckBox.isSelected())) {
@@ -2279,7 +2278,7 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
}
}
});
}
}).start();
} else {
@@ -53,7 +53,7 @@ public class SelectLanguageDialog extends AppDialog implements ActionListener {
boolean found = false;
int enIndex = 0;
for (String code : languages) {
String name = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()), Locale.forLanguageTag(code.equals("en")?"":code)).getString("language");
String name = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()), Locale.forLanguageTag(code.equals("en") ? "" : code)).getString("language");
if (name.length() > 1) {
name = name.substring(0, 1).toUpperCase() + name.substring(1);
}
@@ -111,7 +111,7 @@ public class SelectLanguageDialog extends AppDialog implements ActionListener {
Locale.setDefault(Locale.forLanguageTag(newLanguage));
updateLanguage();
setVisible(false);
AppStrings.updateLanguage();
AppStrings.updateLanguage();
Main.reloadApp();
}
break;
@@ -38,23 +38,23 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail {
public JEditorPane slotConstEditor;
private ABC abc;
private TraitSlotConst trait;
private boolean showWarning=false;
private boolean showWarning = false;
public SlotConstTraitDetailPanel() {
slotConstEditor = new JEditorPane();
setLayout(new BorderLayout());
add(new JLabel(translate("abc.detail.slotconst.typevalue")), BorderLayout.NORTH);
add(new JScrollPane(slotConstEditor), BorderLayout.CENTER);
/*StyledDocument doc = warnLabel.getStyledDocument();
SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
doc.setParagraphAttributes(0, doc.getLength(), center, false);
warnLabel.setOpaque(false);
warnLabel.setFocusable(false);
//warnLabel.setWrapStyleWord(true);
//warnLabel.setLineWrap(true);
warnLabel.setFont(new JLabel().getFont().deriveFont(Font.BOLD));
add(warnLabel, BorderLayout.SOUTH);*/
SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
doc.setParagraphAttributes(0, doc.getLength(), center, false);
warnLabel.setOpaque(false);
warnLabel.setFocusable(false);
//warnLabel.setWrapStyleWord(true);
//warnLabel.setLineWrap(true);
warnLabel.setFont(new JLabel().getFont().deriveFont(Font.BOLD));
add(warnLabel, BorderLayout.SOUTH);*/
slotConstEditor.setContentType("text/flasm3_methodinfo");
Flasm3MethodInfoSyntaxKit sk = (Flasm3MethodInfoSyntaxKit) slotConstEditor.getEditorKit();
sk.deinstallComponent(slotConstEditor, "jsyntaxpane.components.LineNumbersRuler");
@@ -77,7 +77,7 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail {
s = typeStr + valueStr;
showWarning = trait.isConst()||isStatic;
showWarning = trait.isConst() || isStatic;
//warnLabel.setVisible(trait.isConst() || isStatic);
slotConstEditor.setText(s);
}
@@ -97,7 +97,7 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail {
@Override
public void setEditMode(boolean val) {
if(val){
if (val) {
JOptionPane.showMessageDialog(null, translate("warning.initializers"), translate("message.warning"), JOptionPane.WARNING_MESSAGE);
}
slotConstEditor.setEditable(val);
@@ -274,7 +274,7 @@ public class PlaceObject3Tag extends CharacterIdTag implements Container, PlaceO
/**
* Constructor
*
* @param swf
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos