Exemple #1
0
        public static U30 CalcScopeDepth(byte[] code)
        {
            ClearFlags();

            uint i = 0;
            uint n = (uint)code.Length;

            int scopeDepth    = 0;
            int maxScopeDepth = 0;

            while (i < n)
            {
                AVM2Command cmd = null;

                try
                {
                    cmd = Translator.ToCommand(code[i++]);
                }
                catch (Exception)
                {
                    DebugUtil.DumpOpUntilError(code);
                    throw new Exception(String.Format("Can not translate {0} correct at {1}.", code[i - 1], i - 1));
                }


                if (null == cmd)
                {
                    throw new Exception();
                }

                i += cmd.ReadParameters(code, i);

                switch (cmd.OpCode)
                {
                case (byte)Op.PushScope:
                case (byte)Op.PushWith:
                    scopeDepth++;
                    break;

                case (byte)Op.PopScope:
                    scopeDepth--;
                    break;
                }

                if (scopeDepth > maxScopeDepth)
                {
                    maxScopeDepth = scopeDepth;
                }
            }

            U30 result = new U30();

            result.Value = (uint)maxScopeDepth;

            return(result);
        }
Exemple #2
0
        public static U30 CalcMaxStack(byte[] code)
        {
            ClearFlags();

            uint i = 0;
            uint n = (uint)code.Length;

            int stack    = 0;
            int maxStack = 0;

            bool corrupt = false;

            uint j = 0;

            List <ConditionalJump> jumps = new List <ConditionalJump>();
            List <uint>            unconditionalJumps = new List <uint>();

            ConditionalJump cj;

            int jumpIndex = 0;

            do
            {
                while (i < n)
                {
                    AVM2Command cmd = null;

                    try
                    {
                        cmd = Translator.ToCommand(code[i++]);
                    }
                    catch (Exception)
                    {
                        DebugUtil.DumpOpUntilError(code);
                        throw new Exception(String.Format("Can not translate {0} correct at {1}.", code[i - 1], i - 1));
                    }

                    if (null == cmd)
                    {
                        throw new Exception();
                    }

                    i += cmd.ReadParameters(code, i);

                    // There are a couple of opcodes marked "incorrect" with a comment.
                    // The explanation is: If the index in the multiname array is a RTQName
                    // there could be a namspace and/or namespace set on the stack as well
                    // that would be popped.
                    //
                    // We do not take that in account here - in the worst case that a namespace
                    // and namespace set is present it could add +2 to the max sack if the
                    // stack is greater than the one we already have.
                    //
                    // In the calculation of the possible max stack we will therefore only remove
                    // the number of arguments from the current value. If there are no arguments
                    // the opcode will be listed here as incorrect without any following calculation.
                    //
                    // Although this is not a problem for the Flash Player. It is just not very
                    // nice...
                    switch (cmd.OpCode)
                    {
                    case (byte)Op.Jump:
                        if (!unconditionalJumps.Contains(i))
                        {
                            unconditionalJumps.Add(i);

                            i = (uint)((int)i + (int)((S24)cmd.Parameters[0]).Value);
                        }
                        else
                        {
                            //LOOP BAAM!
                        }
                        break;

                    case (byte)Op.PushByte:
                    case (byte)Op.PushDouble:
                    case (byte)Op.PushFalse:
                    case (byte)Op.PushInt:
                    case (byte)Op.PushNamespace:
                    case (byte)Op.PushNaN:
                    case (byte)Op.PushNull:
                    case (byte)Op.PushShort:
                    case (byte)Op.PushString:
                    case (byte)Op.PushTrue:
                    case (byte)Op.PushUInt:
                    case (byte)Op.PushUndefined:
                    case (byte)Op.Dup:
                    case (byte)Op.FindProperty:       //incorrect
                    case (byte)Op.FindPropertyStrict: //incorrect
                    case (byte)Op.GetGlobalScope:
                    case (byte)Op.GetGlobalSlot:
                    case (byte)Op.GetLex:
                    case (byte)Op.GetLocal:
                    case (byte)Op.GetLocal0:
                    case (byte)Op.GetLocal1:
                    case (byte)Op.GetLocal2:
                    case (byte)Op.GetLocal3:
                    case (byte)Op.GetScopeObject:
                    case (byte)Op.HasNext2:
                    case (byte)Op.NewActivation:
                    case (byte)Op.NewCatch:
                    case (byte)Op.NewFunction:
                        ++stack;
                        break;

                    case (byte)Op.IfFalse:
                    case (byte)Op.IfTrue:
                        --stack;

                        cj = new ConditionalJump();

                        cj.offset = (S24)cmd.Parameters[0];
                        cj.pos    = i;
                        cj.stack  = stack;

                        if (!ContainsJumpFrom(jumps, cj))
                        {
                            jumps.Add(cj);
                        }
                        break;

                    case (byte)Op.Add:
                    case (byte)Op.AddInt:
                    case (byte)Op.AsTypeLate:
                    case (byte)Op.BitAnd:
                    case (byte)Op.BitOr:
                    case (byte)Op.BitXor:
                    case (byte)Op.Divide:
                    case (byte)Op.DefaultXmlNamespaceLate:
                    case (byte)Op.Equals:
                    case (byte)Op.GreaterEquals:
                    case (byte)Op.GreaterThan:
                    case (byte)Op.HasNext:
                    case (byte)Op.In:
                    case (byte)Op.InstanceOf:
                    case (byte)Op.IsTypeLate:
                    case (byte)Op.LessEquals:
                    case (byte)Op.LessThan:
                    case (byte)Op.LeftShift:
                    case (byte)Op.Modulo:
                    case (byte)Op.Multiply:
                    case (byte)Op.MultiplyInt:
                    case (byte)Op.NextName:
                    case (byte)Op.NextValue:
                    case (byte)Op.Pop:
                    case (byte)Op.PushScope:   //pop from stack, push to scope stack
                    case (byte)Op.PushWith:    //pop from stack, push to scope stack
                    case (byte)Op.ReturnValue:
                    case (byte)Op.RightShift:
                    case (byte)Op.SetLocal:
                    case (byte)Op.SetLocal0:
                    case (byte)Op.SetLocal1:
                    case (byte)Op.SetLocal2:
                    case (byte)Op.SetLocal3:
                    case (byte)Op.SetGlobalSlot:
                    case (byte)Op.StrictEquals:
                    case (byte)Op.Subtract:
                    case (byte)Op.SubtractInt:
                    case (byte)Op.Throw:
                    case (byte)Op.UnsignedRightShift:
                        --stack;
                        break;

                    case (byte)Op.LookupSwitch:
                        --stack;
                        for (int k = 2; k < cmd.ParameterCount; ++k)
                        {
                            cj.offset = (S24)cmd.Parameters[k];
                            cj.pos    = i;
                            cj.stack  = stack;

                            if (!ContainsJumpFrom(jumps, cj))
                            {
                                jumps.Add(cj);
                            }
                        }
                        break;

                    case (byte)Op.IfEqual:
                    case (byte)Op.IfGreaterEqual:
                    case (byte)Op.IfGreaterThan:
                    case (byte)Op.IfLessEqual:
                    case (byte)Op.IfLowerThan:
                    case (byte)Op.IfNotEqual:
                    case (byte)Op.IfNotGreaterEqual:
                    case (byte)Op.IfNotGreaterThan:
                    case (byte)Op.IfNotLowerEqual:
                    case (byte)Op.IfNotLowerThan:
                    case (byte)Op.IfStrictEqual:
                    case (byte)Op.IfStrictNotEqual:
                        stack -= 2;

                        cj = new ConditionalJump();

                        cj.offset = (S24)cmd.Parameters[0];
                        cj.pos    = i;
                        cj.stack  = stack;

                        if (!ContainsJumpFrom(jumps, cj))
                        {
                            jumps.Add(cj);
                        }
                        break;

                    case (byte)Op.InitProperty:
                    case (byte)Op.SetProperty: //incorrect
                    case (byte)Op.SetSlot:
                    case (byte)Op.SetSuper:    //incorrect
                        stack -= 2;
                        break;

                    case (byte)Op.Call:
                    case (byte)Op.ConstructSuper:
                        stack -= 1 + (int)((U30)cmd.Parameters[0]);
                        break;

                    case (byte)Op.Construct:
                        stack -= (int)((U30)cmd.Parameters[0]);;
                        break;

                    case (byte)Op.NewArray:
                        stack -= (int)((U30)cmd.Parameters[0]) - 1;
                        break;

                    case (byte)Op.CallMethod:
                    case (byte)Op.CallProperty:     //incorrect
                    case (byte)Op.CallPropertyLex:  //incorrect
                    case (byte)Op.CallPropertyVoid: //incorrect
                    case (byte)Op.CallStatic:
                    case (byte)Op.CallSuper:        //incorrect
                    case (byte)Op.CallSuperVoid:    //incorrect
                    case (byte)Op.ConstructProperty:
                        stack -= (int)((U30)cmd.Parameters[1]);
                        break;

                    case (byte)Op.NewObject:
                        stack -= ((int)((U30)cmd.Parameters[0])) << 1;
                        break;

                        //case (byte)Op.DeleteProperty://incorrect
                        //case (byte)Op.GetDescendants://incorrect
                        //case (byte)Op.GetProperty://incorrect
                        //case (byte)Op.GetSuper://incorrect
                        //    break;
                    }

                    if (stack < 0)
                    {
                        RaiseFlag(InvalidStack);
                        corrupt = true;
                        Console.WriteLine("[-] Warning: Stack underflow error at operation {0} (#{1})...", cmd.StringRepresentation, j);
                    }

                    if (stack > maxStack)
                    {
                        maxStack = stack;
                    }

                    ++j;
                }

                if (jumpIndex < jumps.Count)
                {
                    ConditionalJump nextScan = jumps[jumpIndex++];

                    i = (uint)((int)nextScan.pos + (int)nextScan.offset);

                    stack = nextScan.stack;
                }
                else
                {
                    break;
                }
            } while (true);

            U30 result = new U30();

            result.Value = (uint)maxStack;

            if (corrupt)
            {
                DebugUtil.DumpOpUntilError(code);
            }

            return(result);
        }
