7

I'm using FiddlerCore to capture HTTP requests. Everything is working including SSL Captures as long as the Fiddler certificate is manually installed. I've been using manual installation through Fiddler's Options menu and that works fine.

However, if I use the FiddlerCore provided CertMaker class static methods to add the Fiddler certificate I find that I can use the certificate added to the cert root only in the current session. As soon as I shut down the application and start back up, CertMaker.rootCertExists() returns false.

I use the following code to install the certificate for the current user (from an explicit menu option at this point):

public static bool InstallCertificate()
{
    if (!CertMaker.rootCertExists())
    {
        if (!CertMaker.createRootCert())
            return false;

        if (!CertMaker.trustRootCert())
            return false;
    }

    return true;
}

The cert gets installed and I see it in the root cert store for the current user. If I capture SSL requests in the currently running application it works fine.

However, if I shut down the running exe, restart and call CertMaker.certRootExists() it returns false and if I try to capture SSL requests the SSL connection fails in the browser. If I recreate the cert and then re-run the requests in the browser while the app stays running it works again. I now end up with two certificates in the root store.

After exiting and relaunching certMaker.certRootExists() again returns false. Only way to get it to work is to register the cert - per exe session.

What am I doing wrong to cause the installation to not stick between execution of the same application?

Rick Strahl
  • 15,839
  • 13
  • 83
  • 121

2 Answers2

12

I was able to solve this problem and create persistent certificates that are usable across EXE sessions, by removing the default CertMaker.dll and BcMakeCert.dll assemblies that FiddlerCore installs and using and distributing the makecert.exe executable instead.

makecert.exe appears to create certificates in such a way that they are usable across multiple runs of the an application, where the included assemblies are valid only for the current application's running session.

Update:

If you want to use the CertMaker.dll and BcMakeCert.dll that FiddlerCore installs by default, you have to effectively cache and set the certificate and private key, using Fiddlers internal preferences object. There are a couple of keys that hold the certificate after it's been created and you need to capture these values, and write them into some sort of configuration storage.

In the following example I have a static configuration object that holds the certificate and key (persisted to a config file when the app shuts down):

public static bool InstallCertificate()
{
    if (!CertMaker.rootCertExists())           
    {
        if (!CertMaker.createRootCert())
            return false;

        if (!CertMaker.trustRootCert())
            return false;

        // persist Fiddlers certificate into app specific config
        App.Configuration.UrlCapture.Cert = 
           FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.cert", null);
        App.Configuration.UrlCapture.Key = 
           FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.key", null);
    }

    return true;
}

public static bool UninstallCertificate()
{
    if (CertMaker.rootCertExists())
    {
        if (!CertMaker.removeFiddlerGeneratedCerts(true))
            return false;
    }
    // persist Fiddlers certificate into app specific config
    App.Configuration.UrlCapture.Cert = null;
    App.Configuration.UrlCapture.Key = null;
    return true;
}

After installing a certificate this code captures the certificate and private key into the configuration object which persists that value later. For uninstallation, the values are cleared.

At the beginning of the application or the beginning of the capture process, prior to calling CertMaker.rootCertExists() the keys are set from the configuration values. I do this at the beginning of my capture form:

public FiddlerCapture()
{
    InitializeComponent();

    // read previously saved Fiddler certificate from app specific config
    if (!string.IsNullOrEmpty(App.Configuration.UrlCapture.Cert))
    {
        FiddlerApplication.Prefs.SetStringPref("fiddler.certmaker.bc.key", 
                                               App.Configuration.UrlCapture.Key);
        FiddlerApplication.Prefs.SetStringPref("fiddler.certmaker.bc.cert", 
                                               App.Configuration.UrlCapture.Cert);
    }
}

Using this mechanism for saving and then setting the capture settings makes the certificates persist across multiple EXE sessions when using CertMaker.dll.

More detailed info is available this detailed blog post on FiddlerCore.

Rick Strahl
  • 15,839
  • 13
  • 83
  • 121
  • thanks a lot for that solution. However, is it possible it doesn't work for firefox? When doing so, I need to install manually in firefox FiddlerRoot.cer. Is there a way to avoid this? – Cher Jan 22 '17 at 22:28
  • Is there a way to suppress the pop up dialog that shows to install cert – Frank Q. Apr 15 '17 at 01:40
0

If anyone is still interested, I found an easier solution based on the demo that Fiddler provides. This demo simply calls CertMaker.trustRootCert(), and strangely enough, it sticks! The first time it will ask whether you want to install the certificate, but after that, the function just returns true and will not cause the pop-up to show.

Unlike your and mine original program, the certificate sticks without having to go to the trouble of letting it stick yourself, so I analysed the differences with the demo. One of the differences I noticed was that the demo didn't have a reference to CertMaker.dll and BCMakeCert.dll. After removing these references from my own solution, I got the same behaviour as the demo.

Unfortunately, I don't have an explanation to why this works, but I hope this still helps some people.

Safron
  • 569
  • 7
  • 20
  • Can this be used for iOS as well? – Cosmin Feb 13 '18 at 21:52
  • @Cosmin I haven't tried it, but you can easily check. Try running the demo with and without a reference to CertMaker.dll and BCMakeCert.dll. In each case: (1) launch the application, (2) click "yes" when prompted to install the certificate, (3) close the application and (4) launch the application again to check whether the certificate sticks (if prompted again, it didn't stick). In my case on Windows, it sticks when both dll's are absent. – Safron Feb 13 '18 at 22:08