/// <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)); } } } }
/// <summary> /// RunOnce method executes the passed action once and writes the /// trace bits to the shared memory. This function will only work /// if the executable that is calling it is running under afl-fuzz. /// </summary> /// <param name="action"> /// Some action that calls the instrumented library. The stream /// argument passed to the action contains the input data. /// </param> public static unsafe void RunOnce(Action <Stream> action) { ThrowIfNull(action, nameof(action)); var s = Environment.GetEnvironmentVariable("__AFL_SHM_ID"); if (s is null || !Int32.TryParse(s, out var shmid)) { throw new Exception("This program can only be run under afl-fuzz."); } using (var stdin = Console.OpenStandardInput()) using (var stream = new UnclosableStreamWrapper(stdin)) using (var shmaddr = Native.shmat(shmid, IntPtr.Zero, 0)) { InitializeSharedMemory((byte *)shmaddr.DangerousGetHandle()); action(stream); } }
/// <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 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; } var ctl = Environment.GetEnvironmentVariable(ControlHandle); var st = Environment.GetEnvironmentVariable(StatusHandle); var pid = Environment.GetEnvironmentVariable(ParentId); var initial = Environment.GetEnvironmentVariable(InitialRun); if (ctl is null || st is null || pid is null || initial is null) { RunServer(); }