cert_extractor_logo

X.509 Certificate Extractor (TLS over TCP and DTLS)

Introduction

Release 4.0 introduces a new capability: the scanning of TCP and UDP streams for x.509 certificates. You can now either export these certificates to disk or dissect their attributes and output them as JSON objects and arrays. It checks for certificates in all the streams that start with a TLS Handshake content type, and for handshakes of type Certificate. For the TLS over UDP (DTLS) protocol, in case of handshake fragmentation, all fragments are reassembled before scanning for certificates. For the TCP protocol, the reassembly engine is invoked to reconstruct valid streams. The scanning process against the TCP and UDP protocols is port-independent.

Locating And Extracting

The process of locating X.509 certificates in a pcap is not as simple as scanning the entire pcap payload or a packet for specific certificate constants and extracting them. On the contrary, the identification of such a certificate follows a strict set of rules for the TCP and UDP protocols.

For the TCP protocol, and because of MTU limitations, with the possibility that a certificate might span more than one packet, TCP stream calculation becomes a necessity. And, working with TCP streams is not enough, because of packet retransmission, out-of-order packets, and other similar network behaviour. The latter necessitates the implementation of a TCP reassembly engine to handle such types of network behaviour, which is not an easy task.

Once you have all the essential building blocks implemented up to the network layer, working with reassembled TCP streams and searching for certificates is another subtle task. This requires searching in an optimized fashion, all streams that start with a TLS/SSL Handshake (0x16) content type, containing handshakes of type Certificate (0x0b). From this point on, we extract the Certificate record layer certificate header to extract all certificates.

For UDP and in case of handshake fragmentation, the TLS protocol uses fragments with sequence number, offset and length fields; consequently, those fragments have to be reassembled at the UDP stream level before scanning for certificates.

We implemented a custom ASN.1 DER certificate parser to handle the parsing and validation of the acquired certificates. This tool dissects all certificate attributes, including various extensions. The extracted data is then exported as a detailed, organized, and hierarchical JSON array for both TCP and UDP streams. The extractor is highly reliable, making it unlikely to produce false positives (treating an invalid certificate as valid) or false negatives (missing a valid certificate).

The TCP reassembly engine can be turned off and instead switch to payload concatenation of all packets in the stream. Based on our testing, the difference in performance for large pcaps is considerable. Moreover, even the stream’s directionality can be specified in the configuration file, up (c->s), down (s->c) or duplex (c< – >s).

To demonstrate the performance difference, take the following pcap capture20110810.pcap (fsize: 55.5 MB; sha-1: 5b822dc38f8b97f0b966bce4601cf73cb40afbd1) as an example. According to PacketSmith’s calculation, it consists of 15227 streams, with 12469 being TCP-IPv4 and 2758 being UDP-IPv4. A total of 129 X.509 certificates are located exclusively in the TCP-IPv4 streams.

With the TCP reassembly engine on, it takes about 7860_ms to dump all the certificates to a folder on disk, and around 5370_ms with the TCP reassembly engine off; A performance improvement of ~32%.

Case Study

The automated search, location, extraction, and subsequent dissection of X.509 certificates within packet captures is a fundamental requirement for creating fine-grained Intrusion Prevention/Detection System (IPS/IDS) rules. These policies leverage various certificate attributes, a methodology further explored in our research paper, The State of SSL/TLS Certificate Usage in Malware C&C Communications. This is why we add additional metadata to every dissected certificate in the JSON object, such as the entropy, fingerprints against the certificate payload and the public key, and field-level dissection of the subject and issuer attributes.

Let’s take the TLS over TCP traffic pcap (fsize: 2499 bytes) generated by Sliver (Adversary Emulation Framework) as an example. The pcap consists of one TCP stream over TLS v1.2, with 20 packets in total.

To extract all the certificates from the pcap, we execute the following PacketSmith cmd line option:

PacketSmith.exe -i sliver_tcp_tls.pcap —Xtract cert:dump —Outpath C:\Users\PS\Desktop\certs

