Skip to content
Permalink
Browse files

AS1/2 deobfuscation of empty stack pops - returning Undefined instead

  • Loading branch information
jindrapetrik committed May 28, 2018
1 parent f48c92d commit 02660f396ef849edc552422cc9e09d3826fe024c
Showing with 377 additions and 254 deletions.
  1. +1 −0 CHANGELOG.md
  2. +45 −6 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java
  3. +17 −5 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java
  4. +2 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionAdd.java
  5. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionAnd.java
  6. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionAsciiToChar.java
  7. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionCall.java
  8. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionCharToAscii.java
  9. +4 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionCloneSprite.java
  10. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionDivide.java
  11. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionEquals.java
  12. +7 −6 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionGetProperty.java
  13. +1 −1 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionGetTime.java
  14. +5 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionGetURL2.java
  15. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionGetVariable.java
  16. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionGotoFrame2.java
  17. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java
  18. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionLess.java
  19. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionMBAsciiToChar.java
  20. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionMBCharToAscii.java
  21. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionMBStringExtract.java
  22. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionMBStringLength.java
  23. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionMultiply.java
  24. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java
  25. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionOr.java
  26. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java
  27. +4 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java
  28. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionRandomNumber.java
  29. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionRemoveSprite.java
  30. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionSetProperty.java
  31. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionSetTarget2.java
  32. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionSetVariable.java
  33. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionStringAdd.java
  34. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionStringEquals.java
  35. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionStringExtract.java
  36. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionStringLength.java
  37. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionStringLess.java
  38. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionSubtract.java
  39. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionToInteger.java
  40. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionTrace.java
  41. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionAdd2.java
  42. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionBitAnd.java
  43. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionBitLShift.java
  44. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionBitOr.java
  45. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionBitRShift.java
  46. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionBitURShift.java
  47. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionBitXor.java
  48. +1 −1 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionCallFunction.java
  49. +5 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionCallMethod.java
  50. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDecrement.java
  51. +1 −1 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java
  52. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineLocal.java
  53. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineLocal2.java
  54. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDelete2.java
  55. +3 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java
  56. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEquals2.java
  57. +5 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionGetMember.java
  58. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionIncrement.java
  59. +6 −5 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionInitArray.java
  60. +5 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionInitObject.java
  61. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionLess2.java
  62. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionModulo.java
  63. +5 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionNewMethod.java
  64. +6 −5 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionNewObject.java
  65. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java
  66. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionReturn.java
  67. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionSetMember.java
  68. +7 −6 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionStackSwap.java
  69. +1 −1 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionStoreRegister.java
  70. +5 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionTargetPath.java
  71. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionToNumber.java
  72. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionToString.java
  73. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionTypeOf.java
  74. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionWith.java
  75. +3 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java
  76. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionGreater.java
  77. +7 −6 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionInstanceOf.java
  78. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionStrictEquals.java
  79. +4 −3 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionStringGreater.java
  80. +5 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/ActionCastOp.java
  81. +1 −1 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java
  82. +3 −2 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/ActionExtends.java
  83. +5 −4 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/ActionImplementsOp.java
  84. +2 −1 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/collections/FixItemCounterStack.java
  85. +1 −1 test/com/jpexs/decompiler/flash/gui/FlashPlayerTest.java
@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
- Copy AS1/2 Graph source (GraphViz) to clipboard - rightclick menu on graph
- AS1 slash syntax support (decompilation, direct editation)
- Setting of limit of executed instructions during AS1/2 deobfuscation
- AS1/2 deobfuscation of empty stack pops

### Changed
- AS1/2 Better unresolved constant handling - §§constant(xx) func instead of §§constantxx
@@ -12,10 +12,12 @@
* 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;

import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.ecma.Undefined;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -51,6 +53,10 @@

public String executionException;

public boolean checkStackSize = true;

public int undefinedCount = 0;

public LocalDataArea(Stage stage) {
this.stage = stage;
this.target = this.stage;
@@ -64,6 +70,20 @@ public LocalDataArea(Stage stage, boolean preserveVariableOrder) {
}
}

public boolean stackIsEmpty() {
if (!checkStackSize) {
return false;
}
return stack.isEmpty();
}

public boolean stackHasMinSize(int count) {
if (!checkStackSize) {
return true;
}
return stack.size() >= count;
}

