예제 #1
0
 @Override
 public AVM2Instruction clone() {
   try {
     AVM2Instruction ret = (AVM2Instruction) super.clone();
     if (operands != null) {
       ret.operands = Arrays.copyOf(operands, operands.length);
     }
     return ret;
   } catch (CloneNotSupportedException ex) {
     throw new RuntimeException();
   }
 }
  @Override
  public void deobfuscate(
      String path,
      int classIndex,
      boolean isStatic,
      int scriptIndex,
      ABC abc,
      AVM2ConstantPool cpool,
      Trait trait,
      MethodInfo minfo,
      MethodBody body)
      throws InterruptedException {

    // body.getCode().markMappedOffsets();
    // removeUnreachableActions(body.getCode(), cpool, trait, minfo, body);
    AVM2Code code = body.getCode();

    boolean found;
    do {
      found = false;
      Map<Integer, List<Integer>> refs = body.getCode().visitCode(body);
      loopi:
      for (int i = 0; i < code.code.size(); i++) {
        AVM2Instruction ins = code.code.get(i);
        if (ins.definition instanceof JumpIns) {
          long targetAddr = ins.offset + ins.operands[0] + ins.getBytesLength();
          {
            for (int r : refs.get(i)) {
              if (r >= 0) { // Not Exception start/end
                AVM2Instruction srcIns = code.code.get(r);

                if ((srcIns.definition instanceof JumpIns)
                    || ((srcIns.definition instanceof IfTypeIns) && (r != i - 1))) {
                  {
                    int oldop = srcIns.operands[0];
                    srcIns.operands[0] =
                        (int) (targetAddr - (srcIns.offset + srcIns.getBytesLength()));
                    if (srcIns.operands[0] != oldop) {
                      found = true;
                    }
                  }
                }
              }
            }
          }
        }
      }
      removeUnreachableActions(body.getCode(), cpool, trait, minfo, body);
    } while (found);
  }
예제 #3
0
  @Override
  public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
    int locRegIndex = ins.getParamAsLong(constants, 0).intValue();
    Object obj = lda.localRegisters.get(locRegIndex);
    if (obj != NotCompileTime.INSTANCE) {
      lda.localRegisters.put(locRegIndex, EcmaScript.toInt32(obj) - 1);
    }

    return true;
  }
