Version 2.2.9.9 of the FiddlerCore .NET class library has been released. This new version includes a number of new features that make FiddlerCore more useful for a variety of traffic monitoring and capture scenarios. With the exception of the final improvement (Server Read Callback), all of these improvements are also available to extensions running inside the full Fiddler application.

Server Certificate Validation

FiddlerCore hosters will now have the opportunity to accept or reject the server-provided certificate when a HTTPS connection is made and traffic decryption is enabled. This enables a number of new scenarios:

  • Collection and storage of server-provided certificates
    • e.g. analyze how many certificate chains are signed with MD5
  • Acceptance of certificates based on any criteria
    • e.g. treat my development certificate as valid for every site
  • Rejection of certificates based on any criteria
    • e.g. do not accept certificates from government CAs

You can attach an event handler for certificate validation thusly:

FiddlerApplication.OverrideServerCertificateValidation += 
 new OverrideCertificatePolicyHandler(FiddlerApplication_OverrideServerCertificateValidation);

And implement it like so:

/// <summary>
/// This callback allows your code to evaluate the certificate for a site and optionally override default validation behavior for that certificate.
/// You should not implement this method unless you understand why it is a security risk.
/// </summary>
/// <param name="sExpectedCN">The CN expected for this session</param>
/// <param name="ServerCertificate">The certificate provided by the server</param>
/// <param name="ServerCertificateChain">The certificate chain of that certificate</param>
/// <param name="sslPolicyErrors">Errors from default validation</param>
/// <param name="bTreatCertificateAsValid">TRUE if you want to force the certificate to be valid; FALSE if you want to force the certificate to be invalid</param>
/// <returns>TRUE if you want to override default validation; FALSE if bTreatCertificateAsValid should be ignored</returns>
static bool FiddlerApplication_OverrideServerCertificateValidation(string sExpectedCN, X509Certificate ServerCertificate, X509Chain ServerCertificateChain, 
 SslPolicyErrors sslPolicyErrors, out bool bTreatCertificateAsValid)
{
 if (null != ServerCertificate)
 {
 Console.WriteLine("Certificate for " + sExpectedCN + " was for site " + ServerCertificate.Subject + " and errors were " + sslPolicyErrors.ToString());
 
 if (ServerCertificate.Subject.Contains("fiddler2.com"))
 {
 Console.WriteLine("Got a certificate for fiddler2.com and we'll say this is also good for, say, fiddlertool.com");
 bTreatCertificateAsValid = true;
 return true;
 }
 }
 
 bTreatCertificateAsValid = false;
 return false;
}

If you do not implement this method, or you return false, unless Fiddler.CONFIG.IgnoreServerCertErrors is set to true standard certificate validation rules will be respected.

Update: This event was not designed correctly and has been changed in Fiddler/FiddlerCore 2.3.6.3 and above. The event has been renamed to OnValidateServerCertificate which is passed a ValidateServerCertificateEventArgs object. An extension may set the ValidityState property of this object to any of the CertificateValidity constants.

Prevent Storage of Streaming Traffic

A common scenario for FiddlerCore-based applications is to act as a traffic monitor only, looking only at the request and response headers. The log-drop-request-body and log-drop-response-body flags can be set on a session to ensure that the request and response body are discarded once the request is sent and the response is returned,  but these flags only take effect when the response is completed. In the case of streaming data (e.g. an unending Internet radio feed) the hosting application’s memory usage will continue to grow unbounded because the response is never completed.

If a response is streamed (e.g. oSession.bBufferResponse == false) and the log-drop-response-body flag is set, FiddlerCore will discard traffic as it streamed to the client. Alternatively, you can use the following code:

FiddlerApplication.Prefs.SetBoolPref(
    "fiddler.network.streaming.ForgetStreamedData", true
);

…to set the have FiddlerCore discard streamed response data in all sessions, even without the log-drop-response-body flag.

Of course, if your application is not storing response data for examination, you typically should also set the preference:

FiddlerApplication.Prefs.SetBoolPref(
    "fiddler.network.streaming.abortifclientaborts", true
);

…to ensure that FiddlerCore will stop reading from the server if the client closes the connection to the FiddlerCore proxy during streaming.

OnReadResponseBuffer Callback

In very rare cases, it may be useful for an application to receive notice as each block of traffic is downloaded from the server. This raw data buffer is nearly useless for most applications because it provides none of the  parsing conveniences available elsewhere in the Fiddler API.  HTTP response headers and the response body are not delineated, and compressed/chunked traffic are not decoded or unchunked. However, for certain uses (e.g. counting the raw number of bytes received while streaming) this capability may be useful.

Register for this callback like so:

Fiddler.FiddlerApplication.OnReadResponseBuffer += 
    new EventHandler<RawReadEventArgs>(FiddlerApplication_OnReadResponseBuffer);

