Firstly, you could generate self-signed certificate (with CA basic constraints) for your application (you could have your application generate it automatically) and import that certificate into your browser as a trusted CA.
Then, you could generate a new certificate on the fly depending on the requested host name, issued by your CA (i.e. signed using its private key and with the CA's Subject DN as the new certificate's Issuer DN). There are details about generating certificates in C# in this question: Is it possible to programmatically generate an X509 certificate using only C#?
This certificate must follow the specifications of the HTTP over TLS specification:
If a subjectAltName extension of type dNSName is present, that MUST
be used as the identity. Otherwise, the (most specific) Common Name
field in the Subject field of the certificate MUST be used. Although
the use of the Common Name is existing practice, it is deprecated and
Certification Authorities are encouraged to use the dNSName instead.
[...]
In some cases, the URI is specified as an IP address rather than a
hostname. In this case, the iPAddress subjectAltName must be present
in the certificate and must exactly match the IP in the URI.
In short, if what's requested is just a host name, you should be fine with simply a CN=hostname
RDN in the Subject DN (although a Subject Alt Name would be better), but if it's an IP address, you should put an IP addr Subject Alternative Name entry (although some browsers will let you get away with the IP address in the CN RDN in practice).
If you want a proxy that captures the TCP packets, without server name indication, you may actually find it very hard to find which actual host name is requested. I would suggest doing a reverse DNS lookup for the IP address (which you should be able to find) and putting a DNS Subject Alt Name entry for each reverse DNS entry, as well as an IP Subject Alt Name entry for the IP address. This should cover most cases, except those where the client uses a host name for which the IP address doesn't have a reverse DNS entry. Failing that, you'll just have to add the exception by hand in your browser (which is fine since you'll know that you're intercepting your own communication) or set it up by hand within your proxy.
Finding the host name is easier with an HTTP proxy configured in the browser, since you don't need to guess the host name, it will be passed to the CONNECT
HTTP verb.
(Of course, to begin with, for a specific host, you can generate the certificate with makecert
rather than doing it on the fly.)