public void clear() {
constantPool = null;
stack.clear();
@@ -76,17 +96,36 @@ public void clear() {
returnValue = null;
executionException = null;
target = stage;
undefinedCount = 0;
}

public synchronized Object push(Object val) {
return stack.push(val);
}

public Object pop() {
public synchronized Object peek() {
if (!checkStackSize && stack.isEmpty()) {
undefinedCount++;
stack.push(Undefined.INSTANCE);
return Undefined.INSTANCE;
}
return stack.peek();
}

public synchronized Object pop() {
boolean isEmpty = stack.isEmpty();
if (!checkStackSize && stack.isEmpty()) {
undefinedCount++;
return Undefined.INSTANCE;
}
return stack.pop();
}

public Double popAsNumber() {
return EcmaScript.toNumberAs2(stack.pop());
public synchronized Double popAsNumber() {
return EcmaScript.toNumberAs2(pop());
}

public String popAsString() {
return EcmaScript.toString(stack.pop());
public synchronized String popAsString() {
return EcmaScript.toString(pop());
}
}
@@ -210,11 +210,23 @@ private boolean removeObfuscationIfs(FastActionList actions, Map<String, Object>
ActionItem actionItem = iterator.next();
result.clear();
localData.clear();
/*ActionItem container = actions.getContainer(actionItem);
actions.setExcludedFlags(false);
if (container != null) {
markContainerActions(container, actions);
}*/

/*
When running code from first action,
there can be pops from stack when the stack is empty
which results in Undefined popped.
Some obfuscated code checks for these undefineds like:
Not
If loc1
ConstantPool
Jump loc2
loc1:
<code>
loc2:
*/
localData.checkStackSize = !first; //this enables popping undefineds

executeActions(actionItem, localData, cPool, result, fakeFunctions, useVariables, first);

@@ -45,11 +45,11 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.size() < 2) {
if (!lda.stackHasMinSize(2)) {
return false;
}

lda.stack.push(AddActionItem.getResult(lda.pop(), lda.pop(), false));
lda.push(AddActionItem.getResult(lda.pop(), lda.pop(), false));
return true;
}

@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -44,11 +45,11 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.size() < 2) {
if (!lda.stackHasMinSize(2)) {
return false;
}

lda.stack.push(AndActionItem.getResult(lda.pop(), lda.pop()));
lda.push(AndActionItem.getResult(lda.pop(), lda.pop()));
return true;
}

@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -44,11 +45,11 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.isEmpty()) {
if (lda.stackIsEmpty()) {
return false;
}

lda.stack.push(AsciiToCharActionItem.getResult(lda.pop()));
lda.push(AsciiToCharActionItem.getResult(lda.pop()));
return true;
}

@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -49,11 +50,11 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.isEmpty()) {
if (lda.stackIsEmpty()) {
return false;
}

lda.stage.callFrame(EcmaScript.toInt32(lda.stack.pop()));
lda.stage.callFrame(EcmaScript.toInt32(lda.pop()));
return true;
}

@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -44,11 +45,11 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.isEmpty()) {
if (lda.stackIsEmpty()) {
return false;
}

lda.stack.push(CharToAsciiActionItem.getResult(lda.pop()));
lda.push(CharToAsciiActionItem.getResult(lda.pop()));
return true;
}

@@ -48,13 +48,13 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.size() < 3) {
if (!lda.stackHasMinSize(3)) {
return false;
}

int depth = EcmaScript.toInt32(lda.stack.pop());
String source = EcmaScript.toString(lda.stack.pop());
String target = EcmaScript.toString(lda.stack.pop());
int depth = EcmaScript.toInt32(lda.pop());
String source = EcmaScript.toString(lda.pop());
String target = EcmaScript.toString(lda.pop());
Object clonedMember = lda.stage.getMember(source);
if (clonedMember != Undefined.INSTANCE) {
lda.stage.setMember(target, ((ActionScriptObject) clonedMember).clone());
@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -44,11 +45,11 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.size() < 2) {
if (!lda.stackHasMinSize(2)) {
return false;
}

lda.stack.push(DivideActionItem.getResult(lda.popAsNumber(), lda.popAsNumber()));
lda.push(DivideActionItem.getResult(lda.popAsNumber(), lda.popAsNumber()));
return true;
}

@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -44,11 +45,11 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.size() < 2) {
if (!lda.stackHasMinSize(2)) {
return false;
}

lda.stack.push(EqActionItem.getResult(lda.pop(), lda.pop(), false));
lda.push(EqActionItem.getResult(lda.pop(), lda.pop(), false));
return true;
}

@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -48,18 +49,18 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.size() < 2) {
if (!lda.stackHasMinSize(2)) {
return false;
}

int index = EcmaScript.toInt32(lda.stack.pop());
String target = EcmaScript.toString(lda.stack.pop());
int index = EcmaScript.toInt32(lda.pop());
String target = EcmaScript.toString(lda.pop());
Object movieClip = lda.stage.getMember(target);
if (movieClip instanceof ActionScriptObject) {
lda.stack.push(((ActionScriptObject) movieClip).getProperty(index));
lda.push(((ActionScriptObject) movieClip).getProperty(index));
return true;
}
lda.stack.push(Undefined.INSTANCE);
lda.push(Undefined.INSTANCE);
return true;
}

@@ -44,7 +44,7 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
lda.stack.push(lda.stage.getTime());
lda.push(lda.stage.getTime());
return true;
}

@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -112,12 +113,12 @@ public ActionGetURL2(FlasmLexer lexer) throws IOException, ActionParseException

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.size() < 2) {
if (!lda.stackHasMinSize(2)) {
return false;
}

String target = EcmaScript.toString(lda.stack.pop());
String urlString = EcmaScript.toString(lda.stack.pop());
String target = EcmaScript.toString(lda.pop());
String urlString = EcmaScript.toString(lda.pop());

//TODO: Execute - Connection
return true;
@@ -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.swf4;

import com.jpexs.decompiler.flash.BaseLocalData;
@@ -50,7 +51,7 @@ public String toString() {

@Override
public boolean execute(LocalDataArea lda) {
if (lda.stack.isEmpty()) {
if (lda.stackIsEmpty()) {
return false;
}

@@ -59,7 +60,7 @@ public boolean execute(LocalDataArea lda) {
value = Undefined.INSTANCE;
}

lda.stack.push(value);
lda.push(value);
return true;
}

0 comments on commit 02660f3

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