Skip to content
Permalink
Browse files

- AS1 slash syntax support (decompilation, direct editation)

- AS1/2 Using eval, set functions on obfuscated names instead of §§ syntax where applicable
  • Loading branch information
jindrapetrik committed May 27, 2018
1 parent 6ec124f commit d138c610725671e1cfecb9f6093b0f934a6ad837
Showing with 2,436 additions and 2,549 deletions.
  1. +4 −1 CHANGELOG.md
  2. BIN lib/jsyntaxpane-0.9.5.jar
  3. +3 −38 libsrc/ffdec_lib/lexers/actionscript_script.flex
  4. +40 −0 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java
  5. +10 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallFunctionActionItem.java
  6. +16 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/GetPropertyActionItem.java
  7. +7 −9 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/GetVariableActionItem.java
  8. +19 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetPropertyActionItem.java
  9. +8 −11 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java
  10. +36 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java
  11. +2,223 −2,469 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java
  12. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java
  13. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java
  14. +3 −3 libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java
  15. +3 −1 libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/FileTestBase.java
  16. BIN libsrc/ffdec_lib/testdata/as2/as2.fla
  17. BIN libsrc/ffdec_lib/testdata/as2/as2.swf
  18. BIN libsrc/ffdec_lib/testdata/as2_slash_syntax/slash_syntax.fla
  19. +49 −0 libsrc/ffdec_lib/testdata/as2_slash_syntax/slash_syntax.html
  20. BIN libsrc/ffdec_lib/testdata/as2_slash_syntax/slash_syntax.swf
  21. +7 −0 libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex
@@ -7,13 +7,16 @@ All notable changes to this project will be documented in this file.
- Export AS1/2 P-code as GraphViz
- Display better Graph using GraphViz (Must be configured in Advanced settings / Path)
- Copy AS1/2 Graph source (GraphViz) to clipboard - rightclick menu on graph
- AS1 slash syntax support (decompilation, direct editation)

### Changed
- AS1/2 Better unresolved constant handling - §§constant(xx) func instead of §§constantxx
- AS1/2 Using eval, set functions on obfuscated names instead of §§ syntax

### Fixed
- Better continue in for handling
- Using temporary registers after for..in (causing §§pop instructions, etc.)
- AS1/2 Using temporary registers after for..in (causing incorrect chained assignments handling, etc.)
- AS1/2 getProperty, setProperty handling

## [11.1.0] - 2018-05-24
### Added
BIN +3.44 KB (100%) lib/jsyntaxpane-0.9.5.jar
Binary file not shown.
@@ -105,15 +105,9 @@ EndOfLineComment = "//" {InputCharacter}* {LineTerminator}?
/* identifiers */
Identifier = [:jletter:][:jletterdigit:]*

IdentifierNs = {Identifier} ":" {Identifier}
IdentifierOrParent = {Identifier} | ".."

TypeNameSpec = ".<" {Identifier} ">"

/* XML */
XMLIdentifier = {Identifier} | {IdentifierNs}
XMLAttribute = " "* {XMLIdentifier} " "* "=" " "* \" {InputCharacter}* \" " "*
XMLBeginOneTag = "<" {XMLIdentifier} {XMLAttribute}* ">"
XMLEndTag = "</" {XMLIdentifier} ">"
Path = "/" | "/"? {IdentifierOrParent} ("/" {IdentifierOrParent})* "/"?

/* integer literals */
DecIntegerLiteral = 0 | [1-9][0-9]*
@@ -337,40 +331,11 @@ Preprocessor = \u00A7\u00A7 {Identifier}
{LineTerminator} { yyline++;}
/* whitespace */
{WhiteSpace} { /*ignore*/ }
{TypeNameSpec} { String t = yytext(); return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, t.substring(2, t.length() - 1)); }
{XMLBeginOneTag} {string.setLength(0);
yybegin(XML);
String s = yytext();
s = s.substring(1, s.length() - 1);
if (s.contains(" ")){
s = s.substring(0, s.indexOf(' '));
}
xmlTagName = s;
string.append(yytext());
}
/* identifiers */
{Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); }
{Path} { return new ParsedSymbol(SymbolGroup.PATH, SymbolType.PATH, yytext()); }
}

<XMLSTARTTAG> {
{XMLAttribute} { string.append(yytext());}
{LineTerminator} { string.append(yytext()); yyline++;}
{WhiteSpace} { string.append(yytext()); }
">" { yybegin(XML); string.append(yytext());}
}
<XML> {
{XMLBeginOneTag} { string.append(yytext());}
{XMLEndTag} { string.append(yytext());
String endtagname = yytext();
endtagname = endtagname.substring(2, endtagname.length() - 1);
if (endtagname.equals(xmlTagName)){
yybegin(YYINITIAL);
return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML, string.toString());
}
}
{LineTerminator} { string.append(yytext()); yyline++;}
[^] { string.append(yytext()); }
}

