/// <summary> /// Constructor /// </summary> /// <param name="endPoint">EndPoint</param> /// <param name="server">Server</param> /// <param name="httpsCertFile">HTTPS certificate file</param> /// <param name="httpsPassword">HTTPS certificate password</param> public RpcServer(IPEndPoint endPoint, FuzzerServer server, string httpsCertFile, string httpsPassword) { EndPoint = endPoint; Server = server; HTTPSCertFile = httpsCertFile; HTTPSCertificatePassword = httpsPassword; }
private static void PrintStats(FuzzerServer server) { if (Interlocked.Exchange(ref _refreshRequested, 0x01) == 0x01) { return; } new Task(() => { AsyncPrintStats(server); Interlocked.Exchange(ref _refreshRequested, 0x00); }) .Start(); }
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(); } }
private static void Run(CmdOptions opts) { using (var server = new FuzzerServer()) { RpcServer rpc = null; if (!string.IsNullOrEmpty(opts.RpcEndPoint)) { rpc = new RpcServer(opts.RpcEndPoint.ToIpEndPoint(), server, opts.RpcHttpsCertificate, opts.RpcHttpsCertificatePassword); rpc.Start(); } // Parse foreach (var file in CmdOptions.GetFiles(opts.Inputs)) { foreach (var i in SerializationHelper.DeserializeFromFile <FuzzingInputBase>(file)) { server.Inputs.Add(i.Id, new FuzzerStat <FuzzingInputBase>(i)); } } foreach (var file in CmdOptions.GetFiles(opts.Configs)) { foreach (var i in SerializationHelper.DeserializeFromFile <FuzzingConfigBase>(file)) { server.Configurations.Add(i.Id, new FuzzerStat <FuzzingConfigBase>(i)); } } // Checks if (server.Inputs.Count == 0 && rpc == null) { Console.WriteLine("No inputs found"); return; } if (server.Configurations.Count == 0) { // Create an empty mutation, only the original value _showMutations = false; var empty = new PatchConfig() { Changes = new List <PatchChange>(), Description = "Original input", Id = Guid.Empty }; server.Configurations.Add(empty.Id, new FuzzerStat <FuzzingConfigBase>(empty)); } server.Start(opts.GetConnection()); // Listener server.OnNewConnection += (s, e) => { PrintStats(server); }; server.OnReceiveLog += (s2, logs) => { foreach (var log in logs) { log.Error?.Save(opts.OnlyUniques); } PrintStats(server); }; // UI do { Console.Clear(); PrintStats(server); }while (Console.ReadKey().Key != ConsoleKey.Enter); rpc?.Dispose(); } }
private static void AsyncPrintStats(FuzzerServer server) { TitleColumnLength = Math.Max(20, (Console.WindowWidth - 1) - StatColumnLength * 3); Console.CursorVisible = false; Console.SetCursorPosition(0, 0); // Write data var colorBottom = ConsoleColor.White; var cellTitle = new ConsoleBox.Cell("Inputs", TitleColumnLength); var cellConfigurations = new ConsoleBox.Cell("Configurations", TitleColumnLength); var cellConnections = new ConsoleBox.Cell("Connections", TitleColumnLength - (StatColumnLength * 2)); var cellSpeed = new ConsoleBox.Cell("Speed".PadLeft(StatColumnLength - 1, ' '), StatColumnLength); var cellCoverage = new ConsoleBox.Cell("Coverage".PadLeft(StatColumnLength - 1, ' '), StatColumnLength); var cellTest = new ConsoleBox.Cell("Test".PadLeft(StatColumnLength - 1, ' '), StatColumnLength); var cellErrors = new ConsoleBox.Cell("Errors".PadLeft(StatColumnLength - 1, ' '), StatColumnLength); var cellCrashes = new ConsoleBox.Cell("Crashes".PadLeft(StatColumnLength - 1, ' '), StatColumnLength); WriteList(server.Inputs.Values, ConsoleColor.Yellow, colorBottom, cellTitle, cellTest, cellErrors, cellCrashes); if (_showMutations) { WriteList(server.Configurations.Values, ConsoleColor.Yellow, colorBottom, cellConfigurations, cellTest, cellErrors, cellCrashes); } WriteList(server.Connections.Values.ToArray(), ConsoleColor.Yellow, colorBottom, cellConnections, cellCoverage, cellSpeed, cellTest, cellErrors, cellCrashes); // Write summary var l = (TitleColumnLength + (StatColumnLength * 3)) / 4; var lg = (TitleColumnLength + (StatColumnLength * 3)) - (l * 3); Console.ForegroundColor = colorBottom = ConsoleColor.Yellow; ConsoleBox.WriteCorner(CornerStyle.BoldTop, lg, l, l, l); if (server.UniqueErrors + server.TotalErrors > 0) { ConsoleBox.WriteContent(CornerStyle.BoldTop, "Unique", lg, BoxContentType.First); // Red color Console.ForegroundColor = server.UniqueErrors <= 0 ? colorBottom : ConsoleColor.Red; Console.Write(server.UniqueErrors.ToString().PadLeft(l - 1, ' ')); Console.ForegroundColor = colorBottom; Console.Write(CornerStyle.BoldTop.BoxChar.ToString()); ConsoleBox.WriteContent(CornerStyle.BoldTop, "Total", l, BoxContentType.Middle); Console.ForegroundColor = server.TotalErrors <= 0 ? colorBottom : ConsoleColor.Red; Console.Write(server.TotalErrors.ToString().PadLeft(l - 1, ' ')); Console.ForegroundColor = colorBottom; Console.WriteLine(CornerStyle.BoldTop.BoxChar.ToString()); } else { ConsoleBox.WriteContent(CornerStyle.BoldTop, "Unique", lg, BoxContentType.First); ConsoleBox.WriteContent(CornerStyle.BoldTop, server.UniqueErrors.ToString().PadLeft(l - 1, ' '), l, BoxContentType.Middle); ConsoleBox.WriteContent(CornerStyle.BoldTop, "Total", l, BoxContentType.Middle); ConsoleBox.WriteContent(CornerStyle.BoldTop, server.TotalErrors.ToString().PadLeft(l - 1, ' '), l, BoxContentType.Last); } ConsoleBox.WriteCorner(CornerStyle.BoldBot, lg, l, l, l); }