Ejemplo n.º 1
0
        public void Log()
        {
            var log = new FuzzerLog()
            {
                ConfigId = Guid.NewGuid(),
                InputId  = Guid.NewGuid(),
                Coverage = 100.12
            };

            var json = SerializationHelper.SerializeToJson(log, true);
            var copy = SerializationHelper.DeserializeFromJson <FuzzerLog>(json);

            Assert.IsTrue(log.Equals(copy));
            Assert.IsTrue(log.Equals((object)copy));
            Assert.IsFalse(log.Equals(new object()));
            Assert.AreEqual(log.GetHashCode(), copy.GetHashCode());

            copy.ConfigId = Guid.NewGuid();
            Assert.AreNotEqual(log.GetHashCode(), copy.GetHashCode());
        }
Ejemplo n.º 2
0
        private void Test(FuzzerConnectionBase serverConnection, FuzzerConnectionBase clientConnection)
        {
            Fuzzer.Client.ExecutionTimeOut = TimeSpan.FromMilliseconds(5_000);

            using (var server = new FuzzerServer())
                using (var client = new FuzzerClient())
                {
                    // Change name

                    client.PublicName = "TestClient_" + Guid.NewGuid().ToString();

                    // Ensure no error

                    client.SendLog(null);

                    // Dummy input

                    var entryIBuffer = new byte[100];
                    RandomHelper.FillWithRandomBytes(entryIBuffer);

                    var entryI = new FuzzerStat <FuzzingInputBase>(new ManualFuzzingInput(entryIBuffer)
                    {
                        Description = "1"
                    });
                    server.Inputs.Add(entryI.Source.Id, entryI);
                    entryI = new FuzzerStat <FuzzingInputBase>(new RandomFuzzingInput(new FromToValue <long>(100, 200))
                    {
                        Description = "2"
                    });
                    server.Inputs.Add(entryI.Source.Id, entryI);

                    // Dummy configurations

                    var entryC = new FuzzerStat <FuzzingConfigBase>(new PatchConfig("1", new PatchChange("1", 1, 1, new byte[0])));
                    server.Configurations.Add(entryC.Source.Id, entryC);
                    entryC = new FuzzerStat <FuzzingConfigBase>(new PatchConfig("2", new PatchChange("2", 2, 2, new byte[0])));
                    server.Configurations.Add(entryC.Source.Id, entryC);

                    // Check server

                    CheckConfig(() => ((IRandomValue <FuzzingConfigBase>)server).Get(), server.Configurations.Select(u => u.Value.Source).ToArray());
                    CheckConfig(() => ((IRandomValue <FuzzingInputBase>)server).Get(), server.Inputs.Select(u => u.Value.Source).ToArray());
                    CheckConfig(() => server.GetConfig(), server.Configurations.Select(u => u.Value.Source).ToArray());
                    CheckConfig(() => server.GetInput(), server.Inputs.Select(u => u.Value.Source).ToArray());

                    // Start

                    Assert.IsFalse(server.IsStarted);
                    Assert.IsFalse(client.IsStarted);

                    if (serverConnection == null && clientConnection == null)
                    {
                        Assert.Catch <NullReferenceException>(() => server.Start(serverConnection));
                        Assert.Catch <NullReferenceException>(() => client.Start(clientConnection));
                        return;
                    }
                    else
                    {
                        if (serverConnection is TestDummyConnection && clientConnection is TestDummyConnection)
                        {
                            Assert.Catch <ArgumentException>(() => server.Start(serverConnection));
                            Assert.Catch <ArgumentException>(() => client.Start(clientConnection));
                            return;
                        }
                    }

                    var waitInput    = new ManualResetEvent(false);
                    var waitConfigs  = new ManualResetEvent(false);
                    var waitLog      = new ManualResetEvent(false);
                    var waitLogError = new ManualResetEvent(false);

                    client.OnReceiveInputs         += (s, e) => waitInput.Set();
                    client.OnReceiveConfigurations += (s, e) => waitConfigs.Set();
                    server.OnReceiveLog            += (s, e) => (e.Any(u => u.Error != null) ? waitLogError : waitLog).Set();

                    server.Start(serverConnection);
                    Thread.Sleep(250);             // Wait for server
                    client.Start(clientConnection);

                    Assert.IsTrue(server.IsStarted);
                    Assert.IsTrue(client.IsStarted);

                    // Already started

                    Assert.Catch <Exception>(() => server.Start(serverConnection));
                    Assert.Catch <Exception>(() => client.Start(clientConnection));

                    // Check client

                    Assert.IsTrue(waitConfigs.WaitOne(TimeSpan.FromSeconds(10)), "Waiting for configs");
                    Assert.IsTrue(waitInput.WaitOne(TimeSpan.FromSeconds(10)), "Waiting for inputs");

                    Assert.AreEqual(1, server.Connections.Count);
                    Assert.IsTrue(server.Connections.Values.FirstOrDefault()?.Source.Description.Contains(client.PublicName));
                    Assert.AreNotEqual(Guid.Empty, server.Connections.Values.FirstOrDefault()?.Source.Id);
                    Assert.AreNotEqual(Guid.Empty, server.Connections.Values.FirstOrDefault()?.Id);

                    var speedInit = server.Connections.Values.FirstOrDefault().Source.Speed;

                    CheckConfig(() => ((IRandomValue <FuzzingConfigBase>)client).Get(), server.Configurations.Select(u => u.Value.Source).ToArray());
                    CheckConfig(() => ((IRandomValue <FuzzingInputBase>)client).Get(), server.Inputs.Select(u => u.Value.Source).ToArray());
                    CheckConfig(() => client.GetConfig(), server.Configurations.Select(u => u.Value.Source).ToArray());
                    CheckConfig(() => client.GetInput(), server.Inputs.Select(u => u.Value.Source).ToArray());

                    // Send log

                    var cfg   = client.GetConfig();
                    var input = client.GetInput();
                    var log   = new FuzzerLog()
                    {
                        ConfigId = cfg.Id,
                        InputId  = input.Id,
                        Coverage = 10,
                    };

                    var sIn  = server.Inputs.Select(u => u.Value).Where(u => u.Source.Id == log.InputId).FirstOrDefault();
                    var sCfg = server.Configurations.Select(u => u.Value).Where(u => u.Source.Id == log.ConfigId).FirstOrDefault();

                    Assert.AreEqual(0, server.Logs.Count);
                    Assert.AreEqual(0, server.UniqueErrors);
                    Assert.AreEqual(0, server.TotalErrors);

                    client.SendLog(log);

                    Assert.IsTrue(waitLog.WaitOne(TimeSpan.FromSeconds(10)), "Waiting for log");

                    Assert.AreEqual(0, server.Logs.Count);
                    Assert.AreEqual(0, server.UniqueErrors);
                    Assert.AreEqual(0, server.TotalErrors);

                    Thread.Sleep(250);

                    Assert.IsTrue(server.Connections.Values.FirstOrDefault().Source.Speed > speedInit);
                    Assert.AreEqual(log.Coverage, server.Connections.Values.FirstOrDefault().Source.Coverage);

                    // Check stats

                    Assert.AreEqual(1, sIn.Tests);
                    Assert.AreEqual(1, sCfg.Tests);
                    Assert.AreEqual(0, sIn.Crashes);
                    Assert.AreEqual(0, sCfg.Crashes);
                    Assert.AreEqual(0, sIn.Errors);
                    Assert.AreEqual(0, sCfg.Errors);

                    // Send error

                    log = new FuzzerLog()
                    {
                        ConfigId = cfg.Id,
                        InputId  = input.Id,
                        Error    = new FuzzerError()
                        {
                            ErrorId           = Guid.NewGuid(),
                            Error             = FuzzerError.EFuzzingErrorType.Crash,
                            ExplotationResult = FuzzerError.EExplotationResult.Exploitable,
                            ReplicationData   = new byte[0],
                        }
                    };

                    Assert.AreEqual(0, server.UniqueErrors);
                    Assert.AreEqual(0, server.TotalErrors);
                    client.SendLog(log);

                    waitLogError.Reset();
                    Assert.IsTrue(waitLogError.WaitOne(TimeSpan.FromSeconds(10)), "Waiting for error");

                    Assert.AreEqual(1, server.Logs.Count);
                    Assert.IsTrue(server.Logs.TryGetValue(log.Error.ErrorId, out var peekLog));
                    Assert.IsTrue(log.Equals(peekLog));
                    Assert.AreEqual(1, server.UniqueErrors);
                    Assert.AreEqual(1, server.TotalErrors);

                    // Check stats

                    Assert.AreEqual(2, sIn.Tests);
                    Assert.AreEqual(2, sCfg.Tests);
                    Assert.AreEqual(1, sIn.Crashes);
                    Assert.AreEqual(1, sCfg.Crashes);
                    Assert.AreEqual(0, sIn.Errors);
                    Assert.AreEqual(0, sCfg.Errors);

                    // Generic MultiClient

                    FuzzerLog gerr = null;
                    Fuzzer.Client.Stop();
                    if (serverConnection != clientConnection)
                    {
                        // Test default
                        Fuzzer.Client.Start(clientConnection);
                    }

                    waitLogError.Reset();

                    Fuzzer.Run(FuzWERSample, new FuzzerRunArgs()
                    {
                        OnLog = (l, c) =>
                        {
                            if (l.Error != null)
                            {
                                c.Cancel = true;
                                gerr     = l;
                            }
                        }
                    });

                    // Could spend more time because are more tests

                    Assert.IsTrue(waitLogError.WaitOne(TimeSpan.FromSeconds(30)), "Waiting for error");
                    Assert.AreEqual(2, server.Logs.Count);
                    Assert.IsTrue(server.Logs.TryGetValue(gerr.Error.ErrorId, out peekLog));
                    Assert.IsTrue(gerr.Equals(peekLog));
                    Assert.IsTrue(gerr.Error.ReplicationData.Length > 0);
                    Assert.AreEqual(FuzzerError.EExplotationResult.Exploitable, gerr.Error.ExplotationResult);
                    Assert.AreEqual(FuzzerError.EFuzzingErrorType.Crash, gerr.Error.Error);
                    Assert.AreEqual(2, server.UniqueErrors);
                    Assert.AreEqual(2, server.TotalErrors);

                    // Generic MultiThread Client

                    gerr = null;
                    Fuzzer.Client.Stop();
                    Thread.Sleep(250);             // Wait some time for pipes

                    if (serverConnection != clientConnection)
                    {
                        // Test default
                        Fuzzer.Client.Start(clientConnection);
                    }

                    waitLogError.Reset();

                    Fuzzer.Run(1, FuzMultiThreadSample, new FuzzerRunArgs()
                    {
                        OnLog = (l, c) =>
                        {
                            if (l.Error != null)
                            {
                                c.Cancel = true;
                                gerr     = l;
                            }
                        }
                    });

                    // Could spend more time because are more tests

                    Assert.IsTrue(waitLogError.WaitOne(TimeSpan.FromSeconds(30)), "Waiting for error");
                    Assert.AreEqual(3, server.Logs.Count);
                    Assert.IsTrue(server.Logs.TryGetValue(gerr.Error.ErrorId, out peekLog));
                    Assert.IsTrue(gerr.Equals(peekLog));
                    Assert.IsTrue(gerr.Error.ReplicationData.Length > 0);
                    Assert.AreEqual(3, server.UniqueErrors);
                    Assert.AreEqual(3, server.TotalErrors);

                    // Test timeout

                    gerr = null;
                    waitLogError.Reset();

                    Fuzzer.Client.ExecutionTimeOut = TimeSpan.FromMilliseconds(250);
                    Fuzzer.Run(FuzTimeoutSample, new FuzzerRunArgs()
                    {
                        OnLog = (l, c) =>
                        {
                            c.Cancel = true;

                            if (l.Error != null)
                            {
                                gerr = l;
                            }
                        }
                    });

                    Assert.IsTrue(waitLogError.WaitOne(TimeSpan.FromSeconds(5)), "Waiting for error");
                    Assert.AreEqual(4, server.Logs.Count);
                    Assert.IsTrue(server.Logs.TryGetValue(gerr.Error.ErrorId, out peekLog));
                    Assert.IsTrue(gerr.Equals(peekLog));
                    Assert.IsTrue(gerr.Error.ReplicationData.Length > 0);
                    Assert.AreEqual(4, server.UniqueErrors);
                    Assert.AreEqual(4, server.TotalErrors);

                    // Current stream

                    var           logReaded = new byte[255];
                    var           current   = new byte[logReaded.Length];
                    FuzzingStream fuzStream = null;

                    Fuzzer.Run((stream) =>
                    {
                        Array.Resize(ref current, stream.Read(current, 0, current.Length));
                        fuzStream = (FuzzingStream)stream;
                        Assert.IsNotNull(fuzStream.CurrentStream);
                    },
                               new FuzzerRunArgs()
                    {
                        StoreCurrent = true,
                        OnLog        = (l, c) =>
                        {
                            // Read current file

                            var fCurrent = ((FileStream)fuzStream.CurrentStream);
                            fCurrent.Seek(0, SeekOrigin.Begin);
                            Array.Resize(ref logReaded, fCurrent.Read(logReaded, 0, logReaded.Length));
                            c.Cancel = true;
                        },
                    });

                    Assert.IsNotNull(fuzStream);
                    Assert.IsNotNull(fuzStream.CurrentStream);
                    CollectionAssert.AreEqual(current, logReaded);

                    // Clean

                    Fuzzer.Client.Stop();

                    waitInput.Dispose();
                    waitConfigs.Dispose();
                    waitLog.Dispose();
                    waitLogError.Dispose();
                }
        }