Beispiel #1
0
            /// <summary>
            /// Run method starts the libFuzzer runner. It repeatedly executes
            /// the passed action and reports the execution result to libFuzzer.
            /// If the executable that is calling it is not running under libFuzzer,
            /// the action will be executed normally, and will receive its input
            /// from the file specified in the first command line parameter.
            /// </summary>
            /// <param name="action">
            /// Some action that calls the instrumented library. The span argument
            /// passed to the action contains the input data. If an uncaught
            /// exception escapes the call, crash is reported to libFuzzer.
            /// </param>
            public static unsafe void Run(ReadOnlySpanAction action)
            {
                ThrowIfNull(action, nameof(action));

                try
                {
                    using (var ipc = new FuzzerIpc())
                    {
                        var sharedMem = ipc.InputPointer();
                        var trace     = new TraceWrapper(sharedMem);

                        ipc.SetStatus(0);

                        try
                        {
                            var status = Fault.None;

                            // The program instrumented with libFuzzer will exit
                            // after the first error, so we should do the same.
                            while (status != Fault.Crash)
                            {
                                trace.ResetPrevLocation();

                                var size = ipc.InputSize();
                                var data = new ReadOnlySpan <byte>(sharedMem + MapSize, size);

                                try
                                {
                                    action(data);
                                }
                                catch (Exception ex)
                                {
                                    Console.Error.WriteLine(ex);
                                    status = Fault.Crash;
                                }

                                ipc.SetStatus(status);
                            }
                        }
                        catch
                        {
                            // Error communicating with the parent process, most likely
                            // because it was terminated after the timeout expired, or
                            // it was killed by the user. In any case, the exception
                            // details don't matter here, so we can just exit silently.
                            return;
                        }
                    }
                }
                catch (FuzzerIpcEnvironmentException)
                {
                    // Error establishing IPC with the parent process due to missing or
                    // definitely-invalid environment variables. This may be intentional.
                    // Instead of persistent fuzzing, fall back on testing a single input.
                    RunWithoutLibFuzzer(action);
                    return;
                }
            }
Beispiel #2
0
            /// <summary>
            /// Run method starts the libFuzzer runner. It repeatedly executes
            /// the passed action and reports the execution result to libFuzzer.
            /// If the executable that is calling it is not running under libFuzzer,
            /// the action will be executed normally, and will receive its input
            /// from the file specified in the first command line parameter.
            /// </summary>
            /// <param name="action">
            /// Some action that calls the instrumented library. The span argument
            /// passed to the action contains the input data. If an uncaught
            /// exception escapes the call, crash is reported to libFuzzer.
            /// </param>
            public static unsafe void Run(ReadOnlySpanAction action)
            {
                ThrowIfNull(action, nameof(action));
                var s = Environment.GetEnvironmentVariable("__LIBFUZZER_SHM_ID");

                if (s is null || !Int32.TryParse(s, out var shmid))
                {
                    RunWithoutLibFuzzer(action);
                    return;
                }

                using (var shmaddr = Native.shmat(shmid, IntPtr.Zero, 0))
                    using (var r = new BinaryReader(new AnonymousPipeClientStream(PipeDirection.In, "198")))
                        using (var w = new BinaryWriter(new AnonymousPipeClientStream(PipeDirection.Out, "199")))
                        {
                            var sharedMem = (byte *)shmaddr.DangerousGetHandle();
                            var trace     = new TraceWrapper(sharedMem);

                            w.Write(0);

                            try
                            {
                                var status = Fault.None;

                                // The program instrumented with libFuzzer will exit
                                // after the first error, so we should do the same.
                                while (status != Fault.Crash)
                                {
                                    trace.ResetPrevLocation();

                                    var size = r.ReadInt32();
                                    var data = new ReadOnlySpan <byte>(sharedMem + MapSize, size);

                                    try
                                    {
                                        action(data);
                                    }
                                    catch (Exception ex)
                                    {
                                        Console.Error.WriteLine(ex);
                                        status = Fault.Crash;
                                    }

                                    w.Write(status);
                                }
                            }
                            catch
                            {
                                // Error communicating with the parent process, most likely
                                // because it was terminated after the timeout expired, or
                                // it was killed by the user. In any case, the exception
                                // details don't matter here, so we can just exit silently.
                                return;
                            }
                        }
            }