<OIDENTIFIER> {
"\u00A7" {
@@ -238,6 +238,46 @@ public String deobfuscateNameWithPackage(boolean as3, String n, HashMap<DottedCh
return null;
}

private static boolean isValidSlashPath(String s, String... exceptions) {
String[] slashParts = s.split("\\/");
if (s.isEmpty()) {
return false;
}
for (int p = 0; p < slashParts.length; p++) {
String part = slashParts[p];
if (p == 0 && part.isEmpty()) {
continue;
}
if (part.isEmpty() && p < slashParts.length - 1) { // two slashesh xx//yy
return false;
}
if ("..".equals(part)) {
continue; //okay
}
if (!isValidName(false, part, exceptions)) {
return false;
}
}
return true;
}

public static boolean isValidNameWithSlash(String s, String... exceptions) {
if (s.contains(":")) {
String pathVar[] = s.split(":");
if (!isValidSlashPath(pathVar[0], exceptions)) {
return false;
}
for (int i = 1; i < pathVar.length; i++) {
if (!isValidName(false, pathVar[i], exceptions)) {
return false;
}
}
return true;
} else {
return isValidName(false, s, exceptions);
}
}

public static boolean isValidNameWithDot(boolean as3, String s, String... exceptions) {
for (String e : exceptions) {
if (e.equals(s)) {
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model;

import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
@@ -60,7 +61,14 @@ public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) thr
srcData.localName = functionName.toStringNoQuotes(localData);

if (functionName instanceof DirectValueActionItem) {
writer.append(IdentifiersDeobfuscation.printIdentifier(false, (functionName).toStringNoQuotes(localData)));
if (!IdentifiersDeobfuscation.isValidName(false, (functionName).toStringNoQuotes(localData))) {
writer.append("eval(");
functionName.toString(writer, localData);
writer.append(")");
} else {
functionName.toStringNoQuotes(writer, localData);
}
//writer.append(IdentifiersDeobfuscation.printIdentifier(false, (functionName).toStringNoQuotes(localData)));
} else {
functionName.appendTry(writer, localData);
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model;

import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
@@ -57,8 +58,20 @@ public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) thr
if (isEmptyString(target)) {
return writer.append(Action.propertyNames[propertyIndex]);
}
target.toString(writer, localData);
return writer.append(".").append(Action.propertyNames[propertyIndex]);

if ((target instanceof DirectValueActionItem) && ((DirectValueActionItem) target).isString()) {
target.toStringNoQuotes(writer, localData);
return writer.append(":" + Action.propertyNames[propertyIndex]);
}

writer.append("getProperty");
writer.spaceBeforeCallParenthesies(2);
writer.append("(");
target.appendTo(writer, localData);
writer.append(", ");
writer.append(Action.propertyNames[propertyIndex]);
writer.append(")");
return writer;
}

@Override
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model;

import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
@@ -66,20 +67,17 @@ public GetVariableActionItem(GraphSourceItem instruction, GraphSourceItem lineSt

@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {

if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString()) && (!IdentifiersDeobfuscation.isValidNameWithDot(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) {
if ((name instanceof DirectValueActionItem) && (((DirectValueActionItem) name).isString()) && (IdentifiersDeobfuscation.isValidNameWithDot(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super")
|| IdentifiersDeobfuscation.isValidNameWithSlash(((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) {
HighlightData srcData = getSrcData();
srcData.localName = name.toStringNoQuotes(localData);

return IdentifiersDeobfuscation.appendObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData), writer);
} else if ((!(name instanceof DirectValueActionItem)) || (!((DirectValueActionItem) name).isString())) {
return stripQuotes(name, localData, writer);
} else {
writer.append("eval(");
name.appendTry(writer, localData);
return writer.append(")");
}
HighlightData srcData = getSrcData();
srcData.localName = name.toStringNoQuotes(localData);
return stripQuotes(name, localData, writer);
//IdentifiersDeobfuscation.appendObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData), writer);
}

@Override
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model;

import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
@@ -81,9 +82,23 @@ public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) thr
writer.append(Action.propertyNames[propertyIndex]).append(" = ");
return value.toString(writer, localData);
}
target.toString(writer, localData);
writer.append("." + Action.propertyNames[propertyIndex]).append(" = ");
return value.toString(writer, localData);

if ((target instanceof DirectValueActionItem) && ((DirectValueActionItem) target).isString()) {
target.toStringNoQuotes(writer, localData);
writer.append(":" + Action.propertyNames[propertyIndex]).append(" = ");
return value.toString(writer, localData);
}

writer.append("setProperty");
writer.spaceBeforeCallParenthesies(3);
writer.append("(");
target.appendTo(writer, localData);
writer.append(", ");
writer.append(Action.propertyNames[propertyIndex]);
writer.append(", ");
value.appendTo(writer, localData);
writer.append(")");
return writer;
}

@Override
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model;

import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
@@ -76,14 +77,15 @@ public SetVariableActionItem(GraphSourceItem instruction, GraphSourceItem lineSt

@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString()) && (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) {
if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString())
&& (IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super")
|| IdentifiersDeobfuscation.isValidNameWithSlash(((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) {
HighlightData srcData = getSrcData();
srcData.localName = name.toStringNoQuotes(localData);

IdentifiersDeobfuscation.appendObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData), writer);
stripQuotes(name, localData, writer);
writer.append(" = ");
return value.toString(writer, localData);
} else if ((!(name instanceof DirectValueActionItem)) || (!((DirectValueActionItem) name).isString())) {
} else {
writer.append("set");
writer.spaceBeforeCallParenthesies(2);
writer.append("(");
@@ -92,12 +94,7 @@ public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) thr
value.toString(writer, localData);
return writer.append(")");
}
HighlightData srcData = getSrcData();
srcData.localName = name.toStringNoQuotes(localData);

stripQuotes(name, localData, writer);
writer.append(" = ");
return value.toString(writer, localData);
//IdentifiersDeobfuscation.appendObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData), writer);
}

@Override
@@ -33,6 +33,7 @@
import com.jpexs.decompiler.flash.action.model.FSCommandActionItem;
import com.jpexs.decompiler.flash.action.model.FunctionActionItem;
import com.jpexs.decompiler.flash.action.model.GetMemberActionItem;
import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem;
import com.jpexs.decompiler.flash.action.model.GetTimeActionItem;
import com.jpexs.decompiler.flash.action.model.GetURL2ActionItem;
import com.jpexs.decompiler.flash.action.model.GetVariableActionItem;
@@ -63,6 +64,7 @@
import com.jpexs.decompiler.flash.action.model.RemoveSpriteActionItem;
import com.jpexs.decompiler.flash.action.model.ReturnActionItem;
import com.jpexs.decompiler.flash.action.model.SetMemberActionItem;
import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem;
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
import com.jpexs.decompiler.flash.action.model.StartDragActionItem;
import com.jpexs.decompiler.flash.action.model.StopActionItem;
@@ -1784,10 +1786,18 @@ private GraphTargetItem expressionPrimary(boolean allowEmpty, boolean inFunction
case IDENTIFIER:
case THIS:
case SUPER:
case PATH:
if (s.value.equals("not")) {
ret = new NotItem(null, null, expressionPrimary(false, inFunction, inMethod, false, variables, functions));
} else {
ret = new VariableActionItem(s.value.toString(), null, false);
if (s.type == SymbolType.PATH) {
expectedType(SymbolType.COLON);
ParsedSymbol s2 = lex();
expected(s2, lexer.yyline(), SymbolType.IDENTIFIER);
ret = new VariableActionItem(s.value.toString() + ":" + s2.value.toString(), null, false);
} else {
ret = new VariableActionItem(s.value.toString(), null, false);
}
variables.add((VariableActionItem) ret);
allowMemberOrCall = true;
}
@@ -1877,10 +1887,34 @@ private DirectValueActionItem pushConst(String s) throws IOException, ActionPars
for (VariableActionItem v : vars) {
String varName = v.getVariableName();
GraphTargetItem stored = v.getStoreValue();
int propIndex = -1;
boolean hasSubVars = false;
if (varName.contains(":")) {
hasSubVars = true;
String lowerNameStr = varName.toLowerCase();
for (int p = 0; p < Action.propertyNames.length; p++) {
String prop = Action.propertyNames[p];
if (lowerNameStr.endsWith(":" + prop.toLowerCase())) {
propIndex = p;
varName = varName.substring(0, varName.lastIndexOf(":"));
break;
}
}
}
if (v.isDefinition()) {
if (hasSubVars) {
throw new ActionParseException("Invalid : character in variable definition", lexer.yyline());
}
v.setBoxedValue(new DefineLocalActionItem(null, null, pushConst(varName), stored));
} else if (stored != null) {
v.setBoxedValue(new SetVariableActionItem(null, null, pushConst(varName), stored));
if (propIndex > -1) {
v.setBoxedValue(new SetPropertyActionItem(null, null, pushConst(varName), propIndex, stored));
} else {
v.setBoxedValue(new SetVariableActionItem(null, null, pushConst(varName), stored));
}

} else if (propIndex > -1) {
v.setBoxedValue(new GetPropertyActionItem(null, null, pushConst(varName), propIndex));
} else {
v.setBoxedValue(new GetVariableActionItem(null, null, pushConst(varName)));
}

0 comments on commit d138c61

Please sign in to comment.
You can’t perform that action at this time.