Using the option —Xtract cert:dump, the above command will export all found certificates to the folder/Output path “C:\Users\PS\Desktop\certs”, under the filename with the format pattern:

<src_ip>_<src_port>_<dst_ip>_<dst_port>_<stream_type>_<rand_16bit>_<counter>.der

The metadata in the filename is specific to the stream id where the certificate is found. For example,

192.168.0.121_62811_194.190.152.81_443_tcp-ipv4_47499_0.der

And the output message you get from PacketSmith once the above command is successfully executed is the following:

- a total of 1 x.509 DER certificate was dumped to C:\Users\PS\Desktop\certs

– TCP-IPv4 -> 1
– TCP-IPv6 -> 0
– UDP-IPv4 -> 0
– UDP-IPv6 -> 0

To dump the JSON dissection of the certificate to the console, we use a similar command:

PacketSmith.exe -i sliver_tcp_tls.pcap —Xtract cert:json

Which outputs a JSON object similar to this:

sliver_tls_cert_.json
Copy to clipboard
[
    {
        "TCP-IPv4": {
            "streams_total": 1,
            "certs_total": 1,
            "streams": [
                {
                    "stream": {
                        "id": 0,
                        "src_ip": "192.168.0.121",
                        "src_port": "62811",
                        "dst_ip": "194.190.152.81",
                        "dst_port": "443",
                        "total_certs": 1
                    },
                    "certs": [
                        {
                            "id": 0,
                            "entropy": 7.292421981717005,
                            "size": 735,
                            "version": "v3",
                            "serial_number_length": 17,
                            "serial_number": "00:ea:5a:34:f3:08:af:67:f3:ef:1a:dd:fb:f3:2b:c9:12",
                            "signature_algorithm": "ecdsa-with-SHA512",
                            "subject": {
                                "common_name": "localhost",
                                "country": "CA",
                                "locality": "Fredericton",
                                "state": "New Brunswick",
                                "organization": "well, inc.",
                                "organizational_unit": "",
                                "street_address": "",
                                "email": ""
                            },
                            "issuer": {
                                "common_name": "",
                                "country": "",
                                "locality": "",
                                "state": "",
                                "organization": "",
                                "organizational_unit": "",
                                "street_address": "",
                                "email": ""
                            },
                            "not_before": "2023-02-23 08:20:02 UTC",
                            "not_after": "2026-02-22 08:20:02 UTC",
                            "signature_algorithm_outer": "ecdsa-with-SHA512",
                            "signature_value": "30:81:87:02:42:00:9a:fd:72:bc:70:24:6f:37:fc:71:25:6f:d4:d2:7a:ec:18:9a:cf:1a:59:0d:d2:d2:bd:71:06:e0:8b:c3:aa:40:2e:f6:5c:f5:50:38:6a:60:82:97:dc:fe:11:00:25:2d:dd:b7:22:2e:8b:5e:ba:5c:59:13:84:35:19:2d:18:d5:f8:02:41:54:26:a9:35:db:8d:35:59:1f:87:bc:ba:b8:2a:0c:92:38:0b:7d:91:98:e9:4a:ef:35:e0:6f:90:b6:fe:0a:29:06:08:2e:ff:d8:d6:51:31:11:7a:33:44:59:00:80:50:cb:b8:d4:ec:25:cd:d2:d1:ed:fc:89:4c:36:6a:78:0b:0f",
                            "public_key": {
                                "algorithm": "rsaEncryption",
                                "size": 271,
                                "key": "00:30:82:01:0a:02:82:01:01:00:a9:2a:5f:c8:32:c5:8e:da:b7:5e:3b:fb:ef:4a:16:e4:0a:41:a3:ef:03:7f:0b:ab:a6:3e:ac:bb:c0:f6:e5:ac:91:c1:7d:11:13:37:40:f3:57:c0:6f:7a:9a:e8:15:ac:9d:1f:d3:6d:90:e3:61:fe:0b:0b:2c:d1:b5:99:2f:e1:6e:78:fc:dc:42:a3:a9:68:2b:8c:88:bf:af:13:bc:ac:c4:3d:fe:ef:99:2e:4e:30:ed:2c:90:23:90:cd:65:ef:bf:ec:e8:4f:7b:a6:b3:68:5b:66:21:bb:94:1e:fa:26:c4:b2:51:be:11:fb:2f:79:f9:c2:3d:ba:0e:b7:97:a5:53:b3:1d:f7:ea:e8:73:98:3d:99:3d:1f:0e:4a:f9:ff:70:52:4e:4c:e2:55:87:e8:ac:39:33:79:f5:bb:cb:8c:fd:8f:8e:a7:ce:c9:18:ec:87:cc:72:21:81:34:99:6a:c6:81:c1:ba:5d:de:fa:18:3b:2c:c7:96:b9:e3:7c:f7:1b:4c:58:5c:6a:fe:ce:5b:e6:f4:ba:2f:03:b6:2c:31:59:3a:9b:f5:57:9a:b8:8f:8a:01:e1:3c:ce:e1:82:2c:d7:ab:f4:41:17:95:d7:48:1e:bf:fa:63:8a:47:14:44:01:db:c9:75:91:28:39:ff:58:2b:54:da:20:57:c7:f1:02:03:01:00:01"
                            },
                            "extensions": [
                                {
                                    "name": "Key Usage",
                                    "value": "Digital Signature, Key Encipherment"
                                },
                                {
                                    "name": "Extended Key Usage",
                                    "value": "TLS Web Server Authentication"
                                },
                                {
                                    "name": "Authority Key Identifier",
                                    "value": "keyid: 45:a5:ce:12:4b:89:2a:19:64:05:2e:5a:e6:9b:ce:8e:0e:7f:16:ba"
                                },
                                {
                                    "name": "Subject Alternative Name",
                                    "value": "DNS: localhost"
                                }
                            ],
                            "fingerprints": {
                                "cert": {
                                    "sha-1": "a32a48b1ed439b5d6c1e1a7d12177712d34e84bc",
                                    "sha-256": "64c0520fd7d4ce99a71e8bee0b8e7ea29505b4a516ba3e47c889830fd78c7201",
                                    "md5": "aa561e210d10a61ebb7116acc20a14de"
                                },
                                "public_key": {
                                    "sha-1": "96dec0d1b961ca074fbea2237c500f0198da65e3",
                                    "sha-256": "40fd66232439f0309276be0dbdc8a91b551a1054b464352259c446dd1238d87f",
                                    "md5": "eb13c160c7d3bb48e860a6dd7a3fe7d3"
                                }
                            }
                        }
                    ]
                }
            ]
        }
    }
]

To perform the actions of both cert:dump and cert:json simultaneously, you use the option cert:dump__json.

Developing an IDS/IPS detection logic for the dissected JSON attributes isn’t a simple copy-and-paste task. Sliver evades static, one-shot string matching by dynamically generating certificate fields, particularly in the Subject area (as seen in sliver/server/certs/subject.go). However, we can achieve high-confidence detection by analyzing the source code to account for all potential attribute values.

The following recording provides a practical demonstration of PacketSmith v4.0’s functionality in processing a variant of Sliver’s TCP SSL traffic. This includes the capability to extract and persist the X.509 certificate to disk, along with generating a structured JSON dissection of its fields.

Conclusion

We have detailed PacketSmith’s mechanism for identifying and extracting X.509 certificates transmitted by servers within both TLS-over-TCP and DTLS streams. To validate this feature, we utilized a packet capture from the Sliver adversary emulation framework, successfully retrieving the C&C server’s self-signed certificate and providing a comprehensive, dissected JSON representation of its attributes.


Author: Mohamad Mokbel (Netomize)

First release: November 17, 2025