Beispiel #3
0
        /// <summary>
        /// Run method starts the .NET equivalent of AFL fork server.
        /// It repeatedly executes the passed action and reports the
        /// execution result to afl-fuzz. If the executable that is
        /// calling it is not running under afl-fuzz, the action will
        /// be executed only once.
        /// </summary>
        /// <param name="action">
        /// Some action that calls the instrumented library. The stream
        /// argument passed to the action contains the input data. If an
        /// uncaught exception escapes the call, FAULT_CRASH execution
        /// status code is reported to afl-fuzz.
        /// </param>
        public static unsafe void Run(Action <Stream> action)
        {
            ThrowIfNull(action, nameof(action));
            var s = Environment.GetEnvironmentVariable("__AFL_SHM_ID");

            using (var stdin = Console.OpenStandardInput())
                using (var stream = new UnclosableStreamWrapper(stdin))
                {
                    if (s is null || !Int32.TryParse(s, out var shmid))
                    {
                        RunWithoutAflFuzz(action, stream);
                        return;
                    }

                    using (var shmaddr = Native.shmat(shmid, IntPtr.Zero, 0))
                        using (var r = new BinaryReader(new AnonymousPipeClientStream(PipeDirection.In, "198")))
                            using (var w = new BinaryWriter(new AnonymousPipeClientStream(PipeDirection.Out, "199")))
                            {
                                var sharedMem = (byte *)shmaddr.DangerousGetHandle();
                                var trace     = new TraceWrapper(sharedMem);

                                w.Write(0);
                                var pid = Process.GetCurrentProcess().Id;

                                using (var memory = new UnclosableStreamWrapper(new MemoryStream()))
                                {
                                    // In the first run, we have to consume the input stream twice:
                                    // first time to run the Setup function, second time to actually
                                    // report the results. That's why we have to use the MemoryStream
                                    // in order to be able to seek back to the beginning of the input.
                                    stream.CopyTo(memory);
                                    memory.Seek(0, SeekOrigin.Begin);

                                    Setup(action, memory, sharedMem);
                                    memory.Seek(0, SeekOrigin.Begin);

                                    r.ReadInt32();
                                    w.Write(pid);

                                    trace.ResetPrevLocation();
                                    w.Write(Execute(action, memory));
                                }

                                while (true)
                                {
                                    r.ReadInt32();
                                    w.Write(pid);

                                    trace.ResetPrevLocation();
                                    w.Write(Execute(action, stream));
                                }
                            }
                }
        }