Exemple #3
0
        public static U30 CalcLocalCount(byte[] code)
        {
            ClearFlags();

            uint i = 0;
            uint n = (uint)code.Length;

            uint local    = 0;
            uint maxLocal = 0;

            while (i < n)
            {
                AVM2Command cmd = null;

                try
                {
                    cmd = Translator.ToCommand(code[i++]);
                }
                catch (Exception)
                {
                    DebugUtil.DumpOpUntilError(code);
                    throw new Exception(String.Format("Can not translate {0} correct at {1}.", code[i - 1], i - 1));
                }

                if (null == cmd)
                {
                    throw new Exception();
                }

                i += cmd.ReadParameters(code, i);

                switch (cmd.OpCode)
                {
                case (byte)Op.Debug:
                    byte type = (byte)cmd.Parameters[0];
                    if (1 == type)
                    {
                        local = (byte)cmd.Parameters[2] + 1U;
                    }
                    break;

                case (byte)Op.SetLocal:
                case (byte)Op.GetLocal:
                    U30 register = (U30)cmd.Parameters[0];
                    local = register.Value + 1U;
                    break;

                case (byte)Op.SetLocal0:
                case (byte)Op.GetLocal0:
                    local = 1;
                    break;

                case (byte)Op.SetLocal1:
                case (byte)Op.GetLocal1:
                    local = 2;
                    break;

                case (byte)Op.SetLocal2:
                case (byte)Op.GetLocal2:
                    local = 3;
                    break;

                case (byte)Op.SetLocal3:
                case (byte)Op.GetLocal3:
                    local = 4;
                    break;
                }

                if (local > maxLocal)
                {
                    maxLocal = local;
                }
            }

            U30 result = new U30();

            result.Value = maxLocal;

            return(result);
        }