예제 #4
0
  @Override
  public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
    int argCount = ins.getParamAsLong(constants, 0).intValue();
    /* List<Object> passArguments = new ArrayList<Object>();
    for (int i = argCount - 1; i >= 0; i--) {
    passArguments.set(i, lda.operandStack.pop());
    }*/
    for (int i = 0; i < argCount; i++) {
      lda.operandStack.pop();
    }

    Object receiver = lda.operandStack.pop();
    Object function = lda.operandStack.pop();

    // push(result)
    lda.operandStack.push(NotCompileTime.INSTANCE);
    // lda.executionException = "Call to unknown function";
    return true;
  }
  private int visitCode(
      Reference<AVM2Instruction> assignment,
      Set<Integer> visited,
      TranslateStack stack,
      int classIndex,
      boolean isStatic,
      MethodBody body,
      int scriptIndex,
      ABC abc,
      AVM2Code code,
      int idx,
      int endIdx,
      Set<Integer> ignored,
      Set<Integer> ignoredGets)
      throws InterruptedException {
    List<GraphTargetItem> output = new ArrayList<>();
    AVM2LocalData localData =
        newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex);
    initLocalRegs(localData, body.getLocalReservedCount(), body.max_regs);
    localData.localRegs.put(0, new NullAVM2Item(null, null)); // this

    List<Integer> toVisit = new ArrayList<>();
    toVisit.add(idx);
    List<TranslateStack> toVisitStacks = new ArrayList<>();
    toVisitStacks.add(stack);
    outer:
    while (!toVisit.isEmpty()) {
      if (Thread.currentThread().isInterrupted()) {
        throw new InterruptedException();
      }

      idx = toVisit.remove(0);
      stack = toVisitStacks.remove(0);

      while (true) {
        if (idx > endIdx) {
          break;
        }
        if (visited.contains(idx)) {
          break;
        }
        visited.add(idx);

        AVM2Instruction ins = code.code.get(idx);
        InstructionDefinition def = ins.definition;
        // System.err.println("" + idx + ": " + ins + " stack:" + stack.size());

        // do not throw EmptyStackException, much faster
        int requiredStackSize = ins.getStackPopCount(localData);
        if (stack.size() < requiredStackSize) {
          continue outer;
        }

        ins.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
        if (def instanceof SetLocalTypeIns) {
          int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
          if (!ignored.contains(regId)) {
            assignment.setVal(ins);
            return regId;
          }
        } else if (def instanceof GetLocalTypeIns) {
          int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
          if (!ignored.contains(regId) && !ignoredGets.contains(regId)) {
            assignment.setVal(ins);
            return regId;
          }
        } else if (!(def instanceof KillIns) && !(def instanceof DebugIns)) {
          // can be inclocal, declocal, hasnext...
          for (int p = 0; p < ins.definition.operands.length; p++) {
            int op = ins.definition.operands[p];
            if (op == AVM2Code.DAT_LOCAL_REG_INDEX) {
              int regId = ins.operands[p];
              if (!ignored.contains(regId)) {
                assignment.setVal(ins);
                return regId;
              }
            }
          }
        }

        idx++;

        if (ins.definition instanceof JumpIns) {

          long address = ins.offset + ins.getBytesLength() + ins.operands[0];
          idx = code.adr2pos(address); // code.indexOf(code.getByAddress(address));
          if (idx == -1) {
            throw new TranslateException("Jump target not found: " + address);
          }
        }

        if (ins.isBranch()) {
          List<Integer> branches =
              ins.getBranches(
                  new GraphSource() {

                    @Override
                    public int size() {
                      throw new UnsupportedOperationException(
                          "Not supported yet."); // To change body of generated methods, choose
                      // Tools | Templates.
                    }

                    @Override
                    public GraphSourceItem get(int pos) {
                      throw new UnsupportedOperationException(
                          "Not supported yet."); // To change body of generated methods, choose
                      // Tools | Templates.
                    }

                    @Override
                    public boolean isEmpty() {
                      throw new UnsupportedOperationException(
                          "Not supported yet."); // To change body of generated methods, choose
                      // Tools | Templates.
                    }

                    @Override
                    public List<GraphTargetItem> translatePart(
                        GraphPart part,
                        BaseLocalData localData,
                        TranslateStack stack,
                        int start,
                        int end,
                        int staticOperation,
                        String path)
                        throws InterruptedException {
                      throw new UnsupportedOperationException(
                          "Not supported yet."); // To change body of generated methods, choose
                      // Tools | Templates.
                    }

                    @Override
                    public int adr2pos(long adr) {
                      return code.adr2pos(adr);
                    }

                    @Override
                    public long pos2adr(int pos) {
                      return code.pos2adr(pos);
                    }
                  });
          idx = branches.get(0);
          for (int n = 1; n < branches.size(); n++) {
            // visitCode(visited, (TranslateStack) stack.clone(), classIndex, isStatic, body,
            // scriptIndex, abc, code, branches.get(n), endIdx, result);
            int nidx = branches.get(n);
            if (visited.contains(nidx)) {
              continue;
            }
            toVisit.add(nidx);
            toVisitStacks.add((TranslateStack) stack.clone());
          }
        }
        /*if (ins.definition instanceof IfTypeIns) {
        long address = ins.offset + ins.getBytes().length + ins.operands[0];
        int newIdx = code.adr2pos(address);
        if (newIdx == -1) {
        throw new TranslateException("If target not found: " + address);
        }
        visitCode(visited, (TranslateStack) stack.clone(), classIndex, isStatic, body, scriptIndex, abc, code, newIdx, endIdx, result);
        }*/

        if (ins.definition instanceof ReturnValueIns) {
          break;
        }

        if (ins.definition instanceof ThrowIns) {
          break;
        }

        if (ins.definition instanceof ReturnVoidIns) {
          break;
        }
      }
    }
    return -1;
  }
  private boolean executeInstructions(
      Map<Integer, Object> staticRegs,
      MethodBody body,
      ABC abc,
      AVM2Code code,
      LocalDataArea localData,
      int idx,
      int endIdx,
      ExecutionResult result,
      AVM2Instruction inlineIns)
      throws InterruptedException {
    int instructionsProcessed = 0;

    FixItemCounterStack stack = (FixItemCounterStack) localData.operandStack;
    Set<Long> refs = code.getImportantOffsets(body);
    boolean modified = false;
    while (true) {
      if (idx > endIdx) {
        break;
      }

      if (instructionsProcessed > executionLimit) {
        break;
      }

      AVM2Instruction ins = code.code.get(idx);
      if (instructionsProcessed > 0 && refs.contains(ins.getOffset())) {
        break;
      }

      modified = modified | code.inlineJumpExit();
      InstructionDefinition def = ins.definition;
      if (inlineIns == ins) {
        if (def instanceof SetLocalTypeIns) {
          int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
          staticRegs.put(regId, localData.localRegisters.get(regId));
          code.replaceInstruction(
              idx, new AVM2Instruction(0, DeobfuscatePopIns.getInstance(), null), body);
          modified = true;
        }
      }
      if (def instanceof GetLocalTypeIns) {
        int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
        if (staticRegs.containsKey(regId)) {
          AVM2Instruction pushins = abc.constants.makePush(staticRegs.get(regId));
          if (pushins == null) {
            break;
          }

          code.replaceInstruction(idx, pushins, body);
          modified = true;
          ins = pushins;
          def = ins.definition;
        }
      }

      if (def instanceof NewFunctionIns
          && idx + 1 < code.code.size()
          && code.code.get(idx + 1).definition instanceof PopIns) {
        code.removeInstruction(idx + 1, body);
        code.removeInstruction(idx, body);
        modified = true;
        continue;
      }

      boolean ok = false;
      // todo: honfika: order by statistics
      if (def.isNotCompileTimeSupported()
          || def instanceof PushByteIns
          || def instanceof PushShortIns
          || def instanceof PushIntIns
          || def instanceof PushDoubleIns
          || def instanceof PushStringIns
          || def instanceof PushNullIns
          || def instanceof PushUndefinedIns
          || def instanceof PushFalseIns
          || def instanceof PushTrueIns
          || def instanceof DupIns
          || def instanceof SwapIns
          || def instanceof AddIns
          || def instanceof AddIIns
          || def instanceof SubtractIns
          || def instanceof SubtractIIns
          || def instanceof ModuloIns
          || def instanceof MultiplyIns
          || def instanceof MultiplyIIns //
          || def instanceof DivideIns //
          || def instanceof BitAndIns
          || def instanceof BitXorIns
          || def instanceof BitOrIns
          || def instanceof LShiftIns
          || def instanceof RShiftIns
          || def instanceof URShiftIns
          || def instanceof EqualsIns
          || def instanceof NotIns
          || def instanceof NegateIns //
          || def instanceof NegateIIns //
          || def instanceof IncrementIns //
          || def instanceof IncrementIIns //
          || def instanceof DecrementIns //
          || def instanceof DecrementIIns //
          || def instanceof IfTypeIns
          || def instanceof JumpIns
          || def instanceof EqualsIns
          || def instanceof LessEqualsIns
          || def instanceof GreaterEqualsIns
          || def instanceof GreaterThanIns
          || def instanceof LessThanIns
          || def instanceof StrictEqualsIns
          || def instanceof PopIns
          || def instanceof GetLocalTypeIns
          || def instanceof SetLocalTypeIns
          || def instanceof NewFunctionIns
          || def instanceof CoerceOrConvertTypeIns) {
        ok = true;
      }

      if (!ok) {
        break;
      }

      if (!(def instanceof NewFunctionIns)) {
        // do not throw EmptyStackException, much faster
        int requiredStackSize = def.getStackPopCount(ins, abc);
        if (stack.size() < requiredStackSize) {
          break;
        }

        if (requiredStackSize > 0 && !def.isNotCompileTimeSupported()) {
          boolean notCompileTime = false;
          for (int i = 0; i < requiredStackSize; i++) {
            if (stack.peek(i + 1) == NotCompileTime.INSTANCE) {
              notCompileTime = true;
              break;
            }
          }

          if (notCompileTime) {
            break;
          }
        }

        if (localData.scopeStack.size() < -def.getScopeStackDelta(ins, abc)) {
          break;
        }

        boolean supported;
        try {
          localData.jump = null;
          supported = def.execute(localData, abc.constants, ins);
        } catch (AVM2ExecutionException ex) {
          supported = false;
        }

        if (!supported) {
          break;
        }
      }

      boolean ifed = false;
      if (def instanceof IfTypeIns && !(def instanceof JumpIns)) {
        long address = ins.getTargetAddress();
        int nidx = code.adr2pos(address);
        AVM2Instruction tarIns = code.code.get(nidx);

        // Some IfType instructions need more than 1 operand, we must pop out all of them
        int stackCount = -def.getStackDelta(ins, abc);

        if (localData.jump != null) {
          // System.err.println("replacing " + ins + " on " + idx + " with jump");
          AVM2Instruction jumpIns = new AVM2Instruction(0, AVM2Instructions.Jump, new int[] {0});
          // jumpIns.operands[0] = ins.operands[0] /*- ins.getBytes().length*/ +
          // jumpIns.getBytes().length;
          code.replaceInstruction(idx, jumpIns, body);
          jumpIns.operands[0] =
              (int) (tarIns.getOffset() - jumpIns.getOffset() - jumpIns.getBytesLength());
          for (int s = 0; s < stackCount; s++) {
            code.insertInstruction(
                idx,
                new AVM2Instruction(ins.getOffset(), DeobfuscatePopIns.getInstance(), null),
                true,
                body);
          }

          idx = code.adr2pos(jumpIns.getTargetAddress());
        } else {
          // System.err.println("replacing " + ins + " on " + idx + " with pop");
          code.replaceInstruction(
              idx,
              new AVM2Instruction(ins.getOffset(), DeobfuscatePopIns.getInstance(), null),
              body);
          for (int s = 1 /*first is replaced*/; s < stackCount; s++) {
            code.insertInstruction(
                idx,
                new AVM2Instruction(ins.getOffset(), DeobfuscatePopIns.getInstance(), null),
                true,
                body);
          }
          // ins.definition = DeobfuscatePopIns.getInstance();
          idx++;
        }

        modified = true;
        ifed = true;
      } else {
        idx++;
      }

      instructionsProcessed++;

      if (result != null && stack.allItemsFixed()) {
        result.idx = idx == code.code.size() ? idx - 1 : idx;
        result.instructionsProcessed = instructionsProcessed;
        result.stack.clear();
        result.stack.addAll(stack);
      }

      if (ifed) {
        break;
      }

      if (localData.jump != null) {
        idx = code.adr2pos(localData.jump);

        if (idx == -1) {
          throw new TranslateException("Jump target not found: " + localData.jump);
        }
      }
    }

    return modified;
  }