You can view or modify the bytes received like so:

// This event handler is called on every socket read for the HTTP Response. You almost certainly don't want
// to do this, but the code below shows how you can use it to mess up your HTTP traffic.
static void FiddlerApplication_OnReadResponseBuffer(object sender, RawReadEventArgs e)
{
    // NOTE: arrDataBuffer is a fixed-size array. Only bytes (0 to iCountOfBytes) should be read/manipulated.
    //
    // Just for kicks, lowercase every byte. Note that this will obviously break any binary content.
    for (int i = 0; i < e.iCountOfBytes; i++)
    {
        if ((e.arrDataBuffer[i] > 0x40) && (e.arrDataBuffer[i] < 0x5b))
        {
            e.arrDataBuffer[i] = (byte)(e.arrDataBuffer[i] + (byte)0x20);
        }
    }
    Console.WriteLine(String.Format("Read {0} response bytes for session {1}", e.iCountOfBytes, e.sessionOwner.id));
}

The RawEventArgs parameter contains four members:  arrDataBuffer, iCountOfBytes, sessionOwner, and AbortReading. arrDataBuffer is a fixed-size byte array. iCountOfBytes is an integer indicating how many bytes of the arrDataBuffer array have been set by the read from the server. sessionOwner is a reference to the session for which the response is being read. The AbortReading member is a boolean which can be set to request that the read from the server be terminated as soon as possible.

Import/Export Architecture

Fiddler 2.2.9.7 introduced a new Import/Export Architecture to simplify the transcoding of Web traffic to and from multiple formats. FiddlerCore now supports this architecture, and provides default implementations for the Sesssion Archive Zip format.

You can direct FiddlerCore to load additional ISessionImport and ISessionExport classes from either your application’s assembly, or from the assembly of your choice. For instance, the following code will load the transcoders from Formats.dll in your application’s directory.

FiddlerApplication.oTranscoders.ImportTranscoders(
        Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + 
            @"Formats.dll"
);

It is important to note that FiddlerCore’s ISessionImport and ISessionExport interfaces are source-compatible with those in the Fiddler application, but they are not binary-compatible. If you want to share transcoders between a FiddlerCore application and Fiddler itself, you will have to compile your code into two individual assemblies, one Referencing Fiddler.exe and one Referencing FiddlerCore.dll.

The FiddlerCore package includes two source files, SAZ-DotNETZip.cs and SAZ-XCEEDZip.cs either of which will allow FiddlerCore-based applications to load and save SAZ-formatted archives. The former class requires the open-source DotNETZip library while the latter is based on the commercial XCeed Zip library

To import sessions from a file in SAZ format, you can write code like so:

private static void ImportSessions(List<Fiddler.Session> oAllSessions)
{
   TranscoderTuple oImporter = FiddlerApplication.oTranscoders.GetImporter("SAZ");
   if (null != oImporter)
   {
       Dictionary<string, object> dictOptions = new Dictionary<string, object>();
       dictOptions.Add("Filename", Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\ToLoad.saz");
 
       Session[] oLoaded = FiddlerApplication.DoImport("SAZ", false, dictOptions, null);
 
       if ((oLoaded != null) && (oLoaded.Length > 0))
       {
           oAllSessions.AddRange(oLoaded);
           Console.WriteLine("Loaded: " + oLoaded.Length + " sessions.");
       }
   }
}

To export a set of sessions to a file, you can write code like so:

private static void SaveSessionsToDesktop(List<Fiddler.Session> oAllSessions)
{
    bool bSuccess = false;
    string sFilename = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
                  + @"\" + DateTime.Now.ToString("hh-mm-ss") + ".saz";SAZ");Filename", sFilename);Password", "pencil");SAZ", oAllSessions.ToArray(), dictOptions, null);Wrote: " + sFilename) : ("Failed to save: " + sFilename) );Save failed: " + eX.Message);
    try
    {
      try
      {
          Monitor.Enter(oAllSessions);
          TranscoderTuple oExporter = FiddlerApplication.oTranscoders.GetExporter("
    
          if (null != oExporter)
          {
              Dictionary<string, object> dictOptions = new Dictionary<string, object>();
              dictOptions.Add("
              dictOptions.Add("
    
              bSuccess = FiddlerApplication.DoExport("
          }
      }
      finally
      {
          Monitor.Exit(oAllSessions);
      }
    
      Console.WriteLine( bSuccess ? ("
    }
    catch (Exception eX)
    {
      Console.WriteLine("
    }
}

If desired, you may download and redistribute a FiddlerCore-compatible version of the BasicFormats assembly (supporting Import/Export of HTTP Archive JSON and HTTP Archive XML, and Export of Visual Studio Web Test XML, WCAT Load Test Scripts, and Raw Files).

I hope you find these new capabilities useful in building your applications. Please let me know if you encounter any problems!

 

-Eric Lawrence