Exemple #1
0
        private void buttonPitFileNameLoad_Click(object sender, EventArgs e)
        {
            if (!System.IO.File.Exists(textBoxPitFileName.Text))
            {
                MessageBox.Show("Error, Pit file does not exist.");
                return;
            }

            var currentCursor = this.Cursor;

            this.Cursor = Cursors.WaitCursor;

            try
            {
                var pitParser = new Peach.Core.Analyzers.PitParser();
                userSelectedDom = pitParser.asParser(null, textBoxPitFileName.Text);

                comboBoxPitDataModel.Items.Clear();
                foreach (var model in userSelectedDom.dataModels.Keys)
                {
                    comboBoxPitDataModel.Items.Add(model);
                }

                if (userSelectedDom.dataModels.Count > 0)
                {
                    comboBoxPitDataModel.SelectedIndex = 0;
                }

                label4.Enabled = true;
                comboBoxPitDataModel.Enabled = true;
            }
            catch (PeachException ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                this.Cursor = currentCursor;
            }
        }
Exemple #2
0
        /// <summary>
        /// Run the default fuzzing run in the specified dom.
        /// </summary>
        /// <param name="dom"></param>
        /// <param name="config"></param>
        public void startFuzzing(Dom.Dom dom, RunConfiguration config)
        {
            if (dom == null)
            {
                throw new ArgumentNullException("dom parameter is null");
            }
            if (config == null)
            {
                throw new ArgumentNullException("config paremeter is null");
            }

            Test test = null;

            try
            {
                test = dom.tests[config.runName];
            }
            catch (Exception ex)
            {
                throw new PeachException("Unable to locate test named '" + config.runName + "'.", ex);
            }

            startFuzzing(dom, test, config);
        }
Exemple #3
0
        public Program(string[] args)
        {
            AppDomain.CurrentDomain.DomainUnload += new EventHandler(CurrentDomain_DomainUnload);
            Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
            config       = new RunConfiguration();
            config.debug = 0;

            try
            {
                string analyzer      = null;
                bool   test          = false;
                string agent         = null;
                var    definedValues = new List <string>();
                bool   parseOnly     = false;

                var color = Console.ForegroundColor;
                Console.Write("\n");
                Console.ForegroundColor = ConsoleColor.DarkRed;
                Console.Write("[[ ");
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.WriteLine(ProductName);
                Console.ForegroundColor = ConsoleColor.DarkRed;
                Console.Write("[[ ");
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.WriteLine(Copyright);
                Console.ForegroundColor = color;

                if (args.Length == 0)
                {
                    Syntax();
                }

                var p = new OptionSet()
                {
                    { "h|?|help", v => Syntax() },
                    { "analyzer=", v => analyzer = v },
                    { "debug", v => config.debug = 1 },
                    { "trace", v => config.debug = 2 },
                    { "1", v => config.singleIteration = true },
                    { "range=", v => ParseRange(config, v) },
                    { "t|test", v => test = true },
                    { "c|count", v => config.countOnly = true },
                    { "skipto=", v => config.skipToIteration = Convert.ToUInt32(v) },
                    { "seed=", v => config.randomSeed = Convert.ToUInt32(v) },
                    { "p|parallel=", v => ParseParallel(config, v) },
                    { "a|agent=", v => agent = v },
                    { "D|define=", v => AddNewDefine(v) },
                    { "definedvalues=", v => definedValues.Add(v) },
                    { "config=", v => definedValues.Add(v) },
                    { "parseonly", v => parseOnly = true },
                    { "bob", var => bob() },                    //输出他的头像,醉了
                    { "charlie", var => Charlie() },            //醉了
                    { "showdevices", var => ShowDevices() },    //列出网卡设备信息
                    { "showenv", var => ShowEnvironment() },    //输出使用信息?基本属性的使用?
                    { "makexsd", var => MakeSchema() },         //生成Peach.xsd文件
                };

                List <string> extra = p.Parse(args);//extra[0]存放文件名即 pit文件.xml

                if (extra.Count == 0 && agent == null && analyzer == null)
                {
                    Syntax();
                }

                Platform.LoadAssembly();

                AddNewDefine("Peach.Cwd=" + Environment.CurrentDirectory);
                AddNewDefine("Peach.Pwd=" + Path.GetDirectoryName(Assembly.GetCallingAssembly().Location));

                // 判断是否有 pit文件.xml.config 文件,如果有我们就加载改文件
                // 注意:pit文件.xml.config 应该和 pit文件.xml文件放在同一目录下
                if (extra.Count > 0 && File.Exists(extra[0]) &&
                    extra[0].ToLower().EndsWith(".xml") &&
                    File.Exists(extra[0] + ".config"))
                {
                    definedValues.Insert(0, extra[0] + ".config");
                }

                foreach (var definedValuesFile in definedValues)
                {
                    var defs = PitParser.parseDefines(definedValuesFile);

                    foreach (var kv in defs)
                    {
                        // Allow command line to override values in XML file.
                        if (!DefinedValues.ContainsKey(kv.Key))
                        {
                            DefinedValues.Add(kv.Key, kv.Value);
                        }
                    }
                }

                // 如果需要则启动调试
                // 如果已经由.congig文件进行配置,则不会做任何更改
                ConfigureLogging(config.debug);

                if (agent != null)
                {
                    var agentType = ClassLoader.FindTypeByAttribute <AgentServerAttribute>((x, y) => y.name == agent);
                    if (agentType == null)
                    {
                        Console.WriteLine("错误, unable to locate agent server for protocol '" + agent + "'.\n");
                        return;
                    }

                    var agentServer = Activator.CreateInstance(agentType) as IAgentServer;

                    ConsoleWatcher.WriteInfoMark();
                    Console.WriteLine("启动代理服务...");

                    agentServer.Run(new Dictionary <string, string>());
                    return;
                }

                if (analyzer != null)
                {
                    var analyzerType = ClassLoader.FindTypeByAttribute <AnalyzerAttribute>((x, y) => y.Name == analyzer);
                    if (analyzerType == null)
                    {
                        Console.WriteLine("错误,无法定位名为'" + analyzer + "'的analyzer.\n");
                        return;
                    }

                    var field = analyzerType.GetField("supportCommandLine",
                                                      BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                    if ((bool)field.GetValue(null) == false)
                    {
                        Console.WriteLine("错误, 从命令行启动的analyzer还没有进行配置.");
                        return;
                    }

                    var analyzerInstance = Activator.CreateInstance(analyzerType) as Analyzer;

                    ConsoleWatcher.WriteInfoMark();
                    Console.WriteLine("启动Analyzer...");

                    analyzerInstance.asCommandLine(new Dictionary <string, string>());
                    return;
                }

                Dictionary <string, object> parserArgs = new Dictionary <string, object>();
                parserArgs[PitParser.DEFINED_VALUES] = this.DefinedValues;

                if (test)
                {
                    ConsoleWatcher.WriteInfoMark();
                    Console.Write("Validating file [" + extra[0] + "]... ");
                    Analyzer.defaultParser.asParserValidation(parserArgs, extra[0]);

                    if (Type.GetType("Mono.Runtime") != null)
                    {
                        Console.WriteLine("File parsed successfully, but XSD validation is not supported on the Mono runtime.");
                    }
                    else
                    {
                        Console.WriteLine("No Errors Found.");
                    }

                    return;
                }

                Engine e = new Engine(GetUIWatcher());
                dom            = GetParser(e).asParser(parserArgs, extra[0]);
                config.pitFile = extra[0];

                // 用于单元测试
                if (parseOnly)
                {
                    return;
                }

                foreach (string arg in args)
                {
                    config.commandLine += arg + " ";
                }

                if (extra.Count > 1)
                {
                    config.runName = extra[1];
                }

                e.startFuzzing(dom, config);

                exitCode = 0;
            }
            catch (SyntaxException)
            {
                // 由syntax()抛出,可忽略
            }
            catch (OptionException oe)
            {
                Console.WriteLine(oe.Message + "\n");
            }
            catch (PeachException ee)
            {
                if (config.debug > 0)
                {
                    Console.WriteLine(ee);
                }
                else
                {
                    Console.WriteLine(ee.Message + "\n");
                }
            }
            finally
            {
                // HACK - 需使用NLog 2.0的Mono
                ConfigureLogging(-1);

                // 重置控制台输出文字的颜色
                Console.ForegroundColor = DefaultForground;
            }
        }
Exemple #4
0
        /// <summary>
        /// Run a test case.  Contains main fuzzing loop.
        /// </summary>
        /// <param name="dom"></param>
        /// <param name="test"></param>
        /// <param name="context"></param>
        protected void runTest(Dom.Dom dom, Test test, RunContext context)
        {
            try
            {
                context.test = test;
                context.test.strategy.Context         = context;
                context.test.strategy.Engine          = this;
                context.agentManager                  = new AgentManager(context);
                context.reproducingFault              = false;
                context.reproducingIterationJumpCount = 1;

                if (context.config.userDefinedSeed && !test.strategy.UsesRandomSeed)
                {
                    var attr = ClassLoader.GetAttributes <MutationStrategyAttribute>(test.strategy.GetType(), null).Where(a => a.IsDefault == true).FirstOrDefault();
                    var name = attr != null ? attr.Name : test.strategy.GetType().Name;
                    var msg  = "The '{0}' mutation strategy does not allow setting the random seed.".Fmt(name);
                    OnTestWarning(context, msg);
                }

                // Get mutation strategy
                MutationStrategy mutationStrategy = test.strategy;
                mutationStrategy.Initialize(context, this);

                uint iterationStart       = 1;
                uint iterationStop        = uint.MaxValue;
                uint?iterationTotal       = null;
                uint lastControlIteration = 0;

                uint redoCount = 0;

                if (!mutationStrategy.IsDeterministic)
                {
                    if (context.config.parallel)
                    {
                        throw new PeachException("parallel is not supported when a non-deterministic mutation strategy is used");
                    }
                    if (context.config.countOnly)
                    {
                        throw new PeachException("count is not supported when a non-deterministic mutation strategy is used");
                    }
                }

                if (context.config.range)
                {
                    if (context.config.parallel)
                    {
                        throw new PeachException("range is not supported when parallel is used");
                    }

                    logger.Debug("runTest: context.config.range == true, start: " +
                                 context.config.rangeStart + ", stop: " + context.config.rangeStop);

                    iterationStart = context.config.rangeStart;
                    iterationStop  = context.config.rangeStop;
                }
                else if (context.config.skipToIteration > 1)
                {
                    logger.Debug("runTest: context.config.skipToIteration == " +
                                 context.config.skipToIteration);

                    iterationStart = context.config.skipToIteration;
                }

                iterationStart = Math.Max(1, iterationStart);

                uint lastReproFault = iterationStart - 1;
                uint iterationCount = iterationStart;
                bool firstRun       = true;

                // First iteration is always a control/recording iteration
                context.controlIteration          = true;
                context.controlRecordingIteration = true;

                test.markMutableElements();

                OnTestStarting(context);

                // Start agents
                foreach (Dom.Agent agent in test.agents.Values)
                {
                    // Only use agent if on correct platform
                    if ((agent.platform & Platform.GetOS()) != Platform.OS.None)
                    {
                        context.agentManager.AgentConnect(agent);
                        context.agentManager.GetAgent(agent.name).SessionStarting();

                        // Note: We want to perfrom SessionStarting on each agent
                        //       in turn.  We do this incase the first agent starts
                        //       a virtual machine that contains the second agent.
                    }
                }

                while ((firstRun || iterationCount <= iterationStop) && context.continueFuzzing)
                {
                    context.currentIteration = iterationCount;

                    firstRun = false;

                    // Clear out or iteration based state store
                    context.iterationStateStore.Clear();

                    // Should we perform a control iteration?
                    if (test.controlIteration > 0 && !context.reproducingFault)
                    {
                        if ((test.controlIteration == 1 || iterationCount % test.controlIteration == 1) && lastControlIteration != iterationCount)
                        {
                            context.controlIteration = true;
                        }
                    }

                    try
                    {
                        // Must set iteration 1st as strategy could enable control/record bools
                        mutationStrategy.Iteration = iterationCount;

                        if (context.controlIteration && context.controlRecordingIteration)
                        {
                            context.controlRecordingActionsExecuted.Clear();
                            context.controlRecordingStatesExecuted.Clear();
                        }

                        context.controlActionsExecuted.Clear();
                        context.controlStatesExecuted.Clear();


                        if (context.config.singleIteration && !context.controlIteration && iterationCount == 1)
                        {
                            logger.Debug("runTest: context.config.singleIteration == true");
                            break;
                        }

                        // Make sure we are not hanging on to old faults.
                        context.faults.Clear();

                        try
                        {
                            if (IterationStarting != null)
                            {
                                IterationStarting(context, iterationCount, iterationTotal.HasValue ? iterationStop : iterationTotal);
                            }

                            if (context.controlIteration)
                            {
                                if (context.controlRecordingIteration)
                                {
                                    logger.Debug("runTest: Performing recording iteration.");
                                }
                                else
                                {
                                    logger.Debug("runTest: Performing control iteration.");
                                }
                            }

                            context.agentManager.IterationStarting(iterationCount, context.reproducingFault);

                            test.stateModel.Run(context);
                        }
                        catch (SoftException se)
                        {
                            // We should just eat SoftExceptions.
                            // They indicate we should move to the next
                            // iteration.

                            if (context.controlRecordingIteration)
                            {
                                logger.Debug("runTest: SoftException on control recording iteration");
                                if (se.InnerException != null && string.IsNullOrEmpty(se.Message))
                                {
                                    throw new PeachException(se.InnerException.Message, se);
                                }
                                throw new PeachException(se.Message, se);
                            }

                            if (context.controlIteration)
                            {
                                logger.Debug("runTest: SoftException on control iteration, saving as fault");
                                var ex = se.InnerException ?? se;
                                OnControlFault(context, iterationCount, "SoftException Detected:\n" + ex.ToString());
                            }

                            logger.Debug("runTest: SoftException, skipping to next iteration");
                        }
                        catch (PathException)
                        {
                            // We should just eat PathException.
                            // They indicate we should move to the next
                            // iteration.

                            logger.Debug("runTest: PathException, skipping to next iteration");
                        }
                        catch (System.OutOfMemoryException ex)
                        {
                            logger.Debug(ex.Message);
                            logger.Debug(ex.StackTrace);
                            logger.Debug("runTest: " +
                                         "Warning: Iteration ended due to out of memory exception.  Continuing to next iteration.");

                            throw new SoftException("Out of memory");
                        }
                        finally
                        {
                            context.agentManager.IterationFinished();

                            if (IterationFinished != null)
                            {
                                IterationFinished(context, iterationCount);
                            }

                            // If this was a control iteration, verify it againt our origional
                            // recording.
                            if (context.controlRecordingIteration == false &&
                                context.controlIteration &&
                                !test.nonDeterministicActions)
                            {
                                if (context.controlRecordingActionsExecuted.Count != context.controlActionsExecuted.Count)
                                {
                                    string description = string.Format(@"The Peach control iteration performed failed
to execute same as initial control.  Number of actions is different. {0} != {1}",
                                                                       context.controlRecordingActionsExecuted.Count,
                                                                       context.controlActionsExecuted.Count);

                                    logger.Debug(description);
                                    OnControlFault(context, iterationCount, description);
                                }
                                else if (context.controlRecordingStatesExecuted.Count != context.controlStatesExecuted.Count)
                                {
                                    string description = string.Format(@"The Peach control iteration performed failed
to execute same as initial control.  Number of states is different. {0} != {1}",
                                                                       context.controlRecordingStatesExecuted.Count,
                                                                       context.controlStatesExecuted.Count);

                                    logger.Debug(description);
                                    OnControlFault(context, iterationCount, description);
                                }

                                if (context.faults.Count == 0)
                                {
                                    foreach (Dom.Action action in context.controlRecordingActionsExecuted)
                                    {
                                        if (!context.controlActionsExecuted.Contains(action))
                                        {
                                            string description = @"The Peach control iteration performed failed
to execute same as initial control.  Action " + action.name + " was not performed.";

                                            logger.Debug(description);
                                            OnControlFault(context, iterationCount, description);
                                        }
                                    }
                                }

                                if (context.faults.Count == 0)
                                {
                                    foreach (Dom.State state in context.controlRecordingStatesExecuted)
                                    {
                                        if (!context.controlStatesExecuted.Contains(state))
                                        {
                                            string description = @"The Peach control iteration performed failed
to execute same as initial control.  State " + state.name + "was not performed.";

                                            logger.Debug(description);
                                            OnControlFault(context, iterationCount, description);
                                        }
                                    }
                                }
                            }
                        }

                        // User can specify a time to wait between iterations
                        // we can use that time to better detect faults
                        if (context.test.waitTime > 0)
                        {
                            Thread.Sleep((int)(context.test.waitTime * 1000));
                        }

                        if (context.reproducingFault)
                        {
                            // User can specify a time to wait between iterations
                            // when reproducing faults.
                            if (context.test.faultWaitTime > 0)
                            {
                                Thread.Sleep((int)(context.test.faultWaitTime * 1000));
                            }
                        }

                        // Collect any faults that were found
                        context.OnCollectFaults();

                        if (context.faults.Count > 0)
                        {
                            logger.Debug("runTest: detected fault on iteration " + iterationCount);

                            foreach (Fault fault in context.faults)
                            {
                                fault.iteration                 = iterationCount;
                                fault.controlIteration          = context.controlIteration;
                                fault.controlRecordingIteration = context.controlRecordingIteration;
                            }

                            if (context.reproducingFault || !test.replayEnabled)
                            {
                                OnFault(context, iterationCount, test.stateModel, context.faults.ToArray());
                            }
                            else
                            {
                                OnReproFault(context, iterationCount, test.stateModel, context.faults.ToArray());
                            }

                            if (context.controlRecordingIteration && (!test.replayEnabled || context.reproducingFault))
                            {
                                logger.Debug("runTest: Fault detected on control iteration");
                                throw new PeachException("Fault detected on control iteration.");
                            }

                            if (context.reproducingFault)
                            {
                                lastReproFault = iterationCount;

                                // If we have moved less than 20 iterations, start fuzzing
                                // from here thinking we may have not really performed the
                                // next few iterations.

                                // Otherwise skip forward to were we left off.

                                if (context.reproducingInitialIteration - iterationCount > 20)
                                {
                                    iterationCount = (uint)context.reproducingInitialIteration;
                                }

                                context.reproducingFault = false;
                                context.reproducingIterationJumpCount = 1;

                                logger.Debug("runTest: Reproduced fault, continuing fuzzing at iteration " + iterationCount);
                            }
                            else if (test.replayEnabled)
                            {
                                logger.Debug("runTest: Attempting to reproduce fault.");

                                context.reproducingFault              = true;
                                context.reproducingInitialIteration   = iterationCount;
                                context.reproducingIterationJumpCount = 1;

                                // User can specify a time to wait between iterations
                                // we can use that time to better detect faults
                                if (context.test.waitTime > 0)
                                {
                                    Thread.Sleep((int)(context.test.waitTime * 1000));
                                }

                                // User can specify a time to wait between iterations
                                // when reproducing faults.
                                if (context.test.faultWaitTime > 0)
                                {
                                    Thread.Sleep((int)(context.test.faultWaitTime * 1000));
                                }

                                logger.Debug("runTest: replaying iteration " + iterationCount);
                                continue;
                            }
                        }
                        else if (context.reproducingFault)
                        {
                            uint maxJump = context.reproducingInitialIteration - lastReproFault - 1;

                            if (context.reproducingIterationJumpCount >= (maxJump * 2) || context.reproducingIterationJumpCount > context.reproducingMaxBacksearch)
                            {
                                logger.Debug("runTest: Giving up reproducing fault, reached max backsearch.");

                                context.reproducingFault = false;
                                iterationCount           = context.reproducingInitialIteration;

                                OnReproFailed(context, iterationCount);
                            }
                            else
                            {
                                uint delta = Math.Min(maxJump, context.reproducingIterationJumpCount);
                                iterationCount = (uint)context.reproducingInitialIteration - delta - 1;

                                logger.Debug("runTest: " +
                                             "Moving backwards " + delta + " iterations to reproduce fault.");
                            }

                            // Make next jump larger
                            context.reproducingIterationJumpCount *= context.reproducingSkipMultiple;
                        }

                        if (context.agentManager.MustStop())
                        {
                            logger.Debug("runTest: agents say we must stop!");

                            throw new PeachException("Error, agent monitor stopped run!");
                        }

                        // Update our totals and stop based on new count
                        if (context.controlIteration && context.controlRecordingIteration && !iterationTotal.HasValue)
                        {
                            if (context.config.countOnly)
                            {
                                OnHaveCount(context, mutationStrategy.Count);
                                break;
                            }

                            iterationTotal = mutationStrategy.Count;
                            if (iterationTotal < iterationStop)
                            {
                                iterationStop = iterationTotal.Value;
                            }

                            if (context.config.parallel)
                            {
                                if (iterationTotal < context.config.parallelTotal)
                                {
                                    throw new PeachException(string.Format("Error, {1} parallel machines is greater than the {0} total iterations.", iterationTotal, context.config.parallelTotal));
                                }

                                var range = Utilities.SliceRange(1, iterationStop, context.config.parallelNum, context.config.parallelTotal);

                                iterationStart = range.Item1;
                                iterationStop  = range.Item2;

                                OnHaveParallel(context, iterationStart, iterationStop);

                                if (context.config.skipToIteration > iterationStart)
                                {
                                    iterationStart = context.config.skipToIteration;
                                }

                                iterationCount = iterationStart;
                            }
                        }

                        // Don't increment the iteration count if we are on a
                        // control iteration
                        if (!context.controlIteration)
                        {
                            ++iterationCount;
                        }

                        redoCount = 0;
                    }
                    catch (RedoIterationException rte)
                    {
                        logger.Debug("runTest: redoing test iteration for the " + redoCount + " time.");

                        // Repeat the same iteration unless
                        // we have already retried 3 times.

                        if (redoCount >= 3)
                        {
                            throw new PeachException(rte.Message, rte);
                        }

                        redoCount++;
                    }
                    finally
                    {
                        if (!context.reproducingFault)
                        {
                            if (context.controlIteration)
                            {
                                lastControlIteration = iterationCount;
                            }

                            context.controlIteration          = false;
                            context.controlRecordingIteration = false;
                        }
                    }
                }
            }
            catch (MutatorCompleted)
            {
                // Ignore, signals end of fuzzing run
                logger.Debug("runTest: MutatorCompleted exception, ending fuzzing");
            }
            finally
            {
                foreach (Publisher publisher in context.test.publishers.Values)
                {
                    try
                    {
                        publisher.stop();
                    }
                    catch
                    {
                    }
                }

                context.agentManager.SessionFinished();
                context.agentManager.StopAllMonitors();
                context.agentManager.Shutdown();
                OnTestFinished(context);

                context.test = null;

                test.strategy.Finalize(context, this);
            }
        }
Exemple #5
0
 public virtual void asTopLevel(Dom.Dom dom, Dictionary <string, string> args)
 {
     throw new NotImplementedException();
 }
Exemple #6
0
        public Program(string[] args)
        {
            AppDomain.CurrentDomain.DomainUnload += new EventHandler(CurrentDomain_DomainUnload);
            Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
            RunConfiguration config = new RunConfiguration();

            config.debug = false;

            try
            {
                string analyzer      = null;
                bool   test          = false;
                string agent         = null;
                var    definedValues = new List <string>();
                bool   parseOnly     = false;

                var color = Console.ForegroundColor;
                Console.Write("\n");
                Console.ForegroundColor = ConsoleColor.DarkRed;
                Console.Write("[[ ");
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.WriteLine(ProductName);
                Console.ForegroundColor = ConsoleColor.DarkRed;
                Console.Write("[[ ");
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.WriteLine(Copyright);
                Console.WriteLine();
                Console.ForegroundColor = color;

                if (args.Length == 0)
                {
                    Syntax();
                }

                var p = new OptionSet()
                {
                    { "h|?|help", v => Syntax() },
                    { "analyzer=", v => analyzer = v },
                    { "debug", v => config.debug = true },
                    { "1", v => config.singleIteration = true },
                    { "range=", v => ParseRange(config, v) },
                    { "t|test", v => test = true },
                    { "c|count", v => config.countOnly = true },
                    { "skipto=", v => config.skipToIteration = Convert.ToUInt32(v) },
                    { "seed=", v => config.randomSeed = Convert.ToUInt32(v) },
                    { "p|parallel=", v => ParseParallel(config, v) },
                    { "a|agent=", v => agent = v },
                    { "D|define=", v => AddNewDefine(v) },
                    { "definedvalues=", v => definedValues.Add(v) },
                    { "parseonly", v => parseOnly = true },
                    { "bob", var => bob() },
                    { "charlie", var => Charlie() },
                    { "showdevices", var => ShowDevices() },
                    { "showenv", var => ShowEnvironment() },
                    { "inputFilePath=", v => config.inputFilePath = v },
                    { "outputFilePath=", v => config.outputFilePath = v },
                };

                List <string> extra = p.Parse(args);

                if (extra.Count == 0 && agent == null && analyzer == null)
                {
                    Syntax();
                }

                Platform.LoadAssembly();

                AddNewDefine("Peach.Cwd=" + Environment.CurrentDirectory);

                foreach (var definedValuesFile in definedValues)
                {
                    var defs = PitParser.parseDefines(definedValuesFile);

                    foreach (var kv in defs)
                    {
                        // Allow command line to override values in XML file.
                        if (!DefinedValues.ContainsKey(kv.Key))
                        {
                            DefinedValues.Add(kv.Key, kv.Value);
                        }
                    }
                }

                // Enable debugging if asked for
                if (config.debug)
                {
                    var nconfig       = new LoggingConfiguration();
                    var consoleTarget = new ColoredConsoleTarget();
                    nconfig.AddTarget("console", consoleTarget);
                    consoleTarget.Layout = "${logger} ${message}";

                    var rule = new LoggingRule("*", LogLevel.Debug, consoleTarget);
                    nconfig.LoggingRules.Add(rule);

                    LogManager.Configuration = nconfig;
                }

                if (agent != null)
                {
                    var agentType = ClassLoader.FindTypeByAttribute <AgentServerAttribute>((x, y) => y.name == agent);
                    if (agentType == null)
                    {
                        Console.WriteLine("Error, unable to locate agent server for protocol '" + agent + "'.\n");
                        return;
                    }

                    var agentServer = Activator.CreateInstance(agentType) as IAgentServer;

                    ConsoleWatcher.WriteInfoMark();
                    Console.WriteLine("Starting agent server");

                    agentServer.Run(new Dictionary <string, string>());
                    return;
                }

                if (analyzer != null)
                {
                    var analyzerType = ClassLoader.FindTypeByAttribute <AnalyzerAttribute>((x, y) => y.Name == analyzer);
                    if (analyzerType == null)
                    {
                        Console.WriteLine("Error, unable to locate analyzer called '" + analyzer + "'.\n");
                        return;
                    }

                    var field = analyzerType.GetField("supportCommandLine",
                                                      BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                    if ((bool)field.GetValue(null) == false)
                    {
                        Console.WriteLine("Error, analyzer not configured to run from command line.");
                        return;
                    }

                    var analyzerInstance = Activator.CreateInstance(analyzerType) as Analyzer;

                    ConsoleWatcher.WriteInfoMark();
                    Console.WriteLine("Starting Analyzer");

                    analyzerInstance.asCommandLine(new Dictionary <string, string>());
                    return;
                }

                Dictionary <string, object> parserArgs = new Dictionary <string, object>();
                parserArgs[PitParser.DEFINED_VALUES] = this.DefinedValues;

                if (test)
                {
                    ConsoleWatcher.WriteInfoMark();
                    Console.Write("Validating file [" + extra[0] + "]... ");
                    Analyzer.defaultParser.asParserValidation(parserArgs, extra[0]);

                    if (Type.GetType("Mono.Runtime") != null)
                    {
                        Console.WriteLine("File parsed successfully, but XSD validation is not supported on the Mono runtime.");
                    }
                    else
                    {
                        Console.WriteLine("No Errors Found.");
                    }

                    return;
                }

                Engine e = new Engine(GetUIWatcher());
                dom            = GetParser(e).asParser(parserArgs, extra[0]);
                config.pitFile = extra[0];

                // Used for unittests
                if (parseOnly)
                {
                    return;
                }

                foreach (string arg in args)
                {
                    config.commandLine += arg + " ";
                }

                if (extra.Count > 1)
                {
                    if (!dom.tests.ContainsKey(extra[1]))
                    {
                        throw new PeachException("Error, unable to locate test named \"" + extra[1] + "\".");
                    }

                    e.startFuzzing(dom, dom.tests[extra[1]], config);
                }
                else
                {
                    e.startFuzzing(dom, config);
                }

                exitCode = 0;
            }
            catch (SyntaxException)
            {
                // Ignore, thrown by syntax()
            }
            catch (OptionException oe)
            {
                Console.WriteLine(oe.Message + "\n");
            }
            catch (PeachException ee)
            {
                if (config.debug)
                {
                    Console.WriteLine(ee);
                }
                else
                {
                    Console.WriteLine(ee.Message + "\n");
                }
            }
            finally
            {
                // HACK - Required on Mono with NLog 2.0
                LogManager.Configuration = null;

                // Reset console colors
                Console.ForegroundColor = DefaultForground;
            }
        }