コード例 #1
0
ファイル: FuzzerServer.cs プロジェクト: Red4Sec/TuringMachine
        /// <summary>
        /// Start Pipe server
        /// </summary>
        /// <param name="connection">Connection</param>
        public void Start(FuzzerConnectionBase connection)
        {
            if (IsStarted)
            {
                throw new Exception("Already started");
            }

            try
            {
                _cancel      = new CancellationTokenSource();
                _disposables = new ConcurrentBag <IDisposable>();

                if (connection is FuzzerNamedPipeConnection pipe)
                {
                    _tasks    = new Task[5];
                    _tasks[0] = new Task(() => ProcessLogBagAsync(_cancel.Token));

                    for (int x = 1; x < _tasks.Length; x++)
                    {
                        _tasks[x] = new Task(() =>
                        {
                            var client = new FuzzerClientInfo()
                            {
                                Id           = Guid.NewGuid(),
                                Description  = "." + pipe.PipeName,
                                InternalName = "." + pipe.PipeName
                            };

                            while (!_cancel.Token.IsCancellationRequested)
                            {
                                NamedPipeServerStream server = null;

                                try
                                {
                                    _cancel.Token.ThrowIfCancellationRequested();

                                    server = new NamedPipeServerStream(pipe.PipeName, PipeDirection.InOut, _tasks.Length, PipeTransmissionMode.Byte);

                                    _disposables.Add(server);
                                    server.WaitForConnection();

                                    UpdateFromStream(new FuzzerStat <FuzzerClientInfo>(client), server, _cancel.Token);
                                }
                                catch                                 // (Exception ex)
                                {
                                    // Pipe error
                                }
                                finally
                                {
                                    try { server?.Dispose(); } catch { }
                                    _cancel?.Token.ThrowIfCancellationRequested();
                                }

                                Thread.Sleep(50);
                            }
                        },
                                             _cancel.Token);
                    }
                }
                else if (connection is FuzzerTcpConnection tcp)
                {
                    _tasks = new Task[]
                    {
                        new Task(() => ProcessLogBagAsync(_cancel.Token)),
                        new Task(() =>
                        {
                            var server = new TcpListener(tcp.EndPoint);
                            _disposables.Add(server.Server);

                            server.Start();
                            server.BeginAcceptTcpClient(OnNewTcpClient, server);
                            //var res = server.BeginAcceptTcpClient(OnNewTcpClient, server);
                            //_disposables.Add(res.AsyncWaitHandle);
                        },
                                 _cancel.Token)
                    };
                }
                else
                {
                    if (connection == null)
                    {
                        throw new NullReferenceException(nameof(connection));
                    }

                    throw new ArgumentException(nameof(connection));
                }

                _tasks.All(u =>
                {
                    u.Start();
                    return(true);
                });
            }
            catch (Exception e)
            {
                Stop();
                throw e;
            }
        }
コード例 #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();
                }
        }
コード例 #3
0
ファイル: FuzzerClient.cs プロジェクト: Red4Sec/TuringMachine
        /// <summary>
        /// Start Pipe connection
        /// </summary>
        /// <param name="connection">Connection</param>
        public void Start(FuzzerConnectionBase connection)
        {
            if (IsStarted)
            {
                throw new Exception("Already started");
            }

            if (connection is FuzzerNamedPipeConnection pipe)
            {
                var client = new NamedPipeClientStream(".", pipe.PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
                client.Connect(10_000);
                _client = client;
            }
            else if (connection is FuzzerTcpConnection tcp)
            {
#pragma warning disable IDE0067 // Dispose objects before losing scope
                var client = new TcpClient();
#pragma warning restore IDE0067 // Dispose objects before losing scope
                client.Connect(tcp.EndPoint);
                _client = client.GetStream();
            }
            else
            {
                if (connection == null)
                {
                    throw new NullReferenceException(nameof(connection));
                }

                throw new ArgumentException(nameof(connection));
            }

            _cancel = new CancellationTokenSource();
            _tasks  = new Task[]
            {
                new Task(() => UpdateFromStream(_client, _cancel.Token), _cancel.Token),
                new Task(() => FlushBuffer(_cancel.Token), _cancel.Token)
            };
            _tasks.All(u =>
            {
                u.Start();
                return(true);
            });

            // Request Configs and inputs

            var send = new List <byte>(new byte[]
            {
                (byte)EFuzzerMessageType.GetAvailableConfigs,
                (byte)EFuzzerMessageType.GetAvailableInputs
            });

            if (!string.IsNullOrWhiteSpace(PublicName))
            {
                send.AddRange(GetMessage(EFuzzerMessageType.PushPublicName, PublicName));
            }

            lock (_client)
            {
                _client.Write(send.ToArray(), 0, send.Count);
                _client.Flush();
            }
        }