Example #1
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
        }
Example #2
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
            }
        }
Example #3
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
            }
        }
Example #4
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
            }
        }
Example #5
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
            }
        }