Exemple #1
0
        /// <summary>
        /// Turns bytecode into an AbcCode object.
        /// </summary>
        /// <param name="bytecode">The bytecode, as chopped out of a SWF.</param>
        /// <param name="readLog">Ignored in release builds. This logs
        /// on every constant value read for unit test inspection.</param>
        /// <returns>A string rendition of the bytecode.</returns>
        public AbcCode Read(byte[] bytecode, StringBuilder readLog)
        {
#if DEBUG
            this.ReadLog = readLog;
            if (this.ReadLog != null)
            {
                this.ReadLog.AppendLine("\nNew ABC file\n-----------\n");
            }
#endif

            this.code   = new AbcCode();
            this.abcdtr = new ABCDataTypeReader(new MemoryStream(bytecode));

            this.LateResolutions = new Dictionary <object, int>();

            int minor = this.abcdtr.ReadUI16();
            int major = this.abcdtr.ReadUI16();
            if (minor != AbcFileValues.MinorVersion || major != AbcFileValues.MajorVersion)
            {
                throw new SWFModellerException(
                          SWFModellerError.ABCParsing,
                          "Unsupported version, or not an ABC file.");
            }

            this.ReadConstantPool();
            this.ReadMethods();
            this.ReadMetadata();
            this.ReadClasses();
            this.ReadScriptDefs();
            this.ReadMethodBodies();

            this.ResolveReferences();

            return(this.code);
        }
Exemple #2
0
        /// <summary>
        /// Turns bytecode into an AbcCode object.
        /// </summary>
        /// <param name="bytecode">The bytecode, as chopped out of a SWF.</param>
        /// <param name="readLog">Ignored in release builds. This logs
        /// on every constant value read for unit test inspection.</param>
        /// <returns>A string rendition of the bytecode.</returns>
        public AbcCode Read(byte[] bytecode, StringBuilder readLog)
        {
            #if DEBUG
            this.ReadLog = readLog;
            if (this.ReadLog != null)
            {
                this.ReadLog.AppendLine("\nNew ABC file\n-----------\n");
            }
            #endif

            this.code = new AbcCode();
            this.abcdtr = new ABCDataTypeReader(new MemoryStream(bytecode));

            this.LateResolutions = new Dictionary<object, int>();

            int minor = this.abcdtr.ReadUI16();
            int major = this.abcdtr.ReadUI16();
            if (minor != AbcFileValues.MinorVersion || major != AbcFileValues.MajorVersion)
            {
                throw new SWFModellerException(
                        SWFModellerError.ABCParsing,
                        "Unsupported version, or not an ABC file.");
            }

            this.ReadConstantPool();
            this.ReadMethods();
            this.ReadMetadata();
            this.ReadClasses();
            this.ReadScriptDefs();
            this.ReadMethodBodies();

            this.ResolveReferences();

            return this.code;
        }
Exemple #3
0
        /// <summary>
        /// Convenience method for creating an opcode from a position in a byte array.
        /// Returns an opcode object with references resolved and advances the position
        /// to the next place in the byte array.
        /// </summary>
        /// <param name="reader">Where to read the next opcode from</param>
        /// <param name="abc">The code within which we're reading</param>
        /// <returns>A new Opcode object, or null if there was no more data to be read</returns>
        public static Opcode BuildOpcode(ABCDataTypeReader reader, AbcCode abc)
        {
            Opcode op = new Opcode(abc);

            int code;

            code = reader.ReadUI8();
            if (code == -1)
            {
                return(null);
            }
            op.Instruction = (uint)code;

            if (OpcodeTable[code] == null)
            {
                throw new SWFModellerException(
                          SWFModellerError.Internal,
                          "Bad opcode 0x" + code.ToString("X") + " at @" + (reader.Offset - 1));
            }
            OpcodeDef info = (OpcodeDef)OpcodeTable[code];

            List <object> args = new List <object>();

            if (info.Mnemonic == Mnemonics.LookupSwitch)
            {
                /* Special case: Has a variable arg */
                args.Add(reader.ReadSI24()); /* default offset */
                uint caseCount = reader.ReadU30();
                args.Add(caseCount);

                for (int i = 0; i < caseCount + 1; i++)
                {
                    args.Add(reader.ReadSI24());
                }
            }
            else
            {
                if (info.Args != null)
                {
                    foreach (ArgType type in info.Args)
                    {
                        switch (type)
                        {
                        case ArgType.MultinameU30:
                            args.Add(abc.GetMultiname((int)reader.ReadU30()));
                            break;

                        case ArgType.OffsetS24:
                            args.Add(reader.ReadSI24());
                            break;

                        case ArgType.StringU30:
                            args.Add(abc.StringConsts[reader.ReadU30()]);
                            break;

                        case ArgType.RegisterU30:
                        case ArgType.ObjectRegisterU30:
                        case ArgType.PropertyRegisterU30:
                            args.Add(reader.ReadU30());
                            break;

                        case ArgType.ByteU8:
                            args.Add((byte)reader.ReadUI8());
                            break;

                        case ArgType.ShortU30:
                        case ArgType.IntU30:
                        case ArgType.UintU30:
                        case ArgType.DoubleU30:
                            args.Add(reader.ReadU30());
                            break;

                        case ArgType.ShortS30:
                            args.Add((int)reader.ReadU30());
                            break;

                        case ArgType.ByteS8:
                            args.Add(reader.ReadSI8());
                            break;

                        case ArgType.NamespaceU30:
                            args.Add(abc.GetNamespace((int)reader.ReadU30()));
                            break;

                        case ArgType.MethodU30:
                            args.Add(abc.GetMethod((int)reader.ReadU30()));
                            break;

                        case ArgType.CountU30:
                            args.Add(reader.ReadU30());
                            break;

                        case ArgType.ClassU30:
                            args.Add(abc.GetClass((int)reader.ReadU30()));
                            break;

                        case ArgType.ExceptionU30:
                            args.Add(reader.ReadU30());
                            break;

                        case ArgType.StackU8:
                            args.Add((byte)reader.ReadUI8());
                            break;

                        case ArgType.SlotU30:
                            args.Add(reader.ReadU30());
                            break;

                        case ArgType.DebugU8:
                            args.Add((byte)reader.ReadUI8());
                            break;

                        case ArgType.DebugTypeU30:
                            args.Add(reader.ReadU30());
                            break;

                        case ArgType.StringU8:
                            args.Add(abc.StringConsts[reader.ReadUI8()]);
                            break;

                        case ArgType.LineNumberU30:
                            args.Add(reader.ReadU30());
                            break;

                        default:
                            /* ISSUE 73 */
                            throw new SWFModellerException(
                                      SWFModellerError.UnimplementedFeature,
                                      "Oops. Not done " + type.ToString());
                        }
                    }
                }
            }

            op.Args = args.ToArray();

            return(op);
        }
Exemple #4
0
        /// <summary>
        /// Convenience method for creating an opcode from a position in a byte array.
        /// Returns an opcode object with references resolved and advances the position
        /// to the next place in the byte array.
        /// </summary>
        /// <param name="reader">Where to read the next opcode from</param>
        /// <param name="abc">The code within which we're reading</param>
        /// <returns>A new Opcode object, or null if there was no more data to be read</returns>
        public static Opcode BuildOpcode(ABCDataTypeReader reader, AbcCode abc)
        {
            Opcode op = new Opcode(abc);

            int code;
            code = reader.ReadUI8();
            if (code == -1)
            {
                return null;
            }
            op.Instruction = (uint)code;

            if (OpcodeTable[code] == null)
            {
                throw new SWFModellerException(
                        SWFModellerError.Internal,
                        "Bad opcode 0x" + code.ToString("X") + " at @" + (reader.Offset - 1));
            }
            OpcodeDef info = (OpcodeDef)OpcodeTable[code];

            List<object> args = new List<object>();

            if (info.Mnemonic == Mnemonics.LookupSwitch)
            {
                /* Special case: Has a variable arg */
                args.Add(reader.ReadSI24()); /* default offset */
                uint caseCount = reader.ReadU30();
                args.Add(caseCount);

                for (int i = 0; i < caseCount + 1; i++)
                {
                    args.Add(reader.ReadSI24());
                }
            }
            else
            {
                if (info.Args != null)
                {
                    foreach (ArgType type in info.Args)
                    {
                        switch (type)
                        {
                            case ArgType.MultinameU30:
                                args.Add(abc.GetMultiname((int)reader.ReadU30()));
                                break;

                            case ArgType.OffsetS24:
                                args.Add(reader.ReadSI24());
                                break;

                            case ArgType.StringU30:
                                args.Add(abc.StringConsts[reader.ReadU30()]);
                                break;

                            case ArgType.RegisterU30:
                            case ArgType.ObjectRegisterU30:
                            case ArgType.PropertyRegisterU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.ByteU8:
                                args.Add((byte)reader.ReadUI8());
                                break;

                            case ArgType.ShortU30:
                            case ArgType.IntU30:
                            case ArgType.UintU30:
                            case ArgType.DoubleU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.ShortS30:
                                args.Add((int)reader.ReadU30());
                                break;

                            case ArgType.ByteS8:
                                args.Add(reader.ReadSI8());
                                break;

                            case ArgType.NamespaceU30:
                                args.Add(abc.GetNamespace((int)reader.ReadU30()));
                                break;

                            case ArgType.MethodU30:
                                args.Add(abc.GetMethod((int)reader.ReadU30()));
                                break;

                            case ArgType.CountU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.ClassU30:
                                args.Add(abc.GetClass((int)reader.ReadU30()));
                                break;

                            case ArgType.ExceptionU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.StackU8:
                                args.Add((byte)reader.ReadUI8());
                                break;

                            case ArgType.SlotU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.DebugU8:
                                args.Add((byte)reader.ReadUI8());
                                break;

                            case ArgType.DebugTypeU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.StringU8:
                                args.Add(abc.StringConsts[reader.ReadUI8()]);
                                break;

                            case ArgType.LineNumberU30:
                                args.Add(reader.ReadU30());
                                break;

                            default:
                                /* ISSUE 73 */
                                throw new SWFModellerException(
                                        SWFModellerError.UnimplementedFeature,
                                        "Oops. Not done " + type.ToString());
                        }
                    }
                }
            }

            op.Args = args.ToArray();

            return op;
        }
Exemple #5
0
        /// <summary>
        /// Converts the method's bytecode into parsed opcodes, if it hasn't been
        /// disassembled already.
        /// </summary>
        /// <returns>Returns this method, for call chaining.</returns>
        public Method Disassemble()
        {
            if (this.opcodes != null)
            {
                // Already disassembled
                return(this);
            }

            ABCDataTypeReader reader = new ABCDataTypeReader(new MemoryStream(this.Bytes));

            List <Opcode> ops = new List <Opcode>();

            Dictionary <int, Opcode> offsetToOpcode = new Dictionary <int, Opcode>();
            Dictionary <Opcode, int> opcodeToOffset = new Dictionary <Opcode, int>();
            Dictionary <Opcode, int> opcodeLen      = new Dictionary <Opcode, int>();

            Opcode op = null;

            do
            {
                int offset = (int)reader.Offset;

                op = Opcode.BuildOpcode(reader, this.Code);

                if (op != null)
                {
#if (DEBUG)
                    op.NumberLabel = ++this.opcodeIndex;
#endif
                    int len = op.Mnemonic == Opcode.Mnemonics.LookupSwitch ? 0 : (int)reader.Offset - offset;

                    offsetToOpcode.Add(offset, op);
                    opcodeToOffset.Add(op, offset);
                    opcodeLen.Add(op, len);
                    ops.Add(op);
                }
            }while (op != null);

            foreach (ExceptionHandler eh in this.exceptionHandlers)
            {
                eh.From   = offsetToOpcode[eh.From];
                eh.To     = offsetToOpcode[eh.To];
                eh.Target = offsetToOpcode[eh.Target];
            }

            this.opcodes = ops.ToArray();

            foreach (Opcode hasOffsets in this.opcodes.Where(o => o.HasOffsets))
            {
                hasOffsets.OffsetProc(delegate(object arg)
                {
                    int offset  = (int)arg;
                    int current = opcodeToOffset[hasOffsets];
                    int len     = opcodeLen[hasOffsets];
                    int jumpTo  = current + offset + len;
                    return(offsetToOpcode[jumpTo]);
                });
            }

            return(this);
        }