Beispiel #4
0
            /// <summary>
            /// Run method starts the .NET equivalent of SFZ fuzzer main loop.
            /// </summary>
            /// <param name="action">
            /// Some action that calls the instrumented library. The stream
            /// argument passed to the action contains the serialized input data.
            /// </param>
            public static unsafe void RunSfz(string[] args, Action <byte[]> action)
            {
                Console.WriteLine("Starting Sfz Main");

                int[] fileDescriptors = ReadFileDescriptors(args);
                int   fdIn            = fileDescriptors[0];
                int   fdOut           = fileDescriptors[1];

                Console.Write("GO_FUZZ_IN_FD: " + fdIn);
                Console.WriteLine(" GO_FUZZ_OUT_FD: " + fdOut);

                string[] commName = ReadSharedMemoryNames(args);

                using (SafeFileHandle inPipeHandle = new SafeFileHandle(new IntPtr(fdIn), true),
                       outPipeHandle = new SafeFileHandle(new IntPtr(fdOut), true))
                {
                    // Use the filehandles
                    Stream inStream  = new FileStream(inPipeHandle, FileAccess.Read);
                    Stream outStream = new FileStream(outPipeHandle, FileAccess.Write);
                    Console.WriteLine("created inStream and outStream");

                    //MemoryMappedFileSecurity security = new MemoryMappedFileSecurity();
                    //security.AddAccessRule(new AccessRule<MemoryMappedFileRights>(("Everyone"),
                    //    MemoryMappedFileRights.FullControl, AccessControlType.Allow));
                    //Console.WriteLine("created security");

                    using (
                        MemoryMappedFile comm0 = MemoryMappedFile.OpenExisting(commName[0],
                                                                               MemoryMappedFileRights.ReadWrite, HandleInheritability.Inheritable),
                        comm1 = MemoryMappedFile.OpenExisting(commName[1], MemoryMappedFileRights.ReadWrite,
                                                              HandleInheritability.Inheritable),
                        comm2 = MemoryMappedFile.OpenExisting(commName[2], MemoryMappedFileRights.ReadWrite,
                                                              HandleInheritability.Inheritable),
                        comm3 = MemoryMappedFile.OpenExisting(commName[3], MemoryMappedFileRights.ReadWrite,
                                                              HandleInheritability.Inheritable))
                    {
                        const int MaxInputSize     = 1 << 24;
                        const int ReturnResultSize = 1 << 25;
                        const int CoverSize        = 64 << 10;
                        const int SonarRegionSize  = 1 << 20;

                        var cover = new byte[CoverSize];
                        fixed(byte *coverPtr = cover)
                        {
                            var trace = new TraceWrapper(coverPtr);

                            Console.WriteLine("created commX objects");

                            var comm0Accessor = comm0.CreateViewAccessor(0, MaxInputSize);
                            var comm1Accessor = comm1.CreateViewAccessor(0, ReturnResultSize);
                            var comm2Accessor = comm2.CreateViewAccessor(0, CoverSize);
                            var comm3Accessor = comm3.CreateViewAccessor(0, SonarRegionSize);

                            Console.WriteLine("created commX accessors");

                            while (true)
                            {
                                int  fnidx       = 0;
                                long inputLength = 0;
                                (fnidx, inputLength) = ReadIndexAndLength(inStream);

                                // read inputBuffer data from comm0
                                var inputBuffer = new byte[inputLength];
                                comm0Accessor.ReadArray(0, inputBuffer, 0, (int)inputLength);
                                for (int i = 0; i < inputLength; i++)
                                {
                                    inputBuffer[i] = comm0Accessor.ReadByte(i);
                                }

                                var inputString = Encoding.UTF8.GetString(inputBuffer);
                                Console.WriteLine("downstream: " + Encoding.UTF8.GetString(inputBuffer));
                                var downstream = new Downstream();
                                try
                                {
                                    downstream = JsonSerializer.Deserialize <Downstream>(inputString);
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine("downstream deserialization exception: " + ex.Message);
                                }

                                //var downstream = FlatBufferSerializer.Default.Parse<Downstream>(inputBuffer);
                                Console.WriteLine("downstream deserialized");

                                Upstream upstream = NewUpstreamObj();

                                long res   = 0;
                                long ns    = 0;
                                long sonar = 0;

                                var seed = downstream.Seed;
                                if (seed != null && seed.Data != null && seed.Data.Length >= 1)
                                {
                                    ConfigEntry entry = seed.Data[0];
                                    var         value = entry.Value;

                                    if (entry.Value != null)
                                    {
                                        Console.WriteLine("got entry value: " + value);

                                        // Start the clock
                                        var nsStart = DateTime.UtcNow.Ticks;

                                        try
                                        {
                                            // Actually run the function to fuzz
                                            byte[] buffer = Encoding.UTF8.GetBytes(value);
                                            action(buffer);
                                            Console.Write("exec fuzz method");
                                        }
                                        catch (Exception exception)
                                        {
                                            ns = DateTime.UtcNow.Ticks - nsStart;
                                            Console.WriteLine("ns: " + ns);

                                            upstream.Crashed       = true;
                                            upstream.HasFailed     = true;
                                            upstream.ResultMessage = exception.ToString();
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("null entry value!");
                                        var nsStart = DateTime.UtcNow.Ticks;
                                        try
                                        {
                                            // Actually run the function to fuzz
                                            byte[] buffer = Encoding.UTF8.GetBytes("<html><body><h1>h1</h1><p>p</p></body></html>");
                                            action(buffer);
                                            Console.Write("exec fuzz method");
                                        }
                                        catch (Exception exception)
                                        {
                                            ns = DateTime.UtcNow.Ticks - nsStart;
                                            Console.WriteLine("ns: " + ns);

                                            upstream.Crashed       = true;
                                            upstream.HasFailed     = true;
                                            upstream.ResultMessage = exception.ToString();
                                        }
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("zero entries!");
                                    var nsStart = DateTime.UtcNow.Ticks;
                                    try
                                    {
                                        // Actually run the function to fuzz
                                        byte[] buffer = Encoding.UTF8.GetBytes("<html><body><h1>h1</h1><p>p</p></body></html>");
                                        action(buffer);
                                        Console.Write("exec fuzz method");
                                    }
                                    catch (Exception exception)
                                    {
                                        ns = DateTime.UtcNow.Ticks - nsStart;
                                        Console.WriteLine("ns: " + ns);

                                        upstream.Crashed       = true;
                                        upstream.HasFailed     = true;
                                        upstream.ResultMessage = exception.ToString();
                                    }
                                }

                                for (int i = 0; i < cover.Length; i++)
                                {
                                    if (cover[i] != 0)
                                    {
                                        Console.WriteLine("nonzero cover!");
                                    }
                                }

                                // copy cover to shared memory
                                for (int i = 0; i < cover.Length; i++)
                                {
                                    comm2Accessor.Write(i, cover[i]);
                                }
                                comm2Accessor.Flush();

                                ReturnResult(comm1Accessor, outStream, res, ns, sonar, upstream);
                            }
                        }
                    }
                }
            }