mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-12 09:18:08 +00:00
action deobfuscator improved again
This commit is contained in:
@@ -323,6 +323,10 @@ public class ActionList extends ArrayList<Action> {
|
||||
return idx == -1 ? null : get(idx);
|
||||
}
|
||||
|
||||
public int getIndexByAction(Action action) {
|
||||
return getIndexByAddress(action.getAddress());
|
||||
}
|
||||
|
||||
public int getIndexByAddress(long address) {
|
||||
int min = 0;
|
||||
int max = size() - 1;
|
||||
@@ -361,6 +365,108 @@ public class ActionList extends ArrayList<Action> {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public List<Action> getUnreachableActions() {
|
||||
int[] isReachable = getUnreachableActionsMap(-1, 0);
|
||||
List<Action> unreachableActions = new ArrayList<>();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
if (isReachable[i] == 0) {
|
||||
unreachableActions.add(get(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (unreachableActions.isEmpty()) {
|
||||
unreachableActions = null;
|
||||
}
|
||||
|
||||
return unreachableActions;
|
||||
}
|
||||
|
||||
public List<Action> getUnreachableActions(int jumpIndex, int jumpTargetIndex) {
|
||||
int[] isReachable = getUnreachableActionsMap(jumpIndex, jumpTargetIndex);
|
||||
List<Action> unreachableActions = new ArrayList<>();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
if (isReachable[i] == 0) {
|
||||
unreachableActions.add(get(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (unreachableActions.isEmpty()) {
|
||||
unreachableActions = null;
|
||||
}
|
||||
|
||||
return unreachableActions;
|
||||
}
|
||||
|
||||
private int[] getUnreachableActionsMap(int jumpIndex, int jumpTargetIndex) {
|
||||
int size = size();
|
||||
|
||||
// one item for each action. 1 means reachable, 2 means reachable and processed
|
||||
int[] isReachable = new int[size];
|
||||
isReachable[0] = 1;
|
||||
boolean modified = true;
|
||||
while (modified) {
|
||||
modified = false;
|
||||
for (int i = 0; i < size; i++) {
|
||||
Action action = get(i);
|
||||
if (isReachable[i] == 1) {
|
||||
isReachable[i] = 2;
|
||||
modified = true;
|
||||
|
||||
if (i == jumpIndex) {
|
||||
if (isReachable[jumpTargetIndex] == 0) {
|
||||
isReachable[jumpTargetIndex] = 1;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!action.isExit() && !(action instanceof ActionJump) && i != size - 1) {
|
||||
if (isReachable[i + 1] == 0) {
|
||||
isReachable[i + 1] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (action instanceof ActionJump) {
|
||||
ActionJump aJump = (ActionJump) action;
|
||||
long ref = aJump.getAddress() + aJump.getTotalActionLength() + aJump.getJumpOffset();
|
||||
int targetIndex = getIndexByAddress(ref);
|
||||
if (targetIndex != -1 && isReachable[targetIndex] == 0) {
|
||||
isReachable[targetIndex] = 1;
|
||||
}
|
||||
} else if (action instanceof ActionIf) {
|
||||
ActionIf aIf = (ActionIf) action;
|
||||
long ref = aIf.getAddress() + aIf.getTotalActionLength() + aIf.getJumpOffset();
|
||||
int targetIndex = getIndexByAddress(ref);
|
||||
if (targetIndex != -1 && isReachable[targetIndex] == 0) {
|
||||
isReachable[targetIndex] = 1;
|
||||
}
|
||||
} else if (action instanceof ActionStore) {
|
||||
ActionStore aStore = (ActionStore) action;
|
||||
int storeSize = aStore.getStoreSize();
|
||||
if (size > i + storeSize) {
|
||||
int targetIndex = i + storeSize;
|
||||
if (isReachable[targetIndex] == 0) {
|
||||
isReachable[targetIndex] = 1;
|
||||
}
|
||||
}
|
||||
} else if (action instanceof GraphSourceItemContainer) {
|
||||
GraphSourceItemContainer container = (GraphSourceItemContainer) action;
|
||||
long ref = action.getAddress() + action.getTotalActionLength();
|
||||
for (Long containerSize : container.getContainerSizes()) {
|
||||
ref += containerSize;
|
||||
int targetIndex = getIndexByAddress(ref);
|
||||
if (targetIndex != -1 && isReachable[targetIndex] == 0) {
|
||||
isReachable[targetIndex] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isReachable;
|
||||
}
|
||||
|
||||
public void saveToFile(String fileName) {
|
||||
File file = new File(fileName);
|
||||
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(file))) {
|
||||
|
||||
@@ -620,7 +620,7 @@ public class ActionListReader {
|
||||
getJumps(actions, jumps);
|
||||
|
||||
for (Action actionToRemove : actionsToRemove) {
|
||||
int index = actions.indexOf(actionToRemove);
|
||||
int index = actions.getIndexByAction(actionToRemove);
|
||||
Action prevAction = index > 0 ? actions.get(index - 1) : null;
|
||||
Action nextAction = index + 1 < actions.size() ? actions.get(index + 1) : null;
|
||||
for (Action a : containerLastActions.keySet()) {
|
||||
|
||||
@@ -170,6 +170,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple {
|
||||
if (!result.stack.isEmpty()) {
|
||||
newIstructionCount++;
|
||||
}
|
||||
|
||||
newIstructionCount += 2 * result.variables.size();
|
||||
|
||||
boolean allValueValid = true;
|
||||
@@ -180,7 +181,9 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple {
|
||||
}
|
||||
}
|
||||
|
||||
if (allValueValid && newIstructionCount * 2 < result.instructionsProcessed) {
|
||||
int unreachableCount = actions.getUnreachableActions(i, result.idx).size();
|
||||
|
||||
if (allValueValid && newIstructionCount + 2 < unreachableCount) {
|
||||
Action target = actions.get(result.idx);
|
||||
Action prevAction = actions.get(i);
|
||||
|
||||
@@ -415,7 +418,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple {
|
||||
if (action instanceof ActionJump) {
|
||||
ActionJump jump = (ActionJump) action;
|
||||
long address = jump.getAddress() + jump.getTotalActionLength() + jump.getJumpOffset();
|
||||
idx = actions.indexOf(actions.getByAddress(address));
|
||||
idx = actions.getIndexByAddress(address);
|
||||
if (idx == -1) {
|
||||
throw new TranslateException("Jump target not found: " + address);
|
||||
}
|
||||
@@ -429,7 +432,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple {
|
||||
|
||||
if (EcmaScript.toBoolean(stack.pop().getResult())) {
|
||||
long address = aif.getAddress() + aif.getTotalActionLength() + aif.getJumpOffset();
|
||||
idx = actions.indexOf(actions.getByAddress(address));
|
||||
idx = actions.getIndexByAddress(address);
|
||||
if (idx == -1) {
|
||||
throw new TranslateException("If target not found: " + address);
|
||||
}
|
||||
@@ -438,7 +441,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple {
|
||||
|
||||
if (action instanceof ActionDefineFunction) {
|
||||
List<Action> lastActions = actions.getContainerLastActions(action);
|
||||
int lastActionIdx = actions.indexOf(lastActions.get(0));
|
||||
int lastActionIdx = actions.getIndexByAction(lastActions.get(0));
|
||||
idx = lastActionIdx != -1 ? lastActionIdx + 1 : -1;
|
||||
}
|
||||
|
||||
@@ -495,7 +498,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple {
|
||||
|
||||
ExecutionResult result = new ExecutionResult();
|
||||
List<Action> lastActions = actions.getContainerLastActions(action);
|
||||
int lastActionIdx = actions.indexOf(lastActions.get(0));
|
||||
int lastActionIdx = actions.getIndexByAction(lastActions.get(0));
|
||||
executeActions(actions, i + 1, lastActionIdx, null, result, null);
|
||||
if (result.resultValue != null) {
|
||||
results.put(def.functionName, result.resultValue);
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.ActionLocalData;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionStore;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionAdd;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionAnd;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionAsciiToChar;
|
||||
@@ -68,14 +67,11 @@ import com.jpexs.decompiler.flash.action.swf6.ActionStringGreater;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -157,12 +153,10 @@ public class ActionDeobfuscatorSimple implements SWFDecompilerListener {
|
||||
executeActions(actions, i, actions.size() - 1, result);
|
||||
|
||||
if (result.idx != -1) {
|
||||
int newIstructionCount = 1; // jump
|
||||
if (!result.stack.isEmpty()) {
|
||||
newIstructionCount += result.stack.size();
|
||||
}
|
||||
int newIstructionCount = 1 /*jump */ + result.stack.size();
|
||||
int unreachableCount = actions.getUnreachableActions(i, result.idx).size();
|
||||
|
||||
if (newIstructionCount < result.instructionsProcessed) {
|
||||
if (newIstructionCount < unreachableCount) {
|
||||
Action target = actions.get(result.idx);
|
||||
Action prevAction = actions.get(i);
|
||||
|
||||
@@ -206,90 +200,12 @@ public class ActionDeobfuscatorSimple implements SWFDecompilerListener {
|
||||
}
|
||||
|
||||
protected boolean removeUnreachableActions(ActionList actions) {
|
||||
Set<Action> reachableActions = new HashSet<>();
|
||||
Set<Action> processedActions = new HashSet<>();
|
||||
reachableActions.add(actions.get(0));
|
||||
boolean modified = true;
|
||||
while (modified) {
|
||||
modified = false;
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Action action = actions.get(i);
|
||||
if (reachableActions.contains(action) && !processedActions.contains(action)) {
|
||||
if (!action.isExit() && !(action instanceof ActionJump) && i != actions.size() - 1) {
|
||||
Action next = actions.get(i + 1);
|
||||
if (!reachableActions.contains(next)) {
|
||||
reachableActions.add(next);
|
||||
}
|
||||
}
|
||||
|
||||
if (action instanceof ActionJump) {
|
||||
ActionJump aJump = (ActionJump) action;
|
||||
long ref = aJump.getAddress() + aJump.getTotalActionLength() + aJump.getJumpOffset();
|
||||
Action target = actions.getByAddress(ref);
|
||||
if (target != null && !reachableActions.contains(target)) {
|
||||
reachableActions.add(target);
|
||||
}
|
||||
} else if (action instanceof ActionIf) {
|
||||
ActionIf aIf = (ActionIf) action;
|
||||
long ref = aIf.getAddress() + aIf.getTotalActionLength() + aIf.getJumpOffset();
|
||||
Action target = actions.getByAddress(ref);
|
||||
if (target != null && !reachableActions.contains(target)) {
|
||||
reachableActions.add(target);
|
||||
}
|
||||
} else if (action instanceof ActionStore) {
|
||||
ActionStore aStore = (ActionStore) action;
|
||||
int storeSize = aStore.getStoreSize();
|
||||
if (actions.size() > i + storeSize) {
|
||||
Action target = actions.get(i + storeSize);
|
||||
if (!reachableActions.contains(target)) {
|
||||
reachableActions.add(target);
|
||||
}
|
||||
}
|
||||
} else if (action instanceof GraphSourceItemContainer) {
|
||||
GraphSourceItemContainer container = (GraphSourceItemContainer) action;
|
||||
long ref = action.getAddress() + action.getTotalActionLength();
|
||||
for (Long size : container.getContainerSizes()) {
|
||||
ref += size;
|
||||
Action target = actions.getByAddress(ref);
|
||||
if (target != null && !reachableActions.contains(target)) {
|
||||
reachableActions.add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processedActions.add(action);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
List<Action> unreachableActions = actions.getUnreachableActions();
|
||||
if (unreachableActions != null) {
|
||||
actions.removeActions(unreachableActions);
|
||||
}
|
||||
|
||||
/*boolean result = false;
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
if (!reachableActions.contains(actions.get(i))) {
|
||||
actions.removeAction(i);
|
||||
i--;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;*/
|
||||
List<Action> actionsToRemove = null;
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Action action = actions.get(i);
|
||||
if (!reachableActions.contains(action)) {
|
||||
if (actionsToRemove == null) {
|
||||
actionsToRemove = new ArrayList<>();
|
||||
}
|
||||
|
||||
actionsToRemove.add(action);
|
||||
}
|
||||
}
|
||||
|
||||
if (actionsToRemove != null) {
|
||||
actions.removeActions(actionsToRemove);
|
||||
}
|
||||
|
||||
return actionsToRemove != null;
|
||||
return unreachableActions != null;
|
||||
}
|
||||
|
||||
protected boolean removeZeroJumpsOld(ActionList actions) {
|
||||
@@ -422,7 +338,7 @@ public class ActionDeobfuscatorSimple implements SWFDecompilerListener {
|
||||
if (action instanceof ActionJump) {
|
||||
ActionJump jump = (ActionJump) action;
|
||||
long address = jump.getAddress() + jump.getTotalActionLength() + jump.getJumpOffset();
|
||||
idx = actions.indexOf(actions.getByAddress(address));
|
||||
idx = actions.getIndexByAddress(address);
|
||||
if (idx == -1) {
|
||||
throw new TranslateException("Jump target not found: " + address);
|
||||
}
|
||||
@@ -436,7 +352,7 @@ public class ActionDeobfuscatorSimple implements SWFDecompilerListener {
|
||||
|
||||
if (EcmaScript.toBoolean(stack.pop().getResult())) {
|
||||
long address = aif.getAddress() + aif.getTotalActionLength() + aif.getJumpOffset();
|
||||
idx = actions.indexOf(actions.getByAddress(address));
|
||||
idx = actions.getIndexByAddress(address);
|
||||
if (idx == -1) {
|
||||
throw new TranslateException("If target not found: " + address);
|
||||
}
|
||||
|
||||
@@ -165,7 +165,8 @@ public class DirectValueActionItem extends ActionItem implements SimpleValue {
|
||||
if (value instanceof RegisterNumber) {
|
||||
return writer.append(((RegisterNumber) value).translate());
|
||||
}
|
||||
return writer.append(EcmaScript.toString(value, true));
|
||||
return writer.append(value.toString());
|
||||
//return writer.append(EcmaScript.toString(value, true)); // todo, use this line
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user