Added AS3 P-code keyword "Unknown(N)", where N is index. For constants out of bounds. (mostly in dead code)

Fixed AS3 Deobfuscation causing invalid jump offsets for files with constant indices out of bounds
This commit is contained in:
Jindra Petřík
2022-12-18 23:10:24 +01:00
parent 0bad1d2930
commit c4799bc92e
13 changed files with 2527 additions and 2462 deletions
@@ -1154,7 +1154,7 @@ public class ABC implements Openable {
for (int o = 0; o < ins.definition.operands.length; o++) {
if (ins.definition.operands[o] == AVM2Code.DAT_MULTINAME_INDEX) {
int mi = ins.operands[o];
if (!foundMultinames[mi]) {
if (mi < foundMultinames.length && !foundMultinames[mi]) {
ret.get(mi).add(new MethodBodyMultinameUsage(this, mi, scriptIndex, classIndex, traitIndex, traitsType, isInitializer, traits, parentTraitIndex));
foundMultinames[mi] = true;
}
@@ -886,7 +886,8 @@ public class AVM2Code implements Cloneable {
* @param constants
*/
public void removeWrongIndices(AVM2ConstantPool constants) {
for (AVM2Instruction ins : code) {
//This is DANGEROUS as it may alter instruction size which may lead to incorrect jump offsets!!!
/*for (AVM2Instruction ins : code) {
for (int i = 0; i < ins.definition.operands.length; i++) {
if (ins.definition.operands[i] == DAT_MULTINAME_INDEX && ins.operands[i] >= constants.getMultinameCount()) {
ins.operands[i] = 0;
@@ -904,7 +905,7 @@ public class AVM2Code implements Cloneable {
ins.operands[i] = 0;
}
}
}
}*/
}
public AVM2Code(ABCInputStream ais, MethodBody body) throws IOException {
@@ -282,33 +282,18 @@ public class AVM2ConstantPool implements Cloneable {
}
public int getInt(int index) {
try {
if (index == 0) {
return 0;
}
return constant_int.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Int not found. Index: " + index, ex);
if (index == 0) {
return 0;
}
return 0;
return constant_int.get(index);
}
public Namespace getNamespace(int index) {
try {
return constant_namespace.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Namespace not found. Index: " + index, ex);
}
return null;
return constant_namespace.get(index);
}
public NamespaceSet getNamespaceSet(int index) {
try {
return constant_namespace_set.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "NamespaceSet not found. Index: " + index, ex);
}
return null;
return constant_namespace_set.get(index);
}
/**
@@ -336,45 +321,25 @@ public class AVM2ConstantPool implements Cloneable {
}
public Multiname getMultiname(int index) {
try {
return constant_multiname.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Multiname not found. Index: " + index, ex);
}
return null;
return constant_multiname.get(index);
}
public long getUInt(int index) {
try {
if (index == 0) {
return 0;
}
return constant_uint.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "UInt not found. Index: " + index, ex);
if (index == 0) {
return 0;
}
return 0;
return constant_uint.get(index);
}
public double getDouble(int index) {
try {
if (index == 0) {
return 0;
}
return constant_double.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Double not found. Index: " + index, ex);
if (index == 0) {
return 0;
}
return 0;
return constant_double.get(index);
}
public Decimal getDecimal(int index) {
try {
return constant_decimal.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Decimal not found. Index: " + index, ex);
}
return null;
return constant_decimal.get(index);
}
public int getDecimalId(Decimal val, boolean add) {
@@ -386,30 +351,15 @@ public class AVM2ConstantPool implements Cloneable {
}
public Float getFloat(int index) {
try {
return constant_float.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Float not found. Index: " + index, ex);
}
return null;
return constant_float.get(index);
}
public Float4 getFloat4(int index) {
try {
return constant_float4.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Float4 not found. Index: " + index, ex);
}
return null;
return constant_float4.get(index);
}
public String getString(int index) {
try {
return constant_string.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "String not found. Index: " + index, ex);
}
return null;
return constant_string.get(index);
}
public int getIntCount() {
@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.ABCOutputStream;
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
@@ -251,7 +252,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
s.append(" null");
} else {
s.append(" ");
s.append(Multiname.namespaceToString(constants, operands[i]));
try {
s.append(Multiname.namespaceToString(constants, operands[i]));
} catch (IndexOutOfBoundsException iob) {
s.append("Unknown(").append(operands[i]).append(")");
}
}
break;
case AVM2Code.DAT_MULTINAME_INDEX:
@@ -259,11 +264,13 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
s.append(" null");
} else {
s.append(" ");
Multiname multiname = constants.getMultiname(operands[i]);
if (multiname != null) {
s.append(multiname.toString(constants, fullyQualifiedNames));
} else {
s.append("Multiname not found.");
try {
Multiname multiname = constants.getMultiname(operands[i]);
if (multiname != null) {
s.append(multiname.toString(constants, fullyQualifiedNames));
}
} catch (IndexOutOfBoundsException iob) {
s.append("Unknown(").append(operands[i]).append(")");
}
}
/*s.append(" m[");
@@ -278,12 +285,16 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
break;
case AVM2Code.DAT_STRING_INDEX:
String str;
if (operands[i] == 0 || (str = constants.getString(operands[i])) == null) {
s.append(" null");
} else {
s.append(" \"");
s.append(Helper.escapePCodeString(str));
s.append("\"");
try {
if (operands[i] == 0 || (str = constants.getString(operands[i])) == null) {
s.append(" null");
} else {
s.append(" \"");
s.append(Helper.escapePCodeString(str));
s.append("\"");
}
} catch (IndexOutOfBoundsException iob) {
s.append(" Unknown(").append(operands[i]).append(")");
}
break;
case AVM2Code.DAT_INT_INDEX:
@@ -291,7 +302,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getInt(operands[i]));
try {
s.append(constants.getInt(operands[i]));
} catch (IndexOutOfBoundsException iob) {
s.append("Unknown(").append(operands[i]).append(")");
}
}
break;
case AVM2Code.DAT_UINT_INDEX:
@@ -299,7 +314,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getUInt(operands[i]));
try {
s.append(constants.getUInt(operands[i]));
} catch (IndexOutOfBoundsException iob) {
s.append("Unknown(").append(operands[i]).append(")");
}
}
break;
case AVM2Code.DAT_DOUBLE_INDEX:
@@ -307,7 +326,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getDouble(operands[i]));
try {
s.append(constants.getDouble(operands[i]));
} catch (IndexOutOfBoundsException iob) {
s.append("Unknown(").append(operands[i]).append(")");
}
}
break;
case AVM2Code.DAT_FLOAT_INDEX:
@@ -315,18 +338,26 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getFloat(operands[i]));
try {
s.append(constants.getFloat(operands[i]));
} catch (IndexOutOfBoundsException iob) {
s.append("Unknown(").append(operands[i]).append(")");
}
}
break;
case AVM2Code.DAT_FLOAT4_INDEX:
if (operands[i] == 0) {
s.append(" null");
} else {
Float4 f4 = constants.getFloat4(operands[i]);
s.append(" ").append(f4.values[0]);
s.append(" ").append(f4.values[1]);
s.append(" ").append(f4.values[2]);
s.append(" ").append(f4.values[3]);
try {
Float4 f4 = constants.getFloat4(operands[i]);
s.append(" ").append(f4.values[0]);
s.append(" ").append(f4.values[1]);
s.append(" ").append(f4.values[2]);
s.append(" ").append(f4.values[3]);
} catch (IndexOutOfBoundsException iob) {
s.append(" Unknown(").append(operands[i]).append(")");
}
}
break;
case AVM2Code.DAT_DECIMAL_INDEX:
@@ -334,7 +365,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getDecimal(operands[i]));
try {
s.append(constants.getDecimal(operands[i]));
} catch (IndexOutOfBoundsException iob) {
s.append("Unknown(").append(operands[i]).append(")");
}
}
break;
case AVM2Code.DAT_OFFSET:
@@ -244,6 +244,15 @@ public class ASM3Parser {
private static int parseNamespaceSet(AVM2ConstantPool constants, Flasm3Lexer lexer) throws AVM2ParseException, IOException {
List<Integer> namespaceList = new ArrayList<>();
ParsedSymbol s = lexer.lex();
if (s.type == ParsedSymbol.TYPE_KEYWORD_UNKNOWN) {
expected(ParsedSymbol.TYPE_PARENT_OPEN, "(", lexer);
s = lexer.lex();
expected(s, ParsedSymbol.TYPE_INTEGER, "integer");
expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer);
return (int) (Integer) s.value;
}
if (s.type == ParsedSymbol.TYPE_KEYWORD_NULL) {
return 0;
}
@@ -282,6 +291,12 @@ public class ASM3Parser {
ParsedSymbol type = lexer.lex();
int kind = 0;
switch (type.type) {
case ParsedSymbol.TYPE_KEYWORD_UNKNOWN:
expected(ParsedSymbol.TYPE_PARENT_OPEN, "(", lexer);
ParsedSymbol s = lexer.lex();
expected(s, ParsedSymbol.TYPE_INTEGER, "integer");
expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer);
return (int) (Integer) s.value;
case ParsedSymbol.TYPE_KEYWORD_NULL:
return 0;
case ParsedSymbol.TYPE_KEYWORD_NAMESPACE:
@@ -341,6 +356,12 @@ public class ASM3Parser {
int kind = 0;
switch (s.type) {
case ParsedSymbol.TYPE_KEYWORD_UNKNOWN:
expected(ParsedSymbol.TYPE_PARENT_OPEN, "(", lexer);
s = lexer.lex();
expected(s, ParsedSymbol.TYPE_INTEGER, "integer");
expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer);
return (int) (Integer) s.value;
case ParsedSymbol.TYPE_KEYWORD_NULL:
return 0;
case ParsedSymbol.TYPE_KEYWORD_QNAME:
@@ -904,6 +925,25 @@ public class ASM3Parser {
parsedOperand = lexer.lex();
}
}
switch (def.operands[i]) {
case AVM2Code.DAT_MULTINAME_INDEX:
case AVM2Code.DAT_NAMESPACE_INDEX:
case AVM2Code.DAT_STRING_INDEX:
case AVM2Code.DAT_INT_INDEX:
case AVM2Code.DAT_UINT_INDEX:
case AVM2Code.DAT_DOUBLE_INDEX:
case AVM2Code.DAT_FLOAT_INDEX:
case AVM2Code.DAT_FLOAT4_INDEX:
if (parsedOperand.type == ParsedSymbol.TYPE_KEYWORD_UNKNOWN) {
expected(ParsedSymbol.TYPE_PARENT_OPEN, "(", lexer);
ParsedSymbol indexSymb = lexer.lex();
expected(indexSymb, ParsedSymbol.TYPE_INTEGER, "integer");
expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer);
operandsList.add((int) (Integer) indexSymb.value);
continue;
}
break;
}
switch (def.operands[i]) {
case AVM2Code.DAT_MULTINAME_INDEX:
lexer.pushback(parsedOperand);
@@ -913,7 +953,7 @@ public class ASM3Parser {
lexer.pushback(parsedOperand);
operandsList.add(parseNamespace(constants, lexer));
break;
case AVM2Code.DAT_STRING_INDEX:
case AVM2Code.DAT_STRING_INDEX:
if (parsedOperand.type == ParsedSymbol.TYPE_KEYWORD_NULL) {
operandsList.add(0);
} else if (parsedOperand.type == ParsedSymbol.TYPE_STRING) {
File diff suppressed because it is too large Load Diff
@@ -199,6 +199,8 @@ public class ParsedSymbol {
public static final int TYPE_KEYWORD_METADATA_BLOCK = 86;
public static final int TYPE_KEYWORD_ITEM = 87;
public static final int TYPE_KEYWORD_END = 88;
public static final int TYPE_KEYWORD_UNKNOWN = 89;
public ParsedSymbol(int type, Object value) {
this.type = type;