Beispiel #1
0
        public void ReadExternal(BinaryReader input)
        {
            _paramCount = Primitives.ReadU30(input);
            _returnType = Primitives.ReadU30(input);

            _paramType = new ArrayList(Capacity.Max(_paramCount));

            for (uint i = 0; i < _paramCount._value; ++i)
            {
                _paramType.Add(Primitives.ReadU30(input));
            }

            _name  = Primitives.ReadU30(input);
            _flags = input.ReadByte();

            if (HasFlag(HasOptional))
            {
                _optionInfo = new OptionInfo();
                _optionInfo.ReadExternal(input);
            }

            if (HasFlag(HasParamNames))
            {
                //param_info { u30 param_name[param_count] }
                _paramName = new ArrayList(Capacity.Max(_paramCount));

                for (uint i = 0; i < _paramCount._value; ++i)
                {
                    _paramName.Add(Primitives.ReadU30(input));
                }
            }
        }
Beispiel #2
0
 public void ReadExternal(BinaryReader input)
 {
     _from     = Primitives.ReadU30(input);
     _to       = Primitives.ReadU30(input);
     _target   = Primitives.ReadU30(input);
     _execType = Primitives.ReadU30(input);
     _varName  = Primitives.ReadU30(input);
 }
Beispiel #3
0
 public void ReadExternal(BinaryReader input)
 {
     _from = Primitives.ReadU30(input);
     _to = Primitives.ReadU30(input);
     _target = Primitives.ReadU30(input);
     _execType = Primitives.ReadU30(input);
     _varName = Primitives.ReadU30(input);
 }
Beispiel #4
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);
        }
Beispiel #5
0
        public override void ReadExternal(BinaryReader input)
        {
            _slotId   = Primitives.ReadU30(input);
            _typeName = Primitives.ReadU30(input);
            _vIndex   = Primitives.ReadU30(input);

            if (0 != _vIndex.Value)
            {
                _vKind   = input.ReadByte();
                _hasKind = true;
            }
        }
Beispiel #6
0
        public void ReadExternal(BinaryReader input)
        {
            _cinit = Primitives.ReadU30(input);

            uint n = Primitives.ReadU30(input).Value;

            _traits = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                TraitInfo ti = new TraitInfo();
                ti.ReadExternal(input);

                _traits.Add(ti);
            }
        }
Beispiel #7
0
        public void ReadExternal(BinaryReader input)
        {
            _cinit = Primitives.ReadU30(input);

            uint n = Primitives.ReadU30(input).Value;

            _traits = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                TraitInfo ti = new TraitInfo();
                ti.ReadExternal(input);

                _traits.Add(ti);
            }
        }
Beispiel #8
0
        public void ReadExternal(BinaryReader input)
        {
            uint count = Primitives.ReadU30(input).Value;

            _ns = new ArrayList(Capacity.Max(count));

            for (uint i = 0; i < count; ++i)
            {
                U30 ns = Primitives.ReadU30(input);
                _ns.Add(ns);

                if (0 == ns.Value)
                {
                    throw new VerifyException("Namespace must not be 0.");
                }
            }
        }
Beispiel #9
0
        static private MethodBodyInfo FindBody(Abc46 abc, U30 methodIndex)
        {
            SwfLibrary.Abc.MethodInfo methodInfo = (SwfLibrary.Abc.MethodInfo)abc.Methods[(int)methodIndex];
            MethodBodyInfo            methodBody = null;

            for (int i = 0, n = abc.MethodBodies.Count; i < n; ++i)
            {
                methodBody = (MethodBodyInfo)abc.MethodBodies[i];

                if (methodBody.Method.Value == methodIndex.Value)
                {
                    break;
                }
            }

            return(methodBody);
        }
Beispiel #10
0
        public static U30 GetClass(Abc46 abc, string argument)
        {
            U30 multinameIndex = GetMultiname(abc, argument);
            U30 result         = new U30();

            for (int i = 0, n = abc.Instances.Count; i < n; ++i)
            {
                InstanceInfo ii = (InstanceInfo)abc.Instances[i];

                if (ii.Name.Value == multinameIndex.Value)
                {
                    result.Value = (uint)i;
                    break;
                }
            }

            return(result);
        }
Beispiel #11
0
        public static U30 GetClass(Abc46 abc, string argument)
        {
            U30 multinameIndex = GetMultiname(abc, argument);
            U30 result = new U30();

            for (int i = 0, n = abc.Instances.Count; i < n; ++i)
            {
                InstanceInfo ii = (InstanceInfo)abc.Instances[i];

                if (ii.Name.Value == multinameIndex.Value)
                {
                    result.Value = (uint)i;
                    break;
                }
            }

            return result;
        }
Beispiel #12
0
        public void ReadExternal(BinaryReader input)
        {
            _name = Primitives.ReadU30(input);

            _superName = Primitives.ReadU30(input);

            _flags = input.ReadByte();

            if (ClassProtectedNs == (_flags & ClassProtectedNs))
            {
                _protectedNs = Primitives.ReadU30(input);
            }

            uint n = Primitives.ReadU30(input).Value;

            _interface = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                U30 iid = Primitives.ReadU30(input);

                if (0 == iid.Value)
                {
                    throw new VerifyException("Interface must not be 0.");
                }

                _interface.Add(iid);
            }

            _iinit = Primitives.ReadU30(input);

            n = Primitives.ReadU30(input).Value;

            _traits = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                TraitInfo ti = new TraitInfo();
                ti.ReadExternal(input);

                _traits.Add(ti);
            }
        }
Beispiel #13
0
        //public uint WriteParameters(byte[] code, uint index)
        public void WriteParameters(BinaryWriter output)
        {
            for (int i = 0; i < _parameterCount; ++i)
            {
                switch (_types[i])
                {
                case ParameterType.U30:
                    U30 _u30 = (U30)_parameters[i];
                    Primitives.WriteU30(output, _u30);
                    break;

                case ParameterType.U8:
                    output.Write((byte)_parameters[i]);
                    break;

                case ParameterType.S24:
                    S24 _s24 = (S24)_parameters[i];
                    Primitives.WriteS24(output, _s24);
                    break;

                case ParameterType.UInt:
                    U32 _u32 = (U32)_parameters[i];
                    Primitives.WriteU32(output, _u32);
                    break;

                case ParameterType.Dynamic:
                    S24 d_s24 = (S24)_parameters[0];
                    Primitives.WriteS24(output, d_s24);

                    U30 c_u30 = (U30)_parameters[1];
                    Primitives.WriteU30(output, c_u30);

                    for (int j = 0; j <= c_u30.Value; ++j)
                    {
                        S24 j_s24 = (S24)_parameters[2 + j];
                        Primitives.WriteS24(output, j_s24);
                    }

                    break;
                }
            }
        }
Beispiel #14
0
        public void ReadExternal(BinaryReader input)
        {
            _name = Primitives.ReadU30(input);

            if (0 == _name.Value)
                throw new VerifyException("Name must not be 0.");

            uint n = Primitives.ReadU30(input).Value;

            _items = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                ItemInfo itemInfo = new ItemInfo();

                itemInfo.key = Primitives.ReadU30(input);
                itemInfo.value = Primitives.ReadU30(input);

                _items.Add(itemInfo);
            }
        }
Beispiel #15
0
        protected void FormatMethod(U30 method)
        {
            MethodInfo     methodInfo = (MethodInfo)_abc.Methods[(int)method];
            MethodBodyInfo methodBody = null;

            int bodyIndex = 0;

            for (int i = 0, n = _abc.MethodBodies.Count; i < n; ++i)
            {
                methodBody = (MethodBodyInfo)_abc.MethodBodies[i];

                if (methodBody.Method.Value == method.Value)
                {
                    bodyIndex = i;
                    break;
                }
            }

            _output.Add(String.Format(";body{0}\r\n", bodyIndex));
            FormatBody(methodBody);
        }
Beispiel #16
0
        public void ReadExternal(BinaryReader input)
        {
            uint n;

            _method         = Primitives.ReadU30(input);
            _maxStack       = Primitives.ReadU30(input);
            _localCount     = Primitives.ReadU30(input);
            _initScopeDepth = Primitives.ReadU30(input);
            _maxScopeDepth  = Primitives.ReadU30(input);

            n     = Primitives.ReadU30(input).Value;
            _code = new byte[n];//the holy grail...finally...
            for (uint i = 0; i < n; ++i)
            {
                _code[i] = input.ReadByte();
            }


            n = Primitives.ReadU30(input).Value;
            _exceptionInfo = new ArrayList(Capacity.Max(n));
            for (uint i = 0; i < n; ++i)
            {
                ExceptionInfo ei = new ExceptionInfo();
                ei.ReadExternal(input);

                _exceptionInfo.Add(ei);
            }

            n = Primitives.ReadU30(input).Value;

            _traits = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                TraitInfo ti = new TraitInfo();
                ti.ReadExternal(input);

                _traits.Add(ti);
            }
        }
Beispiel #17
0
        public void ReadExternal(BinaryReader input)
        {
            _name = Primitives.ReadU30(input);

            if (0 == _name.Value)
            {
                throw new VerifyException("Name must not be 0.");
            }

            uint n = Primitives.ReadU30(input).Value;

            _items = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                ItemInfo itemInfo = new ItemInfo();

                itemInfo.key   = Primitives.ReadU30(input);
                itemInfo.value = Primitives.ReadU30(input);

                _items.Add(itemInfo);
            }
        }
Beispiel #18
0
        public override void ReadExternal(BinaryReader input)
        {
            _slotId = Primitives.ReadU30(input);
            _typeName = Primitives.ReadU30(input);
            _vIndex = Primitives.ReadU30(input);

            if (0 != _vIndex.Value)
            {
                _vKind = input.ReadByte();
                _hasKind = true;
            }
        }
Beispiel #19
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);
        }
Beispiel #20
0
        public static U30 CalcLocalCount(ArrayList instructions)
        {
            ClearFlags();

            int i = 0;
            int n = instructions.Count;

            uint local    = 0;
            uint maxLocal = 0;

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

                if (instructions[i] is Instruction)
                {
                    avm2Command = ((Instruction)instructions[i]).Command;
                }
                else if (instructions[i] is AVM2Command)
                {
                    avm2Command = (AVM2Command)instructions[i];
                }
                else if (instructions[i] is Label)
                {
                    ++i;
                    continue;
                }
                else
                {
                    throw new Exception("Unknown instruction type.");
                }

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

                case (byte)Op.SetLocal:
                case (byte)Op.GetLocal:
                    U30 register = (U30)avm2Command.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;
                }

                ++i;
            }

            U30 result = new U30();

            result.Value = maxLocal;

            return(result);
        }
Beispiel #21
0
        public static U30 GetNamespace(Abc46 abc, string argument)
        {
            NamespaceInfo ns;

            for (int i = 0, n = abc.ConstantPool.NamespaceTable.Count; i < n; ++i)
            {
                ns = (NamespaceInfo)abc.ConstantPool.NamespaceTable[i];

                string namespaceString = "";

                switch (ns.Kind)
                {
                case NamespaceInfo.Namespace:
                case NamespaceInfo.ExplicitNamespace:
                    //TODO implement this
                    //user defined
                    break;

                case NamespaceInfo.PrivateNs:
                    namespaceString = "private";
                    break;

                case NamespaceInfo.ProtectedNamespace:
                    namespaceString = "protected";
                    break;

                case NamespaceInfo.StaticProtectedNs:
                    namespaceString = "protected$";
                    break;

                case NamespaceInfo.PackageInternalNs:
                    namespaceString = "internal";
                    break;

                case NamespaceInfo.PackageNamespace:
                    namespaceString = "public";
                    break;

                default:
                    namespaceString = "*";
                    break;
                }

                namespaceString += "::" + ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();

                if (argument.IndexOf(namespaceString) != -1)
                {
                    U30 nsIndex = new U30();
                    nsIndex.Value = (uint)i;

                    return(nsIndex);
                }
            }

            NamespaceInfo newNs = new NamespaceInfo();

            string name = "";
            byte   kind = 0;

            if (0 == argument.IndexOf("private::"))
            {
                kind = NamespaceInfo.PrivateNs;
                name = argument.Substring(8);
            }
            else if (0 == argument.IndexOf("public::"))
            {
                kind = NamespaceInfo.PackageNamespace;
                name = argument.Substring(7);
            }

            newNs.Kind = kind;

            if ("" == name)
            {
                newNs.Name = (U30)0;
            }
            else
            {
                newNs.Name = (U30)abc.ConstantPool.ResolveString(name);
            }

            U30 result = new U30();

            result.Value = (uint)abc.ConstantPool.NamespaceTable.Count;

            abc.ConstantPool.NamespaceTable.Add(newNs);

            return(result);
        }
Beispiel #22
0
        public static U30 GetMultiname(Abc46 abc, string argument)
        {
            if (argument.StartsWith("#"))
            {
                int index = int.Parse(argument.Substring(1, argument.Length - 1));

                if (index < abc.ConstantPool.MultinameTable.Count && index > 0)
                {
                    return((U30)index);
                }

                throw new Exception(String.Format("Invalid multiname {0}", index));
            }

            NamespaceInfo    ns;
            NamespaceSetInfo nss;
            StringInfo       name;

            bool skipQname = argument.IndexOf("[") == 0;

            if (skipQname)
            {
                //BAD quick dirty hack
                argument = argument.Replace(" ", "");
            }

            string tempName;
            U30    result = new U30();

            for (int i = 1, n = abc.ConstantPool.MultinameTable.Count; i < n; ++i)
            {
                MultinameInfo multiName = (MultinameInfo)abc.ConstantPool.MultinameTable[i];

                switch (multiName.Kind)
                {
                    #region QName, QNameA

                case MultinameInfo.QName:
                case MultinameInfo.QNameA:

                    if (skipQname)
                    {
                        continue;
                    }

                    ns   = ((NamespaceInfo)abc.ConstantPool.NamespaceTable[(int)multiName.Data[0].Value]);
                    name = ((StringInfo)abc.ConstantPool.StringTable[(int)multiName.Data[1].Value]);

                    tempName = "";

                    switch (ns.Kind)
                    {
                    case NamespaceInfo.Namespace:
                    case NamespaceInfo.ExplicitNamespace:
                        //TODO implement this
                        //user defined
                        break;

                    case NamespaceInfo.PrivateNs:
                        tempName = "private";
                        break;

                    case NamespaceInfo.ProtectedNamespace:
                        tempName = "protected";
                        break;

                    case NamespaceInfo.StaticProtectedNs:
                        tempName = "protected$";
                        break;

                    case NamespaceInfo.PackageInternalNs:
                        tempName = "internal";
                        break;

                    case NamespaceInfo.PackageNamespace:
                        tempName = "public";
                        break;

                    default:
                        tempName = "*";
                        break;
                    }

                    if (0 != ns.Name.Value)
                    {
                        string namespaceName = ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();
                        if ("" != namespaceName && tempName != "")
                        {
                            tempName += "::";
                        }
                        tempName += namespaceName;
                    }

                    tempName += "::" + name.ToString();

                    if (tempName == argument)
                    {
                        result.Value = (uint)i;
                        return(result);
                    }
                    break;

                    #endregion

                    #region MultinameL, MultinameLA

                case MultinameInfo.MultinameL:
                case MultinameInfo.MultinameLA:

                    if (!skipQname)
                    {
                        continue;
                    }

                    tempName = "[";

                    nss = (NamespaceSetInfo)abc.ConstantPool.NamespaceSetTable[(int)multiName.Data[0].Value];

                    for (int j = 0, m = nss.NamespaceSet.Count; j < m; ++j)
                    {
                        U30 nssNs = (U30)nss.NamespaceSet[j];
                        ns = ((NamespaceInfo)abc.ConstantPool.NamespaceTable[(int)nssNs.Value]);

                        string r2 = "";

                        switch (ns.Kind)
                        {
                        case NamespaceInfo.Namespace:
                        case NamespaceInfo.ExplicitNamespace:
                            //TODO implement this
                            //user defined
                            break;

                        case NamespaceInfo.PrivateNs:
                            r2 = "private";
                            break;

                        case NamespaceInfo.ProtectedNamespace:
                            r2 = "protected";
                            break;

                        case NamespaceInfo.StaticProtectedNs:
                            r2 = "protected$";
                            break;

                        case NamespaceInfo.PackageInternalNs:
                            r2 = "internal";
                            break;

                        case NamespaceInfo.PackageNamespace:
                            r2 = "public";
                            break;

                        default:
                            r2 = "*";
                            break;
                        }

                        tempName += r2 + "::" + ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();

                        if (j != (m - 1))
                        {
                            tempName += ",";
                        }
                    }

                    tempName += "]";

                    if (argument == tempName)
                    {
                        result.Value = (uint)i;
                        return(result);
                    }
                    break;

                    #endregion

                default:
                    continue;
                }
            }

            if (skipQname)
            {
                #region Create MultinameL
                //
                // Create a MultinameL
                //

                // Remove [] from argument
                argument = argument.Substring(1, argument.Length - 2);


                // Get new NamespaceSet index
                U30 setIndex = new U30();
                setIndex.Value = (uint)abc.ConstantPool.NamespaceSetTable.Count;


                // Create MultinameInfo
                MultinameInfo newName = new MultinameInfo();
                newName.Data = new U30[1] {
                    setIndex
                };
                newName.Kind = MultinameInfo.MultinameL;


                // Create NamespaceSet
                NamespaceSetInfo newSet = new NamespaceSetInfo();
                newSet.NamespaceSet = new ArrayList();

                abc.ConstantPool.NamespaceSetTable.Add(newSet);

                for (int i = 0, n = abc.ConstantPool.NamespaceTable.Count; i < n; ++i)
                {
                    ns = (NamespaceInfo)abc.ConstantPool.NamespaceTable[i];

                    string r2 = "";

                    switch (ns.Kind)
                    {
                    case NamespaceInfo.Namespace:
                    case NamespaceInfo.ExplicitNamespace:
                        //TODO implement this
                        //user defined
                        break;

                    case NamespaceInfo.PrivateNs:
                        r2 = "private";
                        break;

                    case NamespaceInfo.ProtectedNamespace:
                        r2 = "protected";
                        break;

                    case NamespaceInfo.StaticProtectedNs:
                        r2 = "protected$";
                        break;

                    case NamespaceInfo.PackageInternalNs:
                        r2 = "internal";
                        break;

                    case NamespaceInfo.PackageNamespace:
                        r2 = "public";
                        break;

                    default:
                        r2 = "*";
                        break;
                    }

                    r2 += "::" + ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();

                    if (argument.IndexOf(r2) != -1)
                    {
                        U30 nsIndex = new U30();
                        nsIndex.Value = (uint)i;

                        newSet.NamespaceSet.Add(nsIndex);
                    }
                }

                result.Value = (uint)abc.ConstantPool.MultinameTable.Count;
                abc.ConstantPool.MultinameTable.Add(newName);

                #endregion
            }
            else
            {
                #region Create QName

                // Create a QName

                U30 nsIndex = new U30();

                if (argument.IndexOf("::") == argument.LastIndexOf("::"))
                {
                    nsIndex.Value = GetNamespace(abc, argument.Substring(0, argument.LastIndexOf("::") + 2)).Value;
                }
                else
                {
                    nsIndex.Value = GetNamespace(abc, argument.Substring(0, argument.LastIndexOf("::"))).Value;
                }

                MultinameInfo newQName = new MultinameInfo();
                newQName.Data = new U30[2] {
                    nsIndex, (U30)abc.ConstantPool.ResolveString(argument.Substring(argument.LastIndexOf("::") + 2))
                };
                newQName.Kind = MultinameInfo.QName;

                result.Value = (uint)abc.ConstantPool.MultinameTable.Count;

                abc.ConstantPool.MultinameTable.Add(newQName);

                #endregion
            }

            return(result);
        }
Beispiel #23
0
        public void ReadExternal(BinaryReader input)
        {
            uint n;

            _method = Primitives.ReadU30(input);
            _maxStack = Primitives.ReadU30(input);
            _localCount = Primitives.ReadU30(input);
            _initScopeDepth = Primitives.ReadU30(input);
            _maxScopeDepth = Primitives.ReadU30(input);

            n = Primitives.ReadU30(input).Value;
            _code = new byte[n];//the holy grail...finally...
            for (uint i = 0; i < n; ++i)
                _code[i] = input.ReadByte();

            n = Primitives.ReadU30(input).Value;
            _exceptionInfo = new ArrayList(Capacity.Max(n));
            for (uint i = 0; i < n; ++i)
            {
                ExceptionInfo ei = new ExceptionInfo();
                ei.ReadExternal(input);

                _exceptionInfo.Add(ei);
            }

            n = Primitives.ReadU30(input).Value;

            _traits = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                TraitInfo ti = new TraitInfo();
                ti.ReadExternal(input);

                _traits.Add(ti);
            }
        }
Beispiel #24
0
 public void ReadExternal(BinaryReader input)
 {
     _val = Primitives.ReadU30(input);
     _kind = input.ReadByte();
 }
Beispiel #25
0
        public void Compile(Abc46 abc, ArrayList instructions, Dictionary<string, Label> labels, bool patchMath)
        {
            #if DEBUG
            //Console.WriteLine("[i] Starting to compile method body ...");
            #endif
            //
            // Create buffer
            //

            MemoryStream buffer = new MemoryStream();
            BinaryWriter output = new BinaryWriter(buffer);

            //
            // Convert compiler instructions to IL.
            //
            Instruction instruction;
            Label label;
            List<ReplaceInformation> replaceList = new List<ReplaceInformation>();

            bool hasLocalMath = false;
            uint mathRegister = 0;
            U30 mathMultiName = new U30();
            AVM2Command mathCommand = null;
            AVM2Command lastCommand = null;

            for (int i = 0, n = instructions.Count; i < n; ++i)
            {
                if (instructions[i] is Label)
                {
                    label = (Label)instructions[i];

                    label.Address = (uint)buffer.Position;

                    if (!label.Referenced)
                    {
                        output.Write((byte)Op.Label);
                    }
                }
                else if (instructions[i] is AVM2Command)
                {
                    AVM2Command command = (AVM2Command)instructions[i];

                    output.Write((byte)command.OpCode);

                    switch (command.OpCode)
                    {
                        case (byte)Op.IfEqual:
                        case (byte)Op.IfFalse:
                        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:
                        case (byte)Op.IfTrue:
                        case (byte)Op.Jump:
                            string labelId = (string)command.Parameters[0];

                            try
                            {
                                label = labels[labelId];
                            }
                            catch(Exception)
                            {
                                Console.WriteLine("[-] WARNING: Jumping to an unknown label");
                                continue;
                            }

                            if (label.HasAddress)
                            {
                                int offset = (int)(label.Address - ((uint)buffer.Position + 3));
                                Primitives.WriteS24(output, offset);
                            }
                            else
                            {
                                replaceList.Add(new ReplaceInformation((uint)buffer.Position, label, false));
                                Primitives.WriteS24(output, 0);
                            }

                            label.Referenced = true;
                            break;

                        case (byte)Op.GetLex:
                            if (patchMath)
                            {
                                string lexName = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)command.Parameters[0]).Value]));

                                //
                                // If getlex public::Math is called we will repalce it with
                                // a get_local N where Math will be stored.
                                //

                                if (("public::Math" == lexName || "Math" == lexName) && (null != lastCommand) && (lastCommand.OpCode != (byte)Op.SetLocal))
                                {
            #if DEBUG
                                    Console.WriteLine("[i] Found call to Math class ...");
            #endif

                                    if (!hasLocalMath)
                                    {
                                        mathMultiName = (U30)command.Parameters[0];

                                        U30 currentMaxLocal = ByteCodeAnalyzer.CalcLocalCount(instructions);

            #if DEBUG
                                        Console.WriteLine(String.Format("[i] Math register will be {0}", currentMaxLocal.Value));
            #endif

                                        if (currentMaxLocal.Value < 4)
                                        {
                                            int val = (int)currentMaxLocal.Value;
                                            mathCommand = Translator.ToCommand((byte)(0xd0 + val));
                                        }
                                        else
                                        {
                                            mathCommand = Translator.ToCommand((byte)Op.GetLocal);
                                            mathCommand.Parameters.Add(currentMaxLocal);
                                        }

                                        mathRegister = currentMaxLocal.Value;

                                        hasLocalMath = true;
                                    }

                                    output.Seek(-1, SeekOrigin.Current);
                                    output.Write((byte)mathCommand.OpCode);

                                    if (mathCommand.OpCode == (byte)Op.GetLocal)
                                        mathCommand.WriteParameters(output);
                                }
                                else
                                {
                                    command.WriteParameters(output);
                                }
                            }
                            else
                            {
                                command.WriteParameters(output);
                            }
                            break;

                        default:
                            command.WriteParameters(output);
                            break;
                    }

                    lastCommand = command;
                }
                else if (instructions[i] is Instruction)
                {
                    instruction = (Instruction)instructions[i];

                    output.Write(instruction.Command.OpCode);

                    switch (instruction.Command.OpCode)
                    {
                        case (byte)Op.PushShort:
                            Primitives.WriteU30(output, (U30)Convert.ToInt32(instruction.Arguments[0]));
                            break;

                        case (byte)Op.AsType:
                        case (byte)Op.Coerce:
                        case (byte)Op.DeleteProperty:
                        case (byte)Op.FindProperty:
                        case (byte)Op.FindPropertyStrict:
                        case (byte)Op.GetDescendants:
                        case (byte)Op.GetLex:
                        case (byte)Op.GetProperty:
                        case (byte)Op.GetSuper:
                        case (byte)Op.InitProperty:
                        case (byte)Op.IsType:
                        case (byte)Op.SetProperty:
                        case (byte)Op.PushNamespace:
                            Primitives.WriteU30(output, NameUtil.GetMultiname(abc, instruction.Arguments[0]));
                            break;

                        case (byte)Op.CallProperty:
                        case (byte)Op.CallPropertyLex:
                        case (byte)Op.CallPropertyVoid:
                        case (byte)Op.CallSuper:
                        case (byte)Op.CallSuperVoid:
                        case (byte)Op.ConstructProperty:
                            Primitives.WriteU30(output, NameUtil.GetMultiname(abc, instruction.Arguments[0]));
                            Primitives.WriteU30(output, Convert.ToUInt32(instruction.Arguments[1]));
                            break;

                        case (byte)Op.NewClass:
                            Primitives.WriteU30(output, NameUtil.GetClass(abc, instruction.Arguments[0]));
                            break;

                        case (byte)Op.PushDouble:
                            Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveDouble(Convert.ToDouble(instruction.Arguments[0].Replace('.', ','))));
                            break;

                        case (byte)Op.PushInt:
                            Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveInt((S32)Convert.ToInt32(instruction.Arguments[0])));
                            break;

                        case (byte)Op.PushUInt:
                            Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveUInt((U32)Convert.ToUInt32(instruction.Arguments[0])));
                            break;

                        case (byte)Op.DebugFile:
                        case (byte)Op.PushString:
                            if (instruction.Arguments[0].StartsWith("\"") && instruction.Arguments[0].EndsWith("\""))//TODO fix ugly hack
                            {
                                Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveString(instruction.Arguments[0].Substring(1, instruction.Arguments[0].Length - 2)));
                            }
                            else
                            {
                                Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveString(instruction.Arguments[0]));
                            }
                            break;

                        case (byte)Op.IfEqual:
                        case (byte)Op.IfFalse:
                        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:
                        case (byte)Op.IfTrue:
                        case (byte)Op.Jump:
                            //
                            // Solve label offset
                            //

                            string labelId = null;

                            try
                            {
                                labelId = instruction.Arguments[0];
                            }
                            catch (Exception)
                            {
                                Console.WriteLine("[-] WARNING: Jumping to an unknown label");
                                continue;
                            }

                            //
                            // Make sure the label exsists.
                            //

                            if (!labels.ContainsKey(labelId))
                            {
            #if DEBUG
                                Console.WriteLine("[-] Label \"{0}\" is missing ...", labelId);
            #endif
                                throw new InstructionException(InstructionException.Type.LabelMissing, instruction.DebugInfo);
                            }

                            label = labels[labelId];

                            if (label.HasAddress)
                            {
                                //
                                // We already have the label address. This is a negative jump offset.
                                //

                                int offset = (int)(label.Address - ((uint)buffer.Position + 3));
                                Primitives.WriteS24(output, offset);
                            }
                            else
                            {
                                //
                                // We do not know the label address. This is a positive jump offset.
                                // Mark label to be solved afterwards and write a placeholder ...
                                //

                                replaceList.Add(new ReplaceInformation((uint)buffer.Position, label, false));
                                Primitives.WriteS24(output, 0);
                            }

                            label.Referenced = true;
                            break;

                        default:
                            if (0 < instruction.Command.ParameterCount)
                            {
                                try
                                {
                                    foreach (string argument in instruction.Arguments)
                                    {
                                        output.Write((byte)Convert.ToByte(argument));
                                    }
                                }
                                catch (Exception)
                                {
                                    throw new InstructionException(InstructionException.Type.UnknownType, instruction.DebugInfo);
                                }
                            }
                            break;
                    }

                    lastCommand = instruction.Command;
                }
            }

            int labelOffset = 0;

            #region Add automatically generated code

            //
            // Add local variable containing Math
            //

            if (patchMath && hasLocalMath)
            {
            #if DEBUG
                Console.WriteLine("[i] Body has local Math");
            #endif

                int mathAddress = 2;

                int lastOpCode = -1;
                int opCode = -1;

                long lastPosition = output.BaseStream.Position;

                output.BaseStream.Seek(0, SeekOrigin.Begin);

                while(((opCode = output.BaseStream.ReadByte()) != -1))
                {
                    if (lastOpCode == (byte)Op.GetLocal0 && opCode == (byte)Op.PushScope)
                    {
                        break;
                    }

                    lastOpCode = opCode;
                }

                mathAddress = (int)output.BaseStream.Position;

                output.BaseStream.Seek(lastPosition, SeekOrigin.Begin);

            #if DEBUG
                //Console.WriteLine("[i] Dump Before:");
                //DebugUtil.Dump((MemoryStream)output.BaseStream);
            #endif

                InsertByte(output, mathAddress);
                InsertByte(output, mathAddress);

                labelOffset += 2;

                int byteCoundMulti = 0;

                while (byteCoundMulti < mathMultiName.Length)
                {
                    byteCoundMulti++;
                    labelOffset++;
                    InsertByte(output, mathAddress);
                }

                if (mathRegister > 3)
                {
            #if DEBUG
                    Console.WriteLine("[i] Adding extra register");
            #endif
                    int byteCount = 0;

                    while (byteCount < ((U30)mathRegister).Length+1)
                    {
                        ++byteCount;
                        ++labelOffset;
                        InsertByte(output, mathAddress);
                    }
                }

                output.Seek(mathAddress, SeekOrigin.Begin);

                AVM2Command getLexCommand = Translator.ToCommand((byte)Op.GetLex);
                getLexCommand.Parameters.Add(mathMultiName);

                output.Write((byte)getLexCommand.OpCode);
                getLexCommand.WriteParameters(output);

                if (mathRegister > 3)
                {
                    AVM2Command setLocalCommand = Translator.ToCommand((byte)Op.SetLocal);
                    setLocalCommand.Parameters.Add((U30)mathRegister);

                    output.Write((byte)setLocalCommand.OpCode);
                    setLocalCommand.WriteParameters(output);
                }
                else
                {
                    output.Write((byte)(0xd4 + mathRegister));
                }

            #if DEBUG
                //Console.WriteLine("[i] Dump After:");
                //DebugUtil.Dump((MemoryStream)output.BaseStream);
            #endif

                output.Seek(0, SeekOrigin.End);
                output.Flush();
            }

            #endregion

            //
            // Solve remainig labels
            //

            for (int i = 0, n = replaceList.Count; i < n; ++i)
            {
                ReplaceInformation replaceInfo = replaceList[i];

                label = replaceInfo.label;

                if (!label.Referenced || !label.HasAddress)
                {
                    Console.WriteLine("[-] Warning: Label {0} has never been defined or used ...", label.Identifier);
                    continue;
                }

                if (replaceInfo.lookUpSwitch)
                {
                    //
                    // LookUpSwitch with special offset calculation
                    //

                    throw new Exception("IMPLEMENT ME!");
                }
                else
                {
                    //
                    // Simple jump
                    //

                    int offset = (int)(label.Address - ((uint)replaceInfo.address + 3));

                    buffer.Seek(replaceInfo.address + labelOffset, SeekOrigin.Begin);
                    Primitives.WriteS24(output, offset);
                }
            }

            //
            // Convert stream to byte[]
            //

            buffer.Seek(0, SeekOrigin.Begin);

            BinaryReader reader = new BinaryReader(buffer);

            _code = reader.ReadBytes((int)buffer.Length);

            //
            // Clean up
            //

            reader.Close();
            buffer.Dispose();

            #if DEBUG
            //Console.WriteLine("[i] Done compiling method body ...");
            #endif
        }
Beispiel #26
0
        public void ReadExternal(BinaryReader input)
        {
            _name = Primitives.ReadU30(input);

            _superName = Primitives.ReadU30(input);

            _flags = input.ReadByte();

            if (ClassProtectedNs == (_flags & ClassProtectedNs))
            {
                _protectedNs = Primitives.ReadU30(input);
            }

            uint n = Primitives.ReadU30(input).Value;

            _interface = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                U30 iid = Primitives.ReadU30(input);

                if (0 == iid.Value)
                {
                    throw new VerifyException("Interface must not be 0.");
                }

                _interface.Add(iid);
            }

            _iinit = Primitives.ReadU30(input);

            n = Primitives.ReadU30(input).Value;

            _traits = new ArrayList(Capacity.Max(n));

            for (uint i = 0; i < n; ++i)
            {
                TraitInfo ti = new TraitInfo();
                ti.ReadExternal(input);

                _traits.Add(ti);

            }
        }
Beispiel #27
0
        public static U30 GetMultiname(Abc46 abc, string argument)
        {
            if (argument.StartsWith("#"))
            {
                int index = int.Parse(argument.Substring(1,argument.Length-1));

                if (index < abc.ConstantPool.MultinameTable.Count && index > 0)
                {
                    return (U30)index;
                }

                throw new Exception(String.Format("Invalid multiname {0}", index));
            }

            NamespaceInfo ns;
            NamespaceSetInfo nss;
            StringInfo name;

            bool skipQname = argument.IndexOf("[") == 0;

            if (skipQname)
            {
                //BAD quick dirty hack
                argument = argument.Replace(" ", "");
            }

            string tempName;
            U30 result = new U30();

            for (int i = 1, n = abc.ConstantPool.MultinameTable.Count; i < n; ++i)
            {
                MultinameInfo multiName = (MultinameInfo)abc.ConstantPool.MultinameTable[i];

                switch (multiName.Kind)
                {
                    #region QName, QNameA

                    case MultinameInfo.QName:
                    case MultinameInfo.QNameA:

                        if (skipQname)
                            continue;

                        ns = ((NamespaceInfo)abc.ConstantPool.NamespaceTable[(int)multiName.Data[0].Value]);
                        name = ((StringInfo)abc.ConstantPool.StringTable[(int)multiName.Data[1].Value]);

                        tempName = "";

                        switch (ns.Kind)
                        {
                            case NamespaceInfo.Namespace:
                            case NamespaceInfo.ExplicitNamespace:
                                //TODO implement this
                                //user defined
                                break;
                            case NamespaceInfo.PrivateNs:
                                tempName = "private";
                                break;
                            case NamespaceInfo.ProtectedNamespace:
                                tempName = "protected";
                                break;
                            case NamespaceInfo.StaticProtectedNs:
                                tempName = "protected$";
                                break;
                            case NamespaceInfo.PackageInternalNs:
                                tempName = "internal";
                                break;
                            case NamespaceInfo.PackageNamespace:
                                tempName = "public";
                                break;
                            default:
                                tempName = "*";
                                break;
                        }

                        if (0 != ns.Name.Value)
                        {
                            string namespaceName = ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();
                            if ("" != namespaceName && tempName != "")
                                tempName += "::";
                            tempName += namespaceName;
                        }

                        tempName += "::" + name.ToString();

                        if (tempName == argument)
                        {
                            result.Value = (uint)i;
                            return result;
                        }
                        break;

                    #endregion

                    #region MultinameL, MultinameLA

                    case MultinameInfo.MultinameL:
                    case MultinameInfo.MultinameLA:

                        if (!skipQname)
                            continue;

                        tempName = "[";

                        nss = (NamespaceSetInfo)abc.ConstantPool.NamespaceSetTable[(int)multiName.Data[0].Value];

                        for (int j = 0, m = nss.NamespaceSet.Count; j < m; ++j)
                        {
                            U30 nssNs = (U30)nss.NamespaceSet[j];
                            ns = ((NamespaceInfo)abc.ConstantPool.NamespaceTable[(int)nssNs.Value]);

                            string r2 = "";

                            switch (ns.Kind)
                            {
                                case NamespaceInfo.Namespace:
                                case NamespaceInfo.ExplicitNamespace:
                                    //TODO implement this
                                    //user defined
                                    break;
                                case NamespaceInfo.PrivateNs:
                                    r2 = "private";
                                    break;
                                case NamespaceInfo.ProtectedNamespace:
                                    r2 = "protected";
                                    break;
                                case NamespaceInfo.StaticProtectedNs:
                                    r2 = "protected$";
                                    break;
                                case NamespaceInfo.PackageInternalNs:
                                    r2 = "internal";
                                    break;
                                case NamespaceInfo.PackageNamespace:
                                    r2 = "public";
                                    break;
                                default:
                                    r2 = "*";
                                    break;
                            }

                            tempName += r2 + "::" + ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();

                            if (j != (m-1))
                                tempName += ",";
                        }

                        tempName += "]";

                        if (argument == tempName)
                        {
                            result.Value = (uint)i;
                            return result;
                        }
                        break;

                    #endregion

                    default:
                        continue;
                }
            }

            if (skipQname)
            {
                #region Create MultinameL
                //
                // Create a MultinameL
                //

                // Remove [] from argument
                argument = argument.Substring(1, argument.Length - 2);

                // Get new NamespaceSet index
                U30 setIndex = new U30();
                setIndex.Value = (uint)abc.ConstantPool.NamespaceSetTable.Count;

                // Create MultinameInfo
                MultinameInfo newName = new MultinameInfo();
                newName.Data = new U30[1] { setIndex };
                newName.Kind = MultinameInfo.MultinameL;

                // Create NamespaceSet
                NamespaceSetInfo newSet = new NamespaceSetInfo();
                newSet.NamespaceSet = new ArrayList();

                abc.ConstantPool.NamespaceSetTable.Add(newSet);

                for (int i = 0, n = abc.ConstantPool.NamespaceTable.Count; i < n; ++i)
                {
                    ns = (NamespaceInfo)abc.ConstantPool.NamespaceTable[i];

                    string r2 = "";

                    switch (ns.Kind)
                    {
                        case NamespaceInfo.Namespace:
                        case NamespaceInfo.ExplicitNamespace:
                            //TODO implement this
                            //user defined
                            break;
                        case NamespaceInfo.PrivateNs:
                            r2 = "private";
                            break;
                        case NamespaceInfo.ProtectedNamespace:
                            r2 = "protected";
                            break;
                        case NamespaceInfo.StaticProtectedNs:
                            r2 = "protected$";
                            break;
                        case NamespaceInfo.PackageInternalNs:
                            r2 = "internal";
                            break;
                        case NamespaceInfo.PackageNamespace:
                            r2 = "public";
                            break;
                        default:
                            r2 = "*";
                            break;
                    }

                    r2 += "::" + ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();

                    if (argument.IndexOf(r2) != -1)
                    {
                        U30 nsIndex = new U30();
                        nsIndex.Value = (uint)i;

                        newSet.NamespaceSet.Add(nsIndex);
                    }
                }

                result.Value = (uint)abc.ConstantPool.MultinameTable.Count;
                abc.ConstantPool.MultinameTable.Add(newName);

                #endregion
            }
            else
            {
                #region Create QName

                // Create a QName

                U30 nsIndex = new U30();

                if (argument.IndexOf("::") == argument.LastIndexOf("::"))
                {
                    nsIndex.Value = GetNamespace(abc, argument.Substring(0, argument.LastIndexOf("::") + 2)).Value;
                }
                else
                    nsIndex.Value = GetNamespace(abc, argument.Substring(0, argument.LastIndexOf("::"))).Value;

                MultinameInfo newQName = new MultinameInfo();
                newQName.Data = new U30[2] { nsIndex, (U30)abc.ConstantPool.ResolveString(argument.Substring(argument.LastIndexOf("::") + 2)) };
                newQName.Kind = MultinameInfo.QName;

                result.Value = (uint)abc.ConstantPool.MultinameTable.Count;

                abc.ConstantPool.MultinameTable.Add(newQName);

                #endregion
            }

            return result;
        }
Beispiel #28
0
        public void ReadExternal(BinaryReader input)
        {
            _paramCount = Primitives.ReadU30(input);
            _returnType = Primitives.ReadU30(input);

            _paramType = new ArrayList(Capacity.Max(_paramCount));

            for (uint i = 0; i < _paramCount._value; ++i)
                _paramType.Add(Primitives.ReadU30(input));

            _name = Primitives.ReadU30(input);
            _flags = input.ReadByte();

            if (HasFlag(HasOptional))
            {
                _optionInfo = new OptionInfo();
                _optionInfo.ReadExternal(input);
            }

            if (HasFlag(HasParamNames))
            {
                //param_info { u30 param_name[param_count] }
                _paramName = new ArrayList(Capacity.Max(_paramCount));

                for (uint i = 0; i < _paramCount._value; ++i)
                    _paramName.Add(Primitives.ReadU30(input));
            }
        }
Beispiel #29
0
 public static string ResolveMultiname(Abc46 abc, U30 index)
 {
     return ResolveMultiname(abc, (MultinameInfo)abc.ConstantPool.MultinameTable[(int)index.Value]);
 }
Beispiel #30
0
        public static U30 GetNamespace(Abc46 abc, string argument)
        {
            NamespaceInfo ns;

            for (int i = 0, n = abc.ConstantPool.NamespaceTable.Count; i < n; ++i)
            {
                ns = (NamespaceInfo)abc.ConstantPool.NamespaceTable[i];

                string namespaceString = "";

                switch (ns.Kind)
                {
                    case NamespaceInfo.Namespace:
                    case NamespaceInfo.ExplicitNamespace:
                        //TODO implement this
                        //user defined
                        break;
                    case NamespaceInfo.PrivateNs:
                        namespaceString = "private";
                        break;
                    case NamespaceInfo.ProtectedNamespace:
                        namespaceString = "protected";
                        break;
                    case NamespaceInfo.StaticProtectedNs:
                        namespaceString = "protected$";
                        break;
                    case NamespaceInfo.PackageInternalNs:
                        namespaceString = "internal";
                        break;
                    case NamespaceInfo.PackageNamespace:
                        namespaceString = "public";
                        break;
                    default:
                        namespaceString = "*";
                        break;
                }

                namespaceString += "::" + ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();

                if (argument.IndexOf(namespaceString) != -1)
                {
                    U30 nsIndex = new U30();
                    nsIndex.Value = (uint)i;

                    return nsIndex;
                }
            }

            NamespaceInfo newNs = new NamespaceInfo();

            string name = "";
            byte kind = 0;

            if(0 == argument.IndexOf("private::"))
            {
                kind = NamespaceInfo.PrivateNs;
                name = argument.Substring(8);
            }
            else if (0 == argument.IndexOf("public::"))
            {
                kind = NamespaceInfo.PackageNamespace;
                name = argument.Substring(7);
            }

            newNs.Kind = kind;

            if ("" == name)
                newNs.Name = (U30)0;
            else
                newNs.Name = (U30)abc.ConstantPool.ResolveString(name);

            U30 result = new U30();

            result.Value = (uint)abc.ConstantPool.NamespaceTable.Count;

            abc.ConstantPool.NamespaceTable.Add(newNs);

            return result;
        }
Beispiel #31
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;
        }
Beispiel #32
0
 public override void ReadExternal(BinaryReader input)
 {
     _slotId = Primitives.ReadU30(input);
     _classI = Primitives.ReadU30(input);
 }
Beispiel #33
0
        public static U30 CalcLocalCount(ArrayList instructions)
        {
            ClearFlags();

            int i = 0;
            int n = instructions.Count;

            uint local = 0;
            uint maxLocal = 0;

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

                if (instructions[i] is Instruction)
                {
                    avm2Command = ((Instruction)instructions[i]).Command;
                }
                else if (instructions[i] is AVM2Command)
                {
                    avm2Command = (AVM2Command)instructions[i];
                }
                else if (instructions[i] is Label)
                {
                    ++i;
                    continue;
                }
                else
                {
                    throw new Exception("Unknown instruction type.");
                }

                switch (avm2Command.OpCode)
                {
                    case (byte)Op.Debug:
                        byte type = (byte)avm2Command.Parameters[0];
                        if (1 == type)
                        {
                            local = (byte)avm2Command.Parameters[2] + 1U;
                        }
                        break;
                    case (byte)Op.SetLocal:
                    case (byte)Op.GetLocal:
                        U30 register = (U30)avm2Command.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;

                ++i;
            }

            U30 result = new U30();
            result.Value = maxLocal;

            return result;
        }
Beispiel #34
0
        static void Main(string[] args)
        {
            #if DEBUG
            DateTime start = DateTime.Now;
            #endif
            try
            {
                #region Initialization

                try
                {
                    bool hasMethod = false;

                    if (args.Length < 1)
                    {
                        WriteInfo();
                        Console.WriteLine("[?] Use -help for some instructions.");
                        return;
                    }

                    for (int i = 0, n = args.Length; i < n; ++i)
                    {
                        switch (args[i])
                        {
                            case "-h":
                            case "-help":
                            case "-?":
                            case "/?":
                            case "/help":
                                WriteInfo();
                                Usage();
                                return;

                            // OPTIONS /////////////////////////////////////////////////////////////////////

                            case "-o":
                            case "-output":
                                _pathOutput = args[++i];
                                break;

                            case "-q":
                            case "-quiet":
                                _isQuiet = true;
                                break;

                            // REPLACE ////////////////////////////////////////////////////////////////////

                            case "-r":
                            case "-replace":
                                _action = Action.Replace;
                                break;

                            // REPLACE PROPERTIES ////////////////////////////////////////////////////////

                            case "-sm":
                            case "-static-method":
                                if (hasMethod) throw new Exception("Two methods defined.");
                                _isMethodStatic = true;
                                _methodName = args[++i];
                                break;

                            case "-m":
                            case "-method":
                                if (hasMethod) throw new Exception("Two methods defined.");
                                _isMethodStatic = false;
                                _methodName = args[++i];
                                break;

                            case "-co":
                            case "-constructor":
                                if (hasMethod) throw new Exception("Two methods defined.");
                                _isConstructor = true;
                                _isMethodStatic = false;
                                break;

                            case "-sc":
                            case "-static-constructor":
                                if (hasMethod) throw new Exception("Two methods defined.");
                                _isConstructor = true;
                                _isMethodStatic = true;
                                break;

                            case "-c":
                            case "-class":
                                _className = args[++i];
                                break;

                            case "-n":
                            case "-namespace":
                                _namespace = args[++i];
                                break;

                            // INLINE ///////////////////////////////////////////////////////////////////

                            case "-i":
                            case "-inline":
                                _action = Action.Inline;
                                _pathSwf = args[++i];
                                break;

                            // PATCH ///////////////////////////////////////////////////////////////////
                            case "-optimize":
                                _action = Action.Optimize;
                                _pathSwf = args[++i];
                                break;

                            // DASM ////////////////////////////////////////////////////////////////////

                            case "-d":
                            case "-dasm":
                                _action = Action.Dasm;
                                break;

                            // DASM PROPERTIES ////////////////////////////////////////////////////////

                            case "-a":
                            case "-as3c":
                                _dasmType = Dasm.As3c;
                                break;

                            case "-p":
                            case "-plain":
                                _dasmType = Dasm.Plain;
                                break;

                            default:
                                if (File.Exists(args[i]))
                                {
                                    try
                                    {
                                        BinaryReader fileHead = new BinaryReader(File.Open(args[i], FileMode.Open, FileAccess.Read));

                                        if (fileHead.BaseStream.Length < 3)
                                            throw new Exception("Invalid file given.");

                                        byte[] head = fileHead.ReadBytes(3);

                                        fileHead.Close();

                                        //TODO fix this ugly part...
                                        if ((head[0] == (byte)'C' || head[0] == (byte)'F') && head[1] == (byte)'W' && head[2] == (byte)'S')
                                        {
                                            if (_pathSwf != "")
                                            {
                                                throw new Exception("Two SWF files given.");
                                            }

                                            _pathSwf = args[i];
                                        }
                                        else
                                        {
                                            if ("" != _pathAsm)
                                            {
                                                throw new Exception("Two ASM files given.");
                                            }

                                            _pathAsm = args[i];
                                        }
                                    }
                                    catch (IOException io)
                                    {
                                        WriteInfo();
                                        Console.Error.WriteLine("[-] Error: Can not open file {0}", args[i]);
            #if DEBUG
                                        Console.Error.WriteLine("[-] {0}", io.Message);
            #endif
                                        return;
                                    }
                                    catch (Exception e)
                                    {
                                        WriteInfo();
                                        Console.Error.WriteLine("[-] Error: {0}", e.Message);
            #if DEBUG
                                        Console.Error.WriteLine("[-] {0}", e.StackTrace);
            #endif
                                        return;
                                    }
                                }
                                else
                                {
                                    if (args[i].IndexOf(".") != -1)
                                    {
                                        WriteInfo();
                                        Console.Error.WriteLine("[-] File {0} does not exist.", args[i]);
                                        return;
                                    }
                                    else
                                    {
                                        throw new Exception("Invalid argument given.");
                                    }
                                }
                                break;
                        }
                    }
                }
                catch (Exception e)
                {
                    WriteInfo();
                    Console.Error.WriteLine("[-] Error: Invalid arguments. Use -help for help ...");
            #if DEBUG
                    Console.Error.WriteLine("[-] {0}", e.Message);
                    Console.Error.WriteLine("[-] {0}", e.StackTrace);
            #endif
                    return;
                }

                if (!_isQuiet)
                {
                    Console.WriteLine("[i] As3c - ActionScript3 ASM compiler");
                }

                Translator.InitTable();

                #endregion

                #region Integrity scan for the Translator class (DEBUG only)

            #if DEBUG
                if (Translator.CheckIntegrity())
                {
                    if (!_isQuiet)
                    {
                        Console.WriteLine("[+] Integrity scan passed!");
                    }
                }
                else
                {
                    Console.WriteLine("[-] Integrity scan failed...!");
                }
            #endif

                #endregion

                FileStream fileInput;
                FileStream fileOutput;
                SwfFormat swf;

                switch (_action)
                {
                    case Action.Dasm:

                        #region Disassemble file

                        swf = new SwfFormat();
                        fileInput = File.Open(_pathSwf, FileMode.Open, FileAccess.Read);

                        swf.Read(fileInput);

                        fileInput.Close();
                        fileInput.Dispose();

                        DisassemblerBase dasm;

                        switch (_dasmType)
                        {
                            case Dasm.As3c:
                                dasm = new DisassemblerAs3c();
                                break;

                            case Dasm.Plain:
                                dasm = new DisassemblerPlain();
                                break;

                            default:
                                throw new Exception();
                        }

                        dasm.Parse(swf);

                        if ("" == _pathOutput)
                        {
                            dasm.EmitToConsole();
                        }
                        else
                        {
                            fileOutput = File.Open(_pathOutput, FileMode.OpenOrCreate, FileAccess.Write);
                            dasm.EmitToStream(fileOutput);

                            fileOutput.Close();
                            fileOutput.Dispose();
                        }

                        #endregion

                        break;

                    case Action.Optimize:

                        #region Optimize SWF

                        swf = new SwfFormat();
                        fileInput = File.Open(_pathSwf, FileMode.Open, FileAccess.Read);

                        swf.Read(fileInput);

                        fileInput.Close();
                        fileInput.Dispose();

                        CompilerOptimize compOptimize = new CompilerOptimize(swf);

                        compOptimize.Compile();

                        fileOutput = File.Open((_pathOutput != "") ? _pathOutput : _pathSwf, FileMode.OpenOrCreate, FileAccess.Write);

                        swf.Write(fileOutput);

                        fileOutput.Close();
                        fileOutput.Dispose();

                        #endregion

                        break;

                    case Action.Inline:

                        #region Compile inline instructions

                        swf = new SwfFormat();
                        fileInput = File.Open(_pathSwf, FileMode.Open, FileAccess.Read);

                        swf.Read(fileInput);

                        fileInput.Close();
                        fileInput.Dispose();

                        CompilerInline compInline = new CompilerInline(swf);
                        compInline.Compile();

                        fileOutput = File.Open((_pathOutput != "") ? _pathOutput : _pathSwf, FileMode.OpenOrCreate, FileAccess.Write);

                        swf.Write(fileOutput);

                        fileOutput.Close();
                        fileOutput.Dispose();

                        #endregion

                        break;

                    case Action.Replace:

                        #region Replace method body

                        #region Simple pre-check

                        if ("" == _pathAsm || !File.Exists(_pathAsm))
                        {
                            Console.Error.WriteLine("[-] No valid ASM input given.");
                            return;
                        }

                        if ("" == _pathSwf || !File.Exists(_pathSwf))
                        {
                            Console.Error.WriteLine("[-] No valid SWF target given.");
                            return;
                        }

                        if ("" == _className)
                        {
                            Console.Error.WriteLine("[-] No class given.");
                            return;
                        }

                        if (!_isConstructor)
                        {
                            if ("" == _methodName)
                            {
                                Console.Error.WriteLine("[-] Need method name or constructor to replace");
                                return;
                            }
                        }

                        #endregion

                        swf = new SwfFormat();
                        fileInput = File.Open(_pathSwf, FileMode.Open, FileAccess.Read);

                        swf.Read(fileInput);

                        fileInput.Close();
                        fileInput.Dispose();

                        #region Body lookup

                        Abc46 abc = null;
                        SwfLibrary.Abc.MethodInfo method = null;
                        MethodBodyInfo body = null;
                        bool instanceFound = false;
                        Abc46 currentAbc = null;

                        string classFormat;

                        if (_className.IndexOf(".") != -1)
                        {
                            classFormat = "public::" + _className.Substring(0, _className.LastIndexOf(".")) + "::" + _className.Substring(_className.LastIndexOf(".") + 1, _className.Length - _className.LastIndexOf(".") - 1);
                        }
                        else
                        {
                            classFormat = "public::" + _className;
                        }

                        string methodFormat = _namespace + "::" + _methodName;

                        // Parse for all possibilities
                        for (int i = 0, n = swf.AbcCount; i < n; ++i)
                        {
                            currentAbc = swf.GetAbcAt(i);

                            for (int j = 0, m = currentAbc.Scripts.Count; j < m; ++j)
                            {
                                ScriptInfo script = (ScriptInfo)currentAbc.Scripts[j];

                                for (int k = 0, o = script.Traits.Count; k < o; ++k)
                                {
                                    TraitInfo scriptTrait = (TraitInfo)script.Traits[k];

                                    if (!(scriptTrait.Body is TraitClass))
                                    {
                                        continue;
                                    }

                                    TraitClass classBody = (TraitClass)scriptTrait.Body;
                                    ClassInfo classInfo = (ClassInfo)currentAbc.Classes[(int)classBody.ClassI];
                                    InstanceInfo instanceInfo = (InstanceInfo)currentAbc.Instances[(int)classBody.ClassI];

                                    string instanceName = NameUtil.ResolveMultiname(currentAbc, instanceInfo.Name);

                                    if (classFormat == instanceName)
                                    {
                                        instanceFound = true;

                                        if (!_isQuiet)
                                            Console.WriteLine("[+] Found class {0}", instanceName);

                                        if (_isMethodStatic)
                                        {
                                            if (_isConstructor)
                                            {
                                                if (null != body)
                                                {
                                                    Console.Error.WriteLine("[-] Can not explicitly determine method body.");
                                                    return;
                                                }

                                                method = (SwfLibrary.Abc.MethodInfo)currentAbc.Methods[(int)classInfo.CInit];

                                                body = FindBody(currentAbc, classInfo.CInit);

                                                abc = currentAbc;

                                                if (null != body)
                                                {
                                                    if (!_isQuiet)
                                                        Console.WriteLine("[+] Found static class initializer.");
                                                }
                                            }
                                            else
                                            {
                                                Console.Error.WriteLine("[-] Sorry, static methods do not work yet ...");
                                                return;
                                                //TODO support static methods...
                                            }
                                        }
                                        else
                                        {
                                            if (_isConstructor)
                                            {
                                                if (null != body)
                                                {
                                                    Console.Error.WriteLine("[-] Can not explicitly determine method body.");
                                                    return;
                                                }

                                                method = (SwfLibrary.Abc.MethodInfo)currentAbc.Methods[(int)instanceInfo.IInit];

                                                body = FindBody(currentAbc, instanceInfo.IInit);

                                                abc = currentAbc;

                                                if (null != body)
                                                {
                                                    if (!_isQuiet)
                                                        Console.WriteLine("[+] Found class initializer.");
                                                }
                                            }
                                            else
                                            {
                                                // here begins the ugly part ...
                                                for (int l = 0, p = instanceInfo.Traits.Count; l < p; ++l)
                                                {
                                                    TraitInfo instanceTrait = (TraitInfo)instanceInfo.Traits[l];

                                                    if (!(instanceTrait.Body is TraitMethod))
                                                    {
                                                        continue;
                                                    }

                                                    string methodName = NameUtil.ResolveMultiname(currentAbc, instanceTrait.Name);

                                                    if ("" == _namespace)
                                                    {
                                                        if ("public::" + _methodName != methodName &&
                                                            "private::" + _methodName != methodName &&
                                                            "protected::" + _methodName != methodName &&
                                                            "protected$::" + _methodName != methodName &&
                                                            "internal::" + _methodName != methodName)
                                                        {
                                                            continue;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        if (methodName != methodFormat)
                                                        {
                                                            continue;
                                                        }
                                                    }

                                                    if (null != body)
                                                    {
                                                        Console.Error.WriteLine("[-] Can not explicitly determine method body.");
                                                        return;
                                                    }

                                                    TraitMethod methodBody = (TraitMethod)instanceTrait.Body;

                                                    method = (SwfLibrary.Abc.MethodInfo)currentAbc.Methods[(int)methodBody.Method];

                                                    body = FindBody(currentAbc, methodBody.Method);

                                                    abc = currentAbc;

                                                    if (null != body)
                                                    {
                                                        if (!_isQuiet)
                                                            Console.WriteLine("[+] Found method {0}", methodName);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (null == body)
                        {
                            Console.Error.WriteLine("[-] Could not find {0}.", (instanceFound) ? "method" : "class");
                            return;
                        }

                        #endregion

                        //
                        // We have valid body to replace. Start the parser.
                        //

                        ParserAs3c parser = new ParserAs3c();
                        parser.Parse(_pathAsm);

                        //
                        // Convert the parser instructions to actual bytecode for the AVM2.
                        //

                        CompilerAs3c compAs3c = new CompilerAs3c();
                        compAs3c.Compile(currentAbc, parser.Instructions, parser.Labels, false);

                        //
                        // Get body information (maxstack, localcount, maxscopedepth, initscopedepth)
                        // We keep compiler directives in respect here ...
                        //

                        #region MethodBody information

                        U30 maxStack;
                        U30 maxScopeDepth;
                        U30 localCount;
                        U30 initScopeDepth = new U30();

                        if (parser.HasMaxStack)
                        {
                            maxStack = new U30();
                            maxStack.Value = parser.MaxStack;
                        }
                        else
                        {
                            maxStack = ByteCodeAnalyzer.CalcMaxStack(compAs3c.Code);

                            if (maxStack.Value < method.ParameterCount.Value)
                            {
                                maxStack.Value = method.ParameterCount.Value;
                            }
                        }

                        if (parser.HasLocalCount)
                        {
                            localCount = new U30();
                            localCount.Value = parser.LocalCount;
                        }
                        else
                        {
                            localCount = ByteCodeAnalyzer.CalcLocalCount(compAs3c.Code);
                        }

                        if (parser.HasInitScopeDepth)
                        {
                            initScopeDepth.Value = parser.InitScopeDepth;
                        }
                        else
                        {
                            initScopeDepth.Value = 1;
                        }

                        if (parser.HasMaxScopeDepth)
                        {
                            maxScopeDepth = new U30();
                            maxScopeDepth.Value = parser.MaxScopeDepth;
                        }
                        else
                        {
                            maxScopeDepth = ByteCodeAnalyzer.CalcScopeDepth(compAs3c.Code);
                            maxScopeDepth.Value += initScopeDepth.Value;
                        }

                        if (!_isQuiet)
                        {
                            Console.WriteLine("[i] InitScopeDepth: {0}", (int)initScopeDepth);
                            Console.WriteLine("[i] MaxScopeDepth: {0}", (int)maxScopeDepth);
                            Console.WriteLine("[i] MaxStack: {0}", (int)maxStack);
                            Console.WriteLine("[i] LocalCount: {0}", (int)localCount);
                        }

                        #endregion

                        //
                        // Replace the code of the body.
                        //

                        body.Code = compAs3c.Code;

                        //
                        // Update body information
                        //

                        body.MaxStack = maxStack;
                        body.MaxScopeDepth = maxScopeDepth;
                        body.InitScopeDepth = initScopeDepth;
                        body.LocalCount = localCount;

                        #region Write output

                        if ("" == _pathOutput)
                        {
                            fileOutput = File.Open(_pathSwf, FileMode.OpenOrCreate, FileAccess.Write);
                        }
                        else
                        {
                            fileOutput = File.Open(_pathOutput, FileMode.OpenOrCreate, FileAccess.Write);
                        }

                        swf.Write(fileOutput);

                        fileOutput.Close();
                        fileOutput.Dispose();

                        #endregion

                        #endregion

                        break;

                    case Action.Usage:
                        Usage();
                        break;
                }

                #region Program end

                if (!_isQuiet)
                {
                    Console.WriteLine("[i] Done.");
                }
                #endregion
            }
            catch (IOException ioex)
            {
                Console.Error.WriteLine("[-] Error: {0}", ioex.Message);
            }
            catch (InstructionException iex)
            {
                #region Parser errors

                string message;

                switch (iex.ErrorType)
                {
                    case InstructionException.Type.InvalidSyntax:
                        message = "Error while parsing";
                        break;
                    case InstructionException.Type.NotEnoughArguments:
                        message = "Not enough arguments";
                        break;
                    case InstructionException.Type.TooManyArguments:
                        message = "Too many arguments";
                        break;
                    case InstructionException.Type.UnknownType:
                        message = "Unknown type";
                        break;
                    case InstructionException.Type.LabelRedefined:
                        message = "Label has already been defined";
                        break;
                    case InstructionException.Type.LabelMissing:
                        message = "Label has never been defined";
                        break;
                    default:
                        message = "Unknown error at";
                        break;
                }

                Console.Error.WriteLine("[-] " + message + ":");

                if (null != iex.ParserInfo)
                {
                    Console.Error.WriteLine("{0}({1}): {2}", iex.ParserInfo.FilePath, iex.ParserInfo.LineNumber, iex.ParserInfo.Line);
                }

                #endregion
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine("[-] Unexpected error: {0}", ex.Message);
            #if DEBUG
                Console.Error.WriteLine("[-] Stacktrace: {0}", ex.StackTrace);
            #endif
            }

            #if DEBUG
            DateTime end = DateTime.Now;
            TimeSpan delta = end - start;

            Console.WriteLine("[i] Total: {0}sec {1}ms", delta.Seconds, delta.Milliseconds);
            #endif
        }
Beispiel #35
0
 public static int Max(U30 count)
 {
     return(Max((uint)count));
 }
Beispiel #36
0
        public void ReadExternal(BinaryReader input)
        {
            _name = Primitives.ReadU30(input);

            if (0 == (uint)_name)
            {
                throw new VerifyException("Name must not be 0.");
            }

            _kind = input.ReadByte();

            _type = (byte)(_kind & 0xf);
            _attr = (byte)((_kind >> 4) & 0xf);

            switch (_type)
            {
            case TraitSlot:
                _body = new TraitSlot(this);
                break;

            case TraitConst:
                _body = new TraitConst(this);
                break;

            case TraitClass:
                _body = new TraitClass(this);
                break;

            case TraitFunction:
                _body = new TraitFunction(this);
                break;

            case TraitMethod:
                _body = new TraitMethod(this);
                break;

            case TraitGetter:
                _body = new TraitGetter(this);
                break;

            case TraitSetter:
                _body = new TraitSetter(this);
                break;

            default:
                throw new VerifyException("Unexpected trait body.");
            }

            _body.ReadExternal(input);

            if (AttributeMetadata == (_attr & AttributeMetadata))
            {
                uint n = Primitives.ReadU30(input).Value;

                _metadata = new ArrayList(Capacity.Max(n));

                for (uint i = 0; i < n; ++i)
                {
                    _metadata.Add(Primitives.ReadU30(input));
                }
            }
        }
Beispiel #37
0
        protected void FormatMethod(U30 method)
        {
            MethodInfo methodInfo = (MethodInfo)_abc.Methods[(int)method];
            MethodBodyInfo methodBody = null;

            int bodyIndex = 0;

            for (int i = 0, n = _abc.MethodBodies.Count; i < n; ++i)
            {
                methodBody = (MethodBodyInfo)_abc.MethodBodies[i];

                if (methodBody.Method.Value == method.Value)
                {
                    bodyIndex = i;
                    break;
                }
            }

            _output.Add(String.Format(";body{0}\r\n",bodyIndex));
            FormatBody(methodBody);
        }
Beispiel #38
0
        private void PatchBody(Abc46 abc, MethodBodyInfo body, int bodyId)
        {
            AVM2Command command;
            AVM2Command inlineCommand;
            Dictionary <string, Label> labels = new Dictionary <string, Label>();
            ArrayList instructions            = new ArrayList();
            Label     label;
            string    labelId;

            byte[] il = body.Code;

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

            uint addr;

            string name;

            bool patchBody  = false;
            bool ignoreBody = false;

            _labelUtil.Clear();

            while (i < n)
            {
                addr = i;

                if (_labelUtil.IsMarked(addr))
                {
                    labelId = String.Format(":{0}:", _labelUtil.GetLabelAt(addr).id);
                    label   = new Label(labelId);

                    labels.Add(labelId, label);
                    instructions.Add(label);
                }

                command = Translator.ToCommand(il[i++]);

                if (null == command)
                {
                    throw new Exception("Unknown opcode detected.");
                }

                i += command.ReadParameters(il, i);

                switch (command.OpCode)
                {
                case (byte)Op.Label:
                    labelId = String.Format(":{0}:", _labelUtil.GetLabelAt(addr).id);
                    label   = new Label(labelId);
                    labels.Add(labelId, label);
                    instructions.Add(label);
                    break;

                case (byte)Op.IfEqual:
                case (byte)Op.IfFalse:
                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:
                case (byte)Op.IfTrue:
                case (byte)Op.Jump:
                    S24 offset = (S24)command.Parameters[0];
                    command.Parameters[0] = String.Format(":{0}:", _labelUtil.GetLabelAt((uint)(addr + 1 + offset.Length + offset.Value)).id);
                    instructions.Add(command);
                    break;

                case (byte)Op.GetLex:
                    name = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)command.Parameters[0]).Value]));
                    if ("public::Math" == name || "Math" == name)
                    {
                        patchBody = true;
                    }
                    instructions.Add(command);
                    break;

                case (byte)Op.LookupSwitch:
                    ignoreBody = true;
                    instructions.Add(command);
                    break;

                default:
                    instructions.Add(command);
                    break;
                }
            }

            if (ignoreBody)
            {
#if DEBUG
                Console.WriteLine("[-] Have to ignore body because of lookupswitch ...");
#endif
            }

            if (patchBody && !ignoreBody)
            {
                //
                // We have to patch this function ...
                // Note: We do not change the initScopeDepth
                //

#if DEBUG
                Console.WriteLine("[i] Patching body (id: {0})", bodyId);
#endif
                CompilerAs3c compAs3c = new CompilerAs3c();

                compAs3c.Compile(abc, instructions, labels, true);

                // Now .. only patch if we find a correct stack!

                U30 maxStack = maxStack = ByteCodeAnalyzer.CalcMaxStack(compAs3c.Code);

                if (0 == (ByteCodeAnalyzer.Flags & ByteCodeAnalyzer.InvalidStack))
                {
                    MethodInfo method = (MethodInfo)abc.Methods[(int)body.Method.Value];

                    body.MaxStack      = maxStack;
                    body.MaxScopeDepth = body.InitScopeDepth + ByteCodeAnalyzer.CalcScopeDepth(compAs3c.Code);

                    U30 minLocalCount = method.ParameterCount;
                    U30 maxLocalCount = ByteCodeAnalyzer.CalcLocalCount(compAs3c.Code);

                    if (maxLocalCount.Value > minLocalCount.Value)
                    {
                        body.LocalCount = ByteCodeAnalyzer.CalcLocalCount(compAs3c.Code);
                    }
                    //else <- we would have unused parameters in a function...

                    body.Code = compAs3c.Code;
                }
                else
                {
                    //
                    // What else? We will display warnings automatically but what about
                    // telling the guy in which function he has an invalid stack?
                    //
                }

#if DEBUG
                Console.WriteLine("[+] Body patched");
#endif
            }
        }
Beispiel #39
0
 public static string ResolveMultiname(Abc46 abc, U30 index)
 {
     return(ResolveMultiname(abc, (MultinameInfo)abc.ConstantPool.MultinameTable[(int)index.Value]));
 }
Beispiel #40
0
        protected void PatchBody(Abc46 abc, MethodBodyInfo body, int bodyId)
        {
            AVM2Command command;
            AVM2Command inlineCommand;
            Dictionary <string, Label> labels = new Dictionary <string, Label>();
            ArrayList instructions            = new ArrayList();
            Label     label;
            string    labelId;

            byte[] il = body.Code;

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

            uint addr;

            string name;

            bool hasManualMaxStack   = false;
            uint manualMaxStackValue = 0;

            bool patchBody = false;

            //bool parseInline = false;

            _labelUtil.Clear();


            //
            // We will convert the bytecode into a format that the As3c compiler can understand.
            // When converting labels we will use a ':' in front of them instead of a '.' char for
            // the ones "defined" by the ASC so that we have unique names (label syntax is .label)
            //

            while (i < n)
            {
                addr = i;

                if (_labelUtil.IsMarked(addr))
                {
                    labelId = String.Format(":{0}:", _labelUtil.GetLabelAt(addr).id);
                    label   = new Label(labelId);

                    labels.Add(labelId, label);
                    instructions.Add(label);
                }

                command = Translator.ToCommand(il[i++]);

                if (null == command)
                {
                    throw new Exception("Unknown opcode detected.");
                }

                i += command.ReadParameters(il, i);

                switch (command.OpCode)
                {
                case (byte)Op.Label:

                    labelId = String.Format(":{0}:", _labelUtil.GetLabelAt(addr).id);
                    label   = new Label(labelId);

                    labels.Add(labelId, label);
                    instructions.Add(label);

                    break;

                case (byte)Op.IfEqual:
                case (byte)Op.IfFalse:
                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:
                case (byte)Op.IfTrue:
                case (byte)Op.Jump:
                    // Convert label offset to label reference ...
                    S24 offset = (S24)command.Parameters[0];
                    command.Parameters[0] = String.Format(":{0}:", _labelUtil.GetLabelAt((uint)(addr + 1 + offset.Length + offset.Value)).id);
                    instructions.Add(command);
                    break;

                case (byte)Op.GetLex:
                    name = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)command.Parameters[0]).Value]));
                    //Console.WriteLine("Called GetLex {0}", name);
                    instructions.Add(command);
                    break;

                case (byte)Op.FindPropertyStrict:
                    name = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)command.Parameters[0]).Value]));
                    #region INLINE Block
                    if (inlineWrapper == name)
                    {
                        bool parse = true;
                        patchBody = true;

#if DEBUG
                        Console.WriteLine("[i] Parsing inline block in method {0}", body.Method.Value);
#endif
                        while (parse && i < n)
                        {
                            inlineCommand = Translator.ToCommand(il[i++]);

                            if (null == inlineCommand)
                            {
                                throw new Exception("Unknown opcode detected.");
                            }

                            i += inlineCommand.ReadParameters(il, i);

                            switch (inlineCommand.OpCode)
                            {
                            //
                            // Debug instructions are kept even if they are in an inline block
                            //

                            case (byte)Op.Debug:
                            case (byte)Op.DebugFile:
                            case (byte)Op.DebugLine:
                                instructions.Add(inlineCommand);
                                break;

                            //
                            // Strings are treated as labels -- but make sure it is actually one!
                            //

                            case (byte)Op.PushString:

                                labelId = ((StringInfo)abc.ConstantPool.StringTable[(int)((U30)inlineCommand.Parameters[0])]).ToString();

                                if (labelId.IndexOf('.') != 0 || labelId.IndexOf(':') != (labelId.Length - 1))
                                {
                                    throw new Exception(String.Format("Invalid string \"{0}\" in an inline block. Labels have the format \".labelName:\"", labelId));
                                }

                                labelId = labelId.Substring(0, labelId.Length - 1);
                                label   = new Label(labelId);

                                labels.Add(labelId, label);
                                instructions.Add(label);
                                break;

                            //
                            // GetLex is the one that will bring public::de.popforge.asm::Op on the stack
                            //

                            case (byte)Op.GetLex:
                                name = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)inlineCommand.Parameters[0]).Value]));

                                if (inlineKeyword != name)
                                {
                                    throw new Exception("Malformed inline block. GetLex call with invalid parameters");
                                }

                                List <AVM2Command> args        = new List <AVM2Command>();
                                AVM2Command        userCommand = null;
                                uint argc;

                                while (i < n)
                                {
                                    AVM2Command arg = Translator.ToCommand(il[i++]);

                                    if (null == arg)
                                    {
                                        throw new Exception("Unknown opcode detected.");
                                    }

                                    i += arg.ReadParameters(il, i);

                                    if ((byte)Op.CallProperty == arg.OpCode)
                                    {
                                        name        = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)arg.Parameters[0]).Value]));
                                        userCommand = Translator.ToCommand(name, true);
                                        argc        = ((U30)arg.Parameters[1]).Value;

                                        if (null == userCommand)
                                        {
                                            throw new Exception(String.Format("Unknown command {0}.", name));
                                        }

                                        break;
                                    }

                                    args.Add(arg);
                                }

                                if (null == userCommand)
                                {
                                    throw new Exception("Malformed inline block.");
                                }

                                instructions.Add(new Instruction(abc, userCommand, args));

                                break;

                            case (byte)Op.CallPropertyVoid:
                                name = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)inlineCommand.Parameters[0]).Value]));
                                if (inlineWrapper == name)
                                {
                                    parse = false;
                                }
                                else
                                {
                                    throw new Exception("Malformed inline block. Method calls are not accepted ...");
                                }
                                break;
                            }
                        }

#if DEBUG
                        Console.WriteLine("[+] Inline block parsed");
#endif
                    }
                    #endregion
                    #region INLINE Marker
                    else if (inlineMarker == name)
                    {
#if DEBUG
                        Console.WriteLine("[i] Body {0} has been marked as inline", body.Method.Value);
#endif

                        bool parse = true;

                        while (parse && i < n)
                        {
                            inlineCommand = Translator.ToCommand(il[i++]);

                            if (null == inlineCommand)
                            {
                                throw new Exception("Unknown opcode detected.");
                            }

                            i += inlineCommand.ReadParameters(il, i);

                            switch (inlineCommand.OpCode)
                            {
                            case (byte)Op.CallPropertyVoid:
                                name = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)inlineCommand.Parameters[0]).Value]));
                                if (inlineMarker == name)
                                {
                                    parse = false;
                                }
                                else
                                {
                                    throw new Exception("Malformed inline block. Method calls are not accepted ...");
                                }
                                break;
                            }
                        }

#if DEBUG
                        Console.WriteLine("[+] Inline marker parsed.");
#endif
                        patchBody = true;
                    }
                    #endregion
                    #region MAX_STACK Marker
                    else if (inlineMaxStack == name)
                    {
#if DEBUG
                        Console.WriteLine("[i] Body {0} has a manual maximum stack set.", body.Method.Value);
#endif

                        bool parse = true;

                        uint maxStackValue = 0;
                        bool hasMaxValue   = false;

                        while (parse && i < n)
                        {
                            inlineCommand = Translator.ToCommand(il[i++]);

                            if (null == inlineCommand)
                            {
                                throw new Exception("Unknown opcode detected.");
                            }

                            i += inlineCommand.ReadParameters(il, i);

                            switch (inlineCommand.OpCode)
                            {
                            case (byte)Op.PushByte:
                                maxStackValue = (uint)((byte)inlineCommand.Parameters[0]);
                                hasMaxValue   = true;
                                break;

                            case (byte)Op.PushShort:
                                maxStackValue = (uint)((U30)inlineCommand.Parameters[0]);
                                hasMaxValue   = true;
                                break;

                            case (byte)Op.PushInt:
                                maxStackValue = (uint)((S32)abc.ConstantPool.IntTable[(int)((U30)inlineCommand.Parameters[0]).Value]).Value;
                                hasMaxValue   = true;
                                break;

                            case (byte)Op.PushDouble:
                                throw new Exception("Max stack has to be an integer constant.");

                            case (byte)Op.CallPropertyVoid:

                                name = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)inlineCommand.Parameters[0]).Value]));

                                if (inlineMaxStack == name)
                                {
                                    parse = false;
                                }
                                else
                                {
                                    throw new Exception("Malformed inline block. Method calls are not accepted ...");
                                }
                                break;
                            }
                        }

#if DEBUG
                        Console.WriteLine("[+] MaxStack marker parsed.");
#endif
                        if (hasMaxValue)
                        {
                            hasManualMaxStack   = true;
                            manualMaxStackValue = maxStackValue;
                        }

                        patchBody = true;
                    }
                    #endregion
                    else
                    {
                        instructions.Add(command);
                    }
                    break;

                default:
                    instructions.Add(command);
                    break;
                }
            }

            if (patchBody)
            {
                //
                // We have to patch this function ...
                // Note: We do not change the initScopeDepth
                //

#if DEBUG
                Console.WriteLine("[i] Patching body (id: {0})", bodyId);
#endif
                CompilerAs3c compAs3c = new CompilerAs3c();

                compAs3c.Compile(abc, instructions, labels, false);

                // Now .. only patch if we find a correct stack!

                U30 maxStack;

                if (!hasManualMaxStack)
                {
                    maxStack = ByteCodeAnalyzer.CalcMaxStack(compAs3c.Code);
                }
                else
                {
                    maxStack = (U30)manualMaxStackValue;
                }

                if (hasManualMaxStack || 0 == (ByteCodeAnalyzer.Flags & ByteCodeAnalyzer.InvalidStack))
                {
                    MethodInfo method = (MethodInfo)abc.Methods[(int)body.Method.Value];

                    body.MaxStack      = maxStack;
                    body.MaxScopeDepth = body.InitScopeDepth + ByteCodeAnalyzer.CalcScopeDepth(compAs3c.Code);

                    U30 minLocalCount = method.ParameterCount;
                    U30 maxLocalCount = ByteCodeAnalyzer.CalcLocalCount(compAs3c.Code);

                    if (maxLocalCount.Value > minLocalCount.Value)
                    {
                        body.LocalCount = ByteCodeAnalyzer.CalcLocalCount(compAs3c.Code);
                    }
                    //else <- we would have unused parameters in a function...

                    body.Code = compAs3c.Code;
                }
                else
                {
                    //
                    // What else? We will display warnings automatically but what about
                    // telling the guy in which function he has an invalid stack?
                    //
                }

#if DEBUG
                Console.WriteLine("[+] Body patched");
#endif
            }
        }
Beispiel #41
0
        /**
         * HERE STARTS THE SPAGHETTI CODE
         */
        public static string ResolveMultiname(Abc46 abc, MultinameInfo multiName)
        {
            NamespaceInfo    ns;
            NamespaceSetInfo nss;
            StringInfo       name;

            string result;

            switch (multiName.Kind)
            {
            case MultinameInfo.RTQName:
            case MultinameInfo.RTQNameA:
                //Console.WriteLine("[-] RTQName/RTQNameA is currently not supported.");
                return(((StringInfo)abc.ConstantPool.StringTable[(int)multiName.Data[0].Value]).ToString());

            case MultinameInfo.QName:
            case MultinameInfo.QNameA:
                ns   = ((NamespaceInfo)abc.ConstantPool.NamespaceTable[(int)multiName.Data[0].Value]);
                name = ((StringInfo)abc.ConstantPool.StringTable[(int)multiName.Data[1].Value]);

                result = "";

                switch (ns.Kind)
                {
                case NamespaceInfo.Namespace:
                case NamespaceInfo.ExplicitNamespace:
                    //TODO implement this
                    //user defined
                    break;

                case NamespaceInfo.PrivateNs:
                    result = "private";
                    break;

                case NamespaceInfo.ProtectedNamespace:
                    result = "protected";
                    break;

                case NamespaceInfo.StaticProtectedNs:
                    result = "protected$";
                    break;

                case NamespaceInfo.PackageInternalNs:
                    result = "internal";
                    break;

                case NamespaceInfo.PackageNamespace:
                    result = "public";
                    break;

                default:
                    result = "*";
                    break;
                    //throw new VerifyException("Unexpected namespace kind.");
                }

                if (0 != ns.Name.Value)
                {
                    string namespaceName = ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString();
                    if ("" != namespaceName && result != "")
                    {
                        result += "::";
                    }
                    result += namespaceName;
                }

                result += "::" + name.ToString();

                return(result);

            case MultinameInfo.RTQNameL:
            case MultinameInfo.RTQNameLA:
                Console.WriteLine("[-] RTQNameL/RTQameLA is currently not supported.");
                return("");

            case MultinameInfo.Multiname_:
            case MultinameInfo.MultinameA:
                //TODO fix this -- what about the namespace set here?
                //Console.WriteLine("[-] Multiname/MultinameA is currently not supported.");

                name = ((StringInfo)abc.ConstantPool.StringTable[(int)multiName.Data[0].Value]);
                nss  = ((NamespaceSetInfo)abc.ConstantPool.NamespaceSetTable[(int)multiName.Data[1].Value]);

                return(name.ToString());;

            case MultinameInfo.MultinameL:
            case MultinameInfo.MultinameLA:
                //Console.WriteLine("[-] MultinameL/MultinameLA is currently not supported.")
                nss = ((NamespaceSetInfo)abc.ConstantPool.NamespaceSetTable[(int)multiName.Data[0].Value]);
                string set = "[";
                for (int i = 0, n = nss.NamespaceSet.Count; i < n; ++i)
                {
                    U30 nssNs = (U30)nss.NamespaceSet[i];
                    ns = ((NamespaceInfo)abc.ConstantPool.NamespaceTable[(int)nssNs.Value]);

                    string r2 = "";

                    switch (ns.Kind)
                    {
                    case NamespaceInfo.Namespace:
                    case NamespaceInfo.ExplicitNamespace:
                        //TODO implement this
                        //user defined
                        break;

                    case NamespaceInfo.PrivateNs:
                        r2 = "private";
                        break;

                    case NamespaceInfo.ProtectedNamespace:
                        r2 = "protected";
                        break;

                    case NamespaceInfo.StaticProtectedNs:
                        r2 = "protected$";
                        break;

                    case NamespaceInfo.PackageInternalNs:
                        r2 = "internal";
                        break;

                    case NamespaceInfo.PackageNamespace:
                        r2 = "public";
                        break;

                    default:
                        r2 = "*";
                        break;
                    }

                    set += String.Format("{0}::{1}", r2, ((StringInfo)abc.ConstantPool.StringTable[(int)ns.Name.Value]).ToString());

                    if (i != n - 1)
                    {
                        set += ", ";
                    }
                }

                set += "]";

                return(set);

            default:
                return("*");
                //throw new VerifyException("Unknown multiname kind.");
            }
        }
Beispiel #42
0
 public override void ReadExternal(BinaryReader input)
 {
     _dispId = Primitives.ReadU30(input);
     _method = Primitives.ReadU30(input);
 }
Beispiel #43
0
 public override void ReadExternal(BinaryReader input)
 {
     _slotId = Primitives.ReadU30(input);
     _classI = Primitives.ReadU30(input);
 }
Beispiel #44
0
        protected void FormatCommand(uint address, AVM2Command cmd)
        {
            string output = "";

            //output += String.Format("{0:X4}\t", address);

            //output += String.Format("{0}\t", address);

            if (((byte)Op.Label == cmd.OpCode) || _labels.IsMarked(address))
            {
                output += String.Format("\r\n.label{0}:\r\n", _labels.GetLabelAt(address).id);
            }

            output += "\t" + cmd.StringRepresentation + "\t\t";

            if (cmd.StringRepresentation.Length < 8)
            {
                output += "\t";
            }

            int n = cmd.Parameters.Count;
            int m = n - 1;

            switch (cmd.OpCode)
            {
            // Param 1: U30 -> Multiname
            case (byte)Op.AsType:
            case (byte)Op.Coerce:
            case (byte)Op.DeleteProperty:
            case (byte)Op.FindProperty:
            case (byte)Op.FindPropertyStrict:
            case (byte)Op.GetDescendants:
            case (byte)Op.GetLex:

            case (byte)Op.GetSuper:
            case (byte)Op.InitProperty:
            case (byte)Op.IsType:
            case (byte)Op.SetProperty:
                output += NameUtil.ResolveMultiname(_abc, GetMultiname(cmd, 0));
                break;

            case (byte)Op.GetProperty:
                output += NameUtil.ResolveMultiname(_abc, GetMultiname(cmd, 0));
                break;

            // Param 1: U30 -> Multiname
            // Param 2: Param count
            case (byte)Op.CallProperty:
            case (byte)Op.CallPropertyLex:
            case (byte)Op.CallPropertyVoid:
            case (byte)Op.CallSuper:
            case (byte)Op.CallSuperVoid:
            case (byte)Op.ConstructProperty:
                output += NameUtil.ResolveMultiname(_abc, GetMultiname(cmd, 0));
                output += ", " + ((U30)cmd.Parameters[1]).Value.ToString();
                break;

            // Param 1: U30 -> MethodInfo
            // Param 2: Param count
            case (byte)Op.CallStatic:
                output += ((StringInfo)(_abc.ConstantPool.StringTable[(int)GetMethod(cmd, 0).Name.Value])).ToString();
                output += ", " + ((U30)cmd.Parameters[1]).Value.ToString();
                break;

            // Param 1: U30 -> InstanceInfo
            case (byte)Op.NewClass:
                InstanceInfo ii = (InstanceInfo)_abc.Instances[(int)((U30)cmd.Parameters[0]).Value];
                output += NameUtil.ResolveClass(_abc, ii);
                break;

            // Param 1: ?
            case (byte)Op.PushNamespace:
                output += GetNamespace(cmd, 0);
                break;

            // Param 1: U30 -> DoubleTable
            case (byte)Op.PushDouble:
                //TODO fix this and do not use replace...
                output += GetDouble(cmd, 0).ToString().Replace(',', '.');
                break;

            // Param 1: U30 -> IntTable
            case (byte)Op.PushInt:
                output += GetInt(cmd, 0);
                break;

            // Param 1: U30 -> UIntTable
            case (byte)Op.PushUInt:
                output += GetUInt(cmd, 0);
                break;

            // Param 1: U30 -> StringTable
            case (byte)Op.DebugFile:
            case (byte)Op.PushString:
                output += '"' + GetString(cmd, 0).ToString() + '"';
                break;

            // Param 1: ?
            case (byte)Op.NewFunction:
                output += ((U30)cmd.Parameters[0]).Value + " ;call to anonymous method " + ((U30)cmd.Parameters[0]).Value;
                break;

            // Param 1: S24 -> Jump Offset
            case (byte)Op.IfEqual:
            case (byte)Op.IfFalse:
            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:
            case (byte)Op.IfTrue:
            case (byte)Op.Jump:
                S24 offset = (S24)cmd.Parameters[0];
                // addr + (1byte opcode) + (offset byte length) + (offset value)
                output += String.Format(".label{0}", _labels.GetLabelAt((uint)(address + 1 + offset.Length + offset.Value)).id) + "\r\n";
                break;

            case (byte)Op.LookupSwitch:
                S24 defaultLabel = (S24)cmd.Parameters[0];
                U30 count        = (U30)cmd.Parameters[1];

                output += String.Format(".label{0}", _labels.GetLabelAt((uint)(address + defaultLabel.Value)).id) + ", ";

                for (int i = 0, o = (int)count.Value + 1; i < o; ++i)
                {
                    S24 offsetLabel = (S24)cmd.Parameters[2 + i];

                    output += String.Format(".label{0}", _labels.GetLabelAt((uint)(address + offsetLabel.Value)).id);

                    if (i != o - 1)
                    {
                        output += ", ";
                    }
                }

                output += "\r\n";

                break;

            default:
                for (int i = 0; i < n; ++i)
                {
                    object t = cmd.Parameters[i];

                    if (t is byte)
                    {
                        output += String.Format("{0}", (byte)t);
                    }
                    else if (t is S24)
                    {
                        output += String.Format("{0}", ((S24)t).Value);
                    }
                    else if (t is U30)
                    {
                        output += String.Format("{0}", ((U30)t).Value);
                    }
                    else if (t is U32)
                    {
                        output += String.Format("{0}", ((U32)t).Value);
                    }

                    if (i != m)
                    {
                        output += ", ";
                    }
                }
                break;
            }

            output += "\r\n";

            _output.Add(output);
        }
Beispiel #45
0
        public uint ReadParameters(byte[] code, uint index)
        {
            _parameters.Clear();

            uint p = index;

            for (int i = 0; i < _parameterCount; ++i)
            {
                switch (_types[i])
                {
                case ParameterType.U30:
                    U30 _u30 = Primitives.ReadU30(code, p);

                    p += _u30.Length;

                    _parameters.Add(_u30);
                    break;

                case ParameterType.U8:
                    _parameters.Add(code[p++]);
                    break;

                case ParameterType.S24:
                    S24 _s24 = Primitives.ReadS24(code, p);

                    p += _s24.Length;

                    _parameters.Add(_s24);
                    break;

                case ParameterType.UInt:
                    U32 _u32 = Primitives.ReadU32(code, p);

                    p += _u32.Length;

                    _parameters.Add(_u32);
                    break;

                case ParameterType.Dynamic:
                    S24 d_s24 = Primitives.ReadS24(code, p);

                    p += d_s24.Length;

                    _parameters.Add(d_s24);

                    U30 c_u30 = Primitives.ReadU30(code, p);

                    p += c_u30.Length;

                    _parameters.Add(c_u30);

                    for (int j = 0; j <= c_u30.Value; ++j)
                    {
                        S24 j_s24 = Primitives.ReadS24(code, p);

                        p += j_s24.Length;

                        _parameters.Add(j_s24);
                    }

                    break;
                }
            }

            return(p - index);
        }
Beispiel #46
0
        public void ReadExternal(BinaryReader input)
        {
            _name = Primitives.ReadU30(input);

            if (0 == (uint)_name)
            {
                throw new VerifyException("Name must not be 0.");
            }

            _kind = input.ReadByte();

            _type = (byte)(_kind & 0xf);
            _attr = (byte)((_kind >> 4) & 0xf);

            switch (_type)
            {
                case TraitSlot:
                    _body = new TraitSlot(this);
                    break;
                case TraitConst:
                    _body = new TraitConst(this);
                    break;
                case TraitClass:
                    _body = new TraitClass(this);
                    break;
                case TraitFunction:
                    _body = new TraitFunction(this);
                    break;
                case TraitMethod:
                    _body = new TraitMethod(this);
                    break;
                case TraitGetter:
                    _body = new TraitGetter(this);
                    break;
                case TraitSetter:
                    _body = new TraitSetter(this);
                    break;
                default:
                    throw new VerifyException("Unexpected trait body.");
            }

            _body.ReadExternal(input);

            if (AttributeMetadata == (_attr & AttributeMetadata))
            {
                uint n = Primitives.ReadU30(input).Value;

                _metadata = new ArrayList(Capacity.Max(n));

                for (uint i = 0; i < n; ++i)
                    _metadata.Add(Primitives.ReadU30(input));
            }
        }
Beispiel #47
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;
        }
Beispiel #48
0
 public void ReadExternal(BinaryReader input)
 {
     _val  = Primitives.ReadU30(input);
     _kind = input.ReadByte();
 }
Beispiel #49
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;
        }
Beispiel #50
0
        static void Main(string[] args)
        {
#if DEBUG
            DateTime start = DateTime.Now;
#endif
            try
            {
                #region Initialization

                try
                {
                    bool hasMethod = false;

                    if (args.Length < 1)
                    {
                        WriteInfo();
                        Console.WriteLine("[?] Use -help for some instructions.");
                        return;
                    }

                    for (int i = 0, n = args.Length; i < n; ++i)
                    {
                        switch (args[i])
                        {
                        case "-h":
                        case "-help":
                        case "-?":
                        case "/?":
                        case "/help":
                            WriteInfo();
                            Usage();
                            return;

                        // OPTIONS /////////////////////////////////////////////////////////////////////

                        case "-o":
                        case "-output":
                            _pathOutput = args[++i];
                            break;

                        case "-q":
                        case "-quiet":
                            _isQuiet = true;
                            break;

                        // REPLACE ////////////////////////////////////////////////////////////////////

                        case "-r":
                        case "-replace":
                            _action = Action.Replace;
                            break;

                        // REPLACE PROPERTIES ////////////////////////////////////////////////////////

                        case "-sm":
                        case "-static-method":
                            if (hasMethod)
                            {
                                throw new Exception("Two methods defined.");
                            }
                            _isMethodStatic = true;
                            _methodName     = args[++i];
                            break;

                        case "-m":
                        case "-method":
                            if (hasMethod)
                            {
                                throw new Exception("Two methods defined.");
                            }
                            _isMethodStatic = false;
                            _methodName     = args[++i];
                            break;

                        case "-co":
                        case "-constructor":
                            if (hasMethod)
                            {
                                throw new Exception("Two methods defined.");
                            }
                            _isConstructor  = true;
                            _isMethodStatic = false;
                            break;

                        case "-sc":
                        case "-static-constructor":
                            if (hasMethod)
                            {
                                throw new Exception("Two methods defined.");
                            }
                            _isConstructor  = true;
                            _isMethodStatic = true;
                            break;

                        case "-c":
                        case "-class":
                            _className = args[++i];
                            break;

                        case "-n":
                        case "-namespace":
                            _namespace = args[++i];
                            break;

                        // INLINE ///////////////////////////////////////////////////////////////////

                        case "-i":
                        case "-inline":
                            _action  = Action.Inline;
                            _pathSwf = args[++i];
                            break;

                        // PATCH ///////////////////////////////////////////////////////////////////
                        case "-optimize":
                            _action  = Action.Optimize;
                            _pathSwf = args[++i];
                            break;

                        // DASM ////////////////////////////////////////////////////////////////////

                        case "-d":
                        case "-dasm":
                            _action = Action.Dasm;
                            break;

                        // DASM PROPERTIES ////////////////////////////////////////////////////////

                        case "-a":
                        case "-as3c":
                            _dasmType = Dasm.As3c;
                            break;

                        case "-p":
                        case "-plain":
                            _dasmType = Dasm.Plain;
                            break;

                        default:
                            if (File.Exists(args[i]))
                            {
                                try
                                {
                                    BinaryReader fileHead = new BinaryReader(File.Open(args[i], FileMode.Open, FileAccess.Read));

                                    if (fileHead.BaseStream.Length < 3)
                                    {
                                        throw new Exception("Invalid file given.");
                                    }

                                    byte[] head = fileHead.ReadBytes(3);

                                    fileHead.Close();

                                    //TODO fix this ugly part...
                                    if ((head[0] == (byte)'C' || head[0] == (byte)'F') && head[1] == (byte)'W' && head[2] == (byte)'S')
                                    {
                                        if (_pathSwf != "")
                                        {
                                            throw new Exception("Two SWF files given.");
                                        }

                                        _pathSwf = args[i];
                                    }
                                    else
                                    {
                                        if ("" != _pathAsm)
                                        {
                                            throw new Exception("Two ASM files given.");
                                        }

                                        _pathAsm = args[i];
                                    }
                                }
                                catch (IOException io)
                                {
                                    WriteInfo();
                                    Console.Error.WriteLine("[-] Error: Can not open file {0}", args[i]);
#if DEBUG
                                    Console.Error.WriteLine("[-] {0}", io.Message);
#endif
                                    return;
                                }
                                catch (Exception e)
                                {
                                    WriteInfo();
                                    Console.Error.WriteLine("[-] Error: {0}", e.Message);
#if DEBUG
                                    Console.Error.WriteLine("[-] {0}", e.StackTrace);
#endif
                                    return;
                                }
                            }
                            else
                            {
                                if (args[i].IndexOf(".") != -1)
                                {
                                    WriteInfo();
                                    Console.Error.WriteLine("[-] File {0} does not exist.", args[i]);
                                    return;
                                }
                                else
                                {
                                    throw new Exception("Invalid argument given.");
                                }
                            }
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    WriteInfo();
                    Console.Error.WriteLine("[-] Error: Invalid arguments. Use -help for help ...");
#if DEBUG
                    Console.Error.WriteLine("[-] {0}", e.Message);
                    Console.Error.WriteLine("[-] {0}", e.StackTrace);
#endif
                    return;
                }

                if (!_isQuiet)
                {
                    Console.WriteLine("[i] As3c - ActionScript3 ASM compiler");
                }

                Translator.InitTable();

                #endregion

                #region Integrity scan for the Translator class (DEBUG only)

#if DEBUG
                if (Translator.CheckIntegrity())
                {
                    if (!_isQuiet)
                    {
                        Console.WriteLine("[+] Integrity scan passed!");
                    }
                }
                else
                {
                    Console.WriteLine("[-] Integrity scan failed...!");
                }
#endif

                #endregion

                FileStream fileInput;
                FileStream fileOutput;
                SwfFormat  swf;

                switch (_action)
                {
                case Action.Dasm:

                    #region Disassemble file

                    swf       = new SwfFormat();
                    fileInput = File.Open(_pathSwf, FileMode.Open, FileAccess.Read);

                    swf.Read(fileInput);

                    fileInput.Close();
                    fileInput.Dispose();

                    DisassemblerBase dasm;

                    switch (_dasmType)
                    {
                    case Dasm.As3c:
                        dasm = new DisassemblerAs3c();
                        break;

                    case Dasm.Plain:
                        dasm = new DisassemblerPlain();
                        break;

                    default:
                        throw new Exception();
                    }

                    dasm.Parse(swf);

                    if ("" == _pathOutput)
                    {
                        dasm.EmitToConsole();
                    }
                    else
                    {
                        fileOutput = File.Open(_pathOutput, FileMode.OpenOrCreate, FileAccess.Write);
                        dasm.EmitToStream(fileOutput);

                        fileOutput.Close();
                        fileOutput.Dispose();
                    }

                    #endregion

                    break;

                case Action.Optimize:

                    #region Optimize SWF

                    swf       = new SwfFormat();
                    fileInput = File.Open(_pathSwf, FileMode.Open, FileAccess.Read);

                    swf.Read(fileInput);

                    fileInput.Close();
                    fileInput.Dispose();

                    CompilerOptimize compOptimize = new CompilerOptimize(swf);

                    compOptimize.Compile();

                    fileOutput = File.Open((_pathOutput != "") ? _pathOutput : _pathSwf, FileMode.OpenOrCreate, FileAccess.Write);

                    swf.Write(fileOutput);

                    fileOutput.Close();
                    fileOutput.Dispose();

                    #endregion

                    break;

                case Action.Inline:

                    #region Compile inline instructions

                    swf       = new SwfFormat();
                    fileInput = File.Open(_pathSwf, FileMode.Open, FileAccess.Read);

                    swf.Read(fileInput);

                    fileInput.Close();
                    fileInput.Dispose();

                    CompilerInline compInline = new CompilerInline(swf);
                    compInline.Compile();

                    fileOutput = File.Open((_pathOutput != "") ? _pathOutput : _pathSwf, FileMode.OpenOrCreate, FileAccess.Write);

                    swf.Write(fileOutput);

                    fileOutput.Close();
                    fileOutput.Dispose();

                    #endregion

                    break;

                case Action.Replace:

                    #region Replace method body

                    #region Simple pre-check

                    if ("" == _pathAsm || !File.Exists(_pathAsm))
                    {
                        Console.Error.WriteLine("[-] No valid ASM input given.");
                        return;
                    }

                    if ("" == _pathSwf || !File.Exists(_pathSwf))
                    {
                        Console.Error.WriteLine("[-] No valid SWF target given.");
                        return;
                    }

                    if ("" == _className)
                    {
                        Console.Error.WriteLine("[-] No class given.");
                        return;
                    }

                    if (!_isConstructor)
                    {
                        if ("" == _methodName)
                        {
                            Console.Error.WriteLine("[-] Need method name or constructor to replace");
                            return;
                        }
                    }

                    #endregion

                    swf       = new SwfFormat();
                    fileInput = File.Open(_pathSwf, FileMode.Open, FileAccess.Read);

                    swf.Read(fileInput);

                    fileInput.Close();
                    fileInput.Dispose();

                    #region Body lookup

                    Abc46 abc = null;
                    SwfLibrary.Abc.MethodInfo method = null;
                    MethodBodyInfo            body   = null;
                    bool  instanceFound = false;
                    Abc46 currentAbc    = null;

                    string classFormat;

                    if (_className.IndexOf(".") != -1)
                    {
                        classFormat = "public::" + _className.Substring(0, _className.LastIndexOf(".")) + "::" + _className.Substring(_className.LastIndexOf(".") + 1, _className.Length - _className.LastIndexOf(".") - 1);
                    }
                    else
                    {
                        classFormat = "public::" + _className;
                    }

                    string methodFormat = _namespace + "::" + _methodName;

                    // Parse for all possibilities
                    for (int i = 0, n = swf.AbcCount; i < n; ++i)
                    {
                        currentAbc = swf.GetAbcAt(i);

                        for (int j = 0, m = currentAbc.Scripts.Count; j < m; ++j)
                        {
                            ScriptInfo script = (ScriptInfo)currentAbc.Scripts[j];

                            for (int k = 0, o = script.Traits.Count; k < o; ++k)
                            {
                                TraitInfo scriptTrait = (TraitInfo)script.Traits[k];

                                if (!(scriptTrait.Body is TraitClass))
                                {
                                    continue;
                                }

                                TraitClass   classBody    = (TraitClass)scriptTrait.Body;
                                ClassInfo    classInfo    = (ClassInfo)currentAbc.Classes[(int)classBody.ClassI];
                                InstanceInfo instanceInfo = (InstanceInfo)currentAbc.Instances[(int)classBody.ClassI];

                                string instanceName = NameUtil.ResolveMultiname(currentAbc, instanceInfo.Name);

                                if (classFormat == instanceName)
                                {
                                    instanceFound = true;

                                    if (!_isQuiet)
                                    {
                                        Console.WriteLine("[+] Found class {0}", instanceName);
                                    }

                                    if (_isMethodStatic)
                                    {
                                        if (_isConstructor)
                                        {
                                            if (null != body)
                                            {
                                                Console.Error.WriteLine("[-] Can not explicitly determine method body.");
                                                return;
                                            }

                                            method = (SwfLibrary.Abc.MethodInfo)currentAbc.Methods[(int)classInfo.CInit];

                                            body = FindBody(currentAbc, classInfo.CInit);

                                            abc = currentAbc;

                                            if (null != body)
                                            {
                                                if (!_isQuiet)
                                                {
                                                    Console.WriteLine("[+] Found static class initializer.");
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Console.Error.WriteLine("[-] Sorry, static methods do not work yet ...");
                                            return;
                                            //TODO support static methods...
                                        }
                                    }
                                    else
                                    {
                                        if (_isConstructor)
                                        {
                                            if (null != body)
                                            {
                                                Console.Error.WriteLine("[-] Can not explicitly determine method body.");
                                                return;
                                            }

                                            method = (SwfLibrary.Abc.MethodInfo)currentAbc.Methods[(int)instanceInfo.IInit];

                                            body = FindBody(currentAbc, instanceInfo.IInit);

                                            abc = currentAbc;

                                            if (null != body)
                                            {
                                                if (!_isQuiet)
                                                {
                                                    Console.WriteLine("[+] Found class initializer.");
                                                }
                                            }
                                        }
                                        else
                                        {
                                            // here begins the ugly part ...
                                            for (int l = 0, p = instanceInfo.Traits.Count; l < p; ++l)
                                            {
                                                TraitInfo instanceTrait = (TraitInfo)instanceInfo.Traits[l];

                                                if (!(instanceTrait.Body is TraitMethod))
                                                {
                                                    continue;
                                                }

                                                string methodName = NameUtil.ResolveMultiname(currentAbc, instanceTrait.Name);

                                                if ("" == _namespace)
                                                {
                                                    if ("public::" + _methodName != methodName &&
                                                        "private::" + _methodName != methodName &&
                                                        "protected::" + _methodName != methodName &&
                                                        "protected$::" + _methodName != methodName &&
                                                        "internal::" + _methodName != methodName)
                                                    {
                                                        continue;
                                                    }
                                                }
                                                else
                                                {
                                                    if (methodName != methodFormat)
                                                    {
                                                        continue;
                                                    }
                                                }

                                                if (null != body)
                                                {
                                                    Console.Error.WriteLine("[-] Can not explicitly determine method body.");
                                                    return;
                                                }

                                                TraitMethod methodBody = (TraitMethod)instanceTrait.Body;

                                                method = (SwfLibrary.Abc.MethodInfo)currentAbc.Methods[(int)methodBody.Method];

                                                body = FindBody(currentAbc, methodBody.Method);

                                                abc = currentAbc;

                                                if (null != body)
                                                {
                                                    if (!_isQuiet)
                                                    {
                                                        Console.WriteLine("[+] Found method {0}", methodName);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (null == body)
                    {
                        Console.Error.WriteLine("[-] Could not find {0}.", (instanceFound) ? "method" : "class");
                        return;
                    }

                    #endregion

                    //
                    // We have valid body to replace. Start the parser.
                    //

                    ParserAs3c parser = new ParserAs3c();
                    parser.Parse(_pathAsm);

                    //
                    // Convert the parser instructions to actual bytecode for the AVM2.
                    //

                    CompilerAs3c compAs3c = new CompilerAs3c();
                    compAs3c.Compile(currentAbc, parser.Instructions, parser.Labels, false);

                    //
                    // Get body information (maxstack, localcount, maxscopedepth, initscopedepth)
                    // We keep compiler directives in respect here ...
                    //

                    #region MethodBody information

                    U30 maxStack;
                    U30 maxScopeDepth;
                    U30 localCount;
                    U30 initScopeDepth = new U30();

                    if (parser.HasMaxStack)
                    {
                        maxStack       = new U30();
                        maxStack.Value = parser.MaxStack;
                    }
                    else
                    {
                        maxStack = ByteCodeAnalyzer.CalcMaxStack(compAs3c.Code);

                        if (maxStack.Value < method.ParameterCount.Value)
                        {
                            maxStack.Value = method.ParameterCount.Value;
                        }
                    }

                    if (parser.HasLocalCount)
                    {
                        localCount       = new U30();
                        localCount.Value = parser.LocalCount;
                    }
                    else
                    {
                        localCount = ByteCodeAnalyzer.CalcLocalCount(compAs3c.Code);
                    }

                    if (parser.HasInitScopeDepth)
                    {
                        initScopeDepth.Value = parser.InitScopeDepth;
                    }
                    else
                    {
                        initScopeDepth.Value = 1;
                    }

                    if (parser.HasMaxScopeDepth)
                    {
                        maxScopeDepth       = new U30();
                        maxScopeDepth.Value = parser.MaxScopeDepth;
                    }
                    else
                    {
                        maxScopeDepth        = ByteCodeAnalyzer.CalcScopeDepth(compAs3c.Code);
                        maxScopeDepth.Value += initScopeDepth.Value;
                    }

                    if (!_isQuiet)
                    {
                        Console.WriteLine("[i] InitScopeDepth: {0}", (int)initScopeDepth);
                        Console.WriteLine("[i] MaxScopeDepth: {0}", (int)maxScopeDepth);
                        Console.WriteLine("[i] MaxStack: {0}", (int)maxStack);
                        Console.WriteLine("[i] LocalCount: {0}", (int)localCount);
                    }

                    #endregion

                    //
                    // Replace the code of the body.
                    //

                    body.Code = compAs3c.Code;

                    //
                    // Update body information
                    //

                    body.MaxStack       = maxStack;
                    body.MaxScopeDepth  = maxScopeDepth;
                    body.InitScopeDepth = initScopeDepth;
                    body.LocalCount     = localCount;

                    #region Write output

                    if ("" == _pathOutput)
                    {
                        fileOutput = File.Open(_pathSwf, FileMode.OpenOrCreate, FileAccess.Write);
                    }
                    else
                    {
                        fileOutput = File.Open(_pathOutput, FileMode.OpenOrCreate, FileAccess.Write);
                    }

                    swf.Write(fileOutput);

                    fileOutput.Close();
                    fileOutput.Dispose();

                    #endregion

                    #endregion

                    break;

                case Action.Usage:
                    Usage();
                    break;
                }

                #region Program end

                if (!_isQuiet)
                {
                    Console.WriteLine("[i] Done.");
                }
                #endregion
            }
            catch (IOException ioex)
            {
                Console.Error.WriteLine("[-] Error: {0}", ioex.Message);
            }
            catch (InstructionException iex)
            {
                #region Parser errors

                string message;

                switch (iex.ErrorType)
                {
                case InstructionException.Type.InvalidSyntax:
                    message = "Error while parsing";
                    break;

                case InstructionException.Type.NotEnoughArguments:
                    message = "Not enough arguments";
                    break;

                case InstructionException.Type.TooManyArguments:
                    message = "Too many arguments";
                    break;

                case InstructionException.Type.UnknownType:
                    message = "Unknown type";
                    break;

                case InstructionException.Type.LabelRedefined:
                    message = "Label has already been defined";
                    break;

                case InstructionException.Type.LabelMissing:
                    message = "Label has never been defined";
                    break;

                default:
                    message = "Unknown error at";
                    break;
                }

                Console.Error.WriteLine("[-] " + message + ":");

                if (null != iex.ParserInfo)
                {
                    Console.Error.WriteLine("{0}({1}): {2}", iex.ParserInfo.FilePath, iex.ParserInfo.LineNumber, iex.ParserInfo.Line);
                }

                #endregion
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine("[-] Unexpected error: {0}", ex.Message);
#if DEBUG
                Console.Error.WriteLine("[-] Stacktrace: {0}", ex.StackTrace);
#endif
            }

#if DEBUG
            DateTime end   = DateTime.Now;
            TimeSpan delta = end - start;

            Console.WriteLine("[i] Total: {0}sec {1}ms", delta.Seconds, delta.Milliseconds);
#endif
        }
Beispiel #51
0
 public override void ReadExternal(BinaryReader input)
 {
     _dispId = Primitives.ReadU30(input);
     _method = Primitives.ReadU30(input);
 }
Beispiel #52
0
        public void Compile(Abc46 abc, ArrayList instructions, Dictionary <string, Label> labels, bool patchMath)
        {
#if DEBUG
            //Console.WriteLine("[i] Starting to compile method body ...");
#endif
            //
            // Create buffer
            //

            MemoryStream buffer = new MemoryStream();
            BinaryWriter output = new BinaryWriter(buffer);

            //
            // Convert compiler instructions to IL.
            //
            Instruction instruction;
            Label       label;
            List <ReplaceInformation> replaceList = new List <ReplaceInformation>();

            bool        hasLocalMath  = false;
            uint        mathRegister  = 0;
            U30         mathMultiName = new U30();
            AVM2Command mathCommand   = null;
            AVM2Command lastCommand   = null;

            for (int i = 0, n = instructions.Count; i < n; ++i)
            {
                if (instructions[i] is Label)
                {
                    label = (Label)instructions[i];

                    label.Address = (uint)buffer.Position;

                    if (!label.Referenced)
                    {
                        output.Write((byte)Op.Label);
                    }
                }
                else if (instructions[i] is AVM2Command)
                {
                    AVM2Command command = (AVM2Command)instructions[i];

                    output.Write((byte)command.OpCode);

                    switch (command.OpCode)
                    {
                    case (byte)Op.IfEqual:
                    case (byte)Op.IfFalse:
                    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:
                    case (byte)Op.IfTrue:
                    case (byte)Op.Jump:
                        string labelId = (string)command.Parameters[0];

                        try
                        {
                            label = labels[labelId];
                        }
                        catch (Exception)
                        {
                            Console.WriteLine("[-] WARNING: Jumping to an unknown label");
                            continue;
                        }

                        if (label.HasAddress)
                        {
                            int offset = (int)(label.Address - ((uint)buffer.Position + 3));
                            Primitives.WriteS24(output, offset);
                        }
                        else
                        {
                            replaceList.Add(new ReplaceInformation((uint)buffer.Position, label, false));
                            Primitives.WriteS24(output, 0);
                        }

                        label.Referenced = true;
                        break;

                    case (byte)Op.GetLex:
                        if (patchMath)
                        {
                            string lexName = NameUtil.ResolveMultiname(abc, (MultinameInfo)(abc.ConstantPool.MultinameTable[(int)((U30)command.Parameters[0]).Value]));

                            //
                            // If getlex public::Math is called we will repalce it with
                            // a get_local N where Math will be stored.
                            //

                            if (("public::Math" == lexName || "Math" == lexName) && (null != lastCommand) && (lastCommand.OpCode != (byte)Op.SetLocal))
                            {
#if DEBUG
                                Console.WriteLine("[i] Found call to Math class ...");
#endif

                                if (!hasLocalMath)
                                {
                                    mathMultiName = (U30)command.Parameters[0];

                                    U30 currentMaxLocal = ByteCodeAnalyzer.CalcLocalCount(instructions);

#if DEBUG
                                    Console.WriteLine(String.Format("[i] Math register will be {0}", currentMaxLocal.Value));
#endif

                                    if (currentMaxLocal.Value < 4)
                                    {
                                        int val = (int)currentMaxLocal.Value;
                                        mathCommand = Translator.ToCommand((byte)(0xd0 + val));
                                    }
                                    else
                                    {
                                        mathCommand = Translator.ToCommand((byte)Op.GetLocal);
                                        mathCommand.Parameters.Add(currentMaxLocal);
                                    }

                                    mathRegister = currentMaxLocal.Value;

                                    hasLocalMath = true;
                                }

                                output.Seek(-1, SeekOrigin.Current);
                                output.Write((byte)mathCommand.OpCode);

                                if (mathCommand.OpCode == (byte)Op.GetLocal)
                                {
                                    mathCommand.WriteParameters(output);
                                }
                            }
                            else
                            {
                                command.WriteParameters(output);
                            }
                        }
                        else
                        {
                            command.WriteParameters(output);
                        }
                        break;

                    default:
                        command.WriteParameters(output);
                        break;
                    }

                    lastCommand = command;
                }
                else if (instructions[i] is Instruction)
                {
                    instruction = (Instruction)instructions[i];

                    output.Write(instruction.Command.OpCode);

                    switch (instruction.Command.OpCode)
                    {
                    case (byte)Op.PushShort:
                        Primitives.WriteU30(output, (U30)Convert.ToInt32(instruction.Arguments[0]));
                        break;

                    case (byte)Op.AsType:
                    case (byte)Op.Coerce:
                    case (byte)Op.DeleteProperty:
                    case (byte)Op.FindProperty:
                    case (byte)Op.FindPropertyStrict:
                    case (byte)Op.GetDescendants:
                    case (byte)Op.GetLex:
                    case (byte)Op.GetProperty:
                    case (byte)Op.GetSuper:
                    case (byte)Op.InitProperty:
                    case (byte)Op.IsType:
                    case (byte)Op.SetProperty:
                    case (byte)Op.PushNamespace:
                        Primitives.WriteU30(output, NameUtil.GetMultiname(abc, instruction.Arguments[0]));
                        break;

                    case (byte)Op.CallProperty:
                    case (byte)Op.CallPropertyLex:
                    case (byte)Op.CallPropertyVoid:
                    case (byte)Op.CallSuper:
                    case (byte)Op.CallSuperVoid:
                    case (byte)Op.ConstructProperty:
                        Primitives.WriteU30(output, NameUtil.GetMultiname(abc, instruction.Arguments[0]));
                        Primitives.WriteU30(output, Convert.ToUInt32(instruction.Arguments[1]));
                        break;

                    case (byte)Op.NewClass:
                        Primitives.WriteU30(output, NameUtil.GetClass(abc, instruction.Arguments[0]));
                        break;

                    case (byte)Op.PushDouble:
                        Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveDouble(Convert.ToDouble(instruction.Arguments[0].Replace('.', ','))));
                        break;

                    case (byte)Op.PushInt:
                        Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveInt((S32)Convert.ToInt32(instruction.Arguments[0])));
                        break;

                    case (byte)Op.PushUInt:
                        Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveUInt((U32)Convert.ToUInt32(instruction.Arguments[0])));
                        break;

                    case (byte)Op.DebugFile:
                    case (byte)Op.PushString:
                        if (instruction.Arguments[0].StartsWith("\"") && instruction.Arguments[0].EndsWith("\""))    //TODO fix ugly hack
                        {
                            Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveString(instruction.Arguments[0].Substring(1, instruction.Arguments[0].Length - 2)));
                        }
                        else
                        {
                            Primitives.WriteU30(output, (U30)abc.ConstantPool.ResolveString(instruction.Arguments[0]));
                        }
                        break;

                    case (byte)Op.IfEqual:
                    case (byte)Op.IfFalse:
                    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:
                    case (byte)Op.IfTrue:
                    case (byte)Op.Jump:
                        //
                        // Solve label offset
                        //

                        string labelId = null;

                        try
                        {
                            labelId = instruction.Arguments[0];
                        }
                        catch (Exception)
                        {
                            Console.WriteLine("[-] WARNING: Jumping to an unknown label");
                            continue;
                        }

                        //
                        // Make sure the label exsists.
                        //

                        if (!labels.ContainsKey(labelId))
                        {
#if DEBUG
                            Console.WriteLine("[-] Label \"{0}\" is missing ...", labelId);
#endif
                            throw new InstructionException(InstructionException.Type.LabelMissing, instruction.DebugInfo);
                        }

                        label = labels[labelId];

                        if (label.HasAddress)
                        {
                            //
                            // We already have the label address. This is a negative jump offset.
                            //

                            int offset = (int)(label.Address - ((uint)buffer.Position + 3));
                            Primitives.WriteS24(output, offset);
                        }
                        else
                        {
                            //
                            // We do not know the label address. This is a positive jump offset.
                            // Mark label to be solved afterwards and write a placeholder ...
                            //

                            replaceList.Add(new ReplaceInformation((uint)buffer.Position, label, false));
                            Primitives.WriteS24(output, 0);
                        }

                        label.Referenced = true;
                        break;

                    default:
                        if (0 < instruction.Command.ParameterCount)
                        {
                            try
                            {
                                foreach (string argument in instruction.Arguments)
                                {
                                    output.Write((byte)Convert.ToByte(argument));
                                }
                            }
                            catch (Exception)
                            {
                                throw new InstructionException(InstructionException.Type.UnknownType, instruction.DebugInfo);
                            }
                        }
                        break;
                    }

                    lastCommand = instruction.Command;
                }
            }

            int labelOffset = 0;

            #region Add automatically generated code

            //
            // Add local variable containing Math
            //

            if (patchMath && hasLocalMath)
            {
#if DEBUG
                Console.WriteLine("[i] Body has local Math");
#endif

                int mathAddress = 2;

                int lastOpCode = -1;
                int opCode     = -1;

                long lastPosition = output.BaseStream.Position;

                output.BaseStream.Seek(0, SeekOrigin.Begin);

                while (((opCode = output.BaseStream.ReadByte()) != -1))
                {
                    if (lastOpCode == (byte)Op.GetLocal0 && opCode == (byte)Op.PushScope)
                    {
                        break;
                    }

                    lastOpCode = opCode;
                }


                mathAddress = (int)output.BaseStream.Position;

                output.BaseStream.Seek(lastPosition, SeekOrigin.Begin);

#if DEBUG
                //Console.WriteLine("[i] Dump Before:");
                //DebugUtil.Dump((MemoryStream)output.BaseStream);
#endif

                InsertByte(output, mathAddress);
                InsertByte(output, mathAddress);

                labelOffset += 2;

                int byteCoundMulti = 0;

                while (byteCoundMulti < mathMultiName.Length)
                {
                    byteCoundMulti++;
                    labelOffset++;
                    InsertByte(output, mathAddress);
                }


                if (mathRegister > 3)
                {
#if DEBUG
                    Console.WriteLine("[i] Adding extra register");
#endif
                    int byteCount = 0;

                    while (byteCount < ((U30)mathRegister).Length + 1)
                    {
                        ++byteCount;
                        ++labelOffset;
                        InsertByte(output, mathAddress);
                    }
                }


                output.Seek(mathAddress, SeekOrigin.Begin);

                AVM2Command getLexCommand = Translator.ToCommand((byte)Op.GetLex);
                getLexCommand.Parameters.Add(mathMultiName);

                output.Write((byte)getLexCommand.OpCode);
                getLexCommand.WriteParameters(output);

                if (mathRegister > 3)
                {
                    AVM2Command setLocalCommand = Translator.ToCommand((byte)Op.SetLocal);
                    setLocalCommand.Parameters.Add((U30)mathRegister);

                    output.Write((byte)setLocalCommand.OpCode);
                    setLocalCommand.WriteParameters(output);
                }
                else
                {
                    output.Write((byte)(0xd4 + mathRegister));
                }


#if DEBUG
                //Console.WriteLine("[i] Dump After:");
                //DebugUtil.Dump((MemoryStream)output.BaseStream);
#endif

                output.Seek(0, SeekOrigin.End);
                output.Flush();
            }

            #endregion

            //
            // Solve remainig labels
            //

            for (int i = 0, n = replaceList.Count; i < n; ++i)
            {
                ReplaceInformation replaceInfo = replaceList[i];

                label = replaceInfo.label;

                if (!label.Referenced || !label.HasAddress)
                {
                    Console.WriteLine("[-] Warning: Label {0} has never been defined or used ...", label.Identifier);
                    continue;
                }

                if (replaceInfo.lookUpSwitch)
                {
                    //
                    // LookUpSwitch with special offset calculation
                    //

                    throw new Exception("IMPLEMENT ME!");
                }
                else
                {
                    //
                    // Simple jump
                    //

                    int offset = (int)(label.Address - ((uint)replaceInfo.address + 3));

                    buffer.Seek(replaceInfo.address + labelOffset, SeekOrigin.Begin);
                    Primitives.WriteS24(output, offset);
                }
            }

            //
            // Convert stream to byte[]
            //

            buffer.Seek(0, SeekOrigin.Begin);

            BinaryReader reader = new BinaryReader(buffer);

            _code = reader.ReadBytes((int)buffer.Length);

            //
            // Clean up
            //

            reader.Close();
            buffer.Dispose();

#if DEBUG
            //Console.WriteLine("[i] Done compiling method body ...");
#endif
        }
Beispiel #53
0
        private static MethodBodyInfo FindBody(Abc46 abc, U30 methodIndex)
        {
            SwfLibrary.Abc.MethodInfo methodInfo = (SwfLibrary.Abc.MethodInfo)abc.Methods[(int)methodIndex];
            MethodBodyInfo methodBody = null;

            for (int i = 0, n = abc.MethodBodies.Count; i < n; ++i)
            {
                methodBody = (MethodBodyInfo)abc.MethodBodies[i];

                if (methodBody.Method.Value == methodIndex.Value)
                {
                    break;
                }
            }

            return methodBody;
        }
Beispiel #54
0
 public static int Max(U30 count)
 {
     return Max((uint)count);
 }