Skip to content

Commit

Permalink
Activating compatibility mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Marty committed Dec 20, 2018
1 parent b5417e4 commit 26c174e
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 9 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ The algorithm originates from Salesforce and the official Python and Bro impleme

This package includes a go library with an implementation of the algorithm and a command line tool which allows reading packets from pcap and pcapng files as well as from an interface.

As the Go implementation of [dreadl0ck](https://github.com/dreadl0ck) uses a deprecated and faulty TLS parser and does not comply with the JA3 algorithm regarding certain ciphers Open Systems AG decided to build its own implementation of the JA3 algorithm. Further we could increase the efficiency of the implementation.
As the Go implementation of [dreadl0ck](https://github.com/dreadl0ck) uses a deprecated and faulty TLS parser and does not comply with the JA3 algorithm regarding certain ciphers, Open Systems AG decided to build its own implementation of the JA3 algorithm. So we also had more control over the parsing and could make it more efficient.

## Usage

```
import "github.com/open-ch/ja3"
```
See the following example to get an idea of the exposed API. For more information look in the [godoc](https://godoc.org/github.com/open-ch/ja3).
See the following example to get an idea of the exposed API. For more information consult the [godoc](https://godoc.org/github.com/open-ch/ja3).

```
j, err := ja3.ComputeJA3FromSegment(tcpPayload)
Expand All @@ -33,14 +33,18 @@ ja3String := j.GetJA3ByteString()
anyWriterClass.Write(ja3String)
```

To use the CLI do the following on your preferred shell.
To check out the CLI, try the following on your preferred shell.
```
[host:]# go build ja3exporter.go engine.go
[host:]# ./ja3exporter -pcap="/path/to/file"
{"destination_ip":"172.217.168.67","destination_port":443,"ja3":"771,49200-49196-49199-49195-49172-49162-49171-49161-159-158-57-51-157-156-53-47-10-255,0-11-10-35-13-5-15-13172,23-25-28-27-24-26-22-14-13-11-12-9-10,0-1-2","ja3_digest":"5e647d60a56d199388ae462b75b3cdad","source_ip":"213.156.236.180","source_port":34577,"sni":"www.google.ch","timestamp":1537516825571014000}
```

**Attention: By default, the JA3Exporter only supports packets built up of an Ethernet Layer, followed by an IPv4 or IPv6 Layer, followed by a TCP Layer.**

If the package structure does not comply with this, use the -c flag for compatibility mode. Beware that this will make the JA3Exporter significantly slower.

## Tests and Benchmarks
As the TLS parser is custom built and highly optimized for the JA3 digest, a full coverage testing suite is put in place.
Our Go implementation is more than an order of magnitude faster than the python implementation.
Expand Down
9 changes: 7 additions & 2 deletions cli/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ func ReadFromInterface(device string) (Reader, error) {
}

// ComputeJA3FromReader reads from reader until an io.EOF error is encountered and writes verbose information about
// the found Client Hellos in the stream in JSON format to the writer.
// the found Client Hellos in the stream in JSON format to the writer. It only supports packets consisting of a pure
// ETH/IP/TCP stack but is very fast. If your packets have a different structure, use the CompatComputeJA3FromReader
// function.
func ComputeJA3FromReader(reader Reader, writer io.Writer) error {

// Build a selective parser which only decodes the needed layers
Expand Down Expand Up @@ -96,6 +98,9 @@ func ComputeJA3FromReader(reader Reader, writer io.Writer) error {
return nil
}

// CompatComputeJA3FromReader has the same functionality as ComputeJA3FromReader but supports any protocol that is
// supported by the gopacket library. It is much slower than the ComputeJA3FromReader function and therefore should not
// be used unless needed.
func CompatComputeJA3FromReader(reader Reader, writer io.Writer) error {
for {
// Read packet data
Expand Down Expand Up @@ -132,7 +137,7 @@ func CompatComputeJA3FromReader(reader Reader, writer io.Writer) error {

// writeJSON to writer
func writeJSON(dstIP string, dstPort int, srcIP string, srcPort int, timestamp int64, j *ja3.JA3, writer io.Writer) error {
// Use the same convention as in the official python implementation
// Use the same convention as in the official Python implementation
js, err := json.Marshal(struct {
DstIP string `json:"destination_ip"`
DstPort int `json:"destination_port"`
Expand Down
19 changes: 16 additions & 3 deletions cli/ja3exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func main() {
pcap := flag.String("pcap", "", "Path to pcap file to be read")
pcapng := flag.String("pcapng", "", "Path to pcapng file to be read")
device := flag.String("interface", "", "Name of interface to be read (e.g. eth0)")
compat := flag.Bool("c", false, "Activates compatibility mode (use this if packet does not consist of a pure ETH/IP/TCP stack)")
flag.Parse()

if *pcap != "" {
Expand All @@ -36,7 +37,11 @@ func main() {
}

// Compute JA3 digests and output to os.Stdout
err = ComputeJA3FromReader(r, os.Stdout)
if *compat {
err = ComputeJA3FromReader(r, os.Stdout)
} else {
err = CompatComputeJA3FromReader(r, os.Stdout)
}
if err != nil {
panic(err)
}
Expand All @@ -53,7 +58,11 @@ func main() {
}

// Compute JA3 digests and output to os.Stdout
err = ComputeJA3FromReader(r, os.Stdout)
if *compat {
err = ComputeJA3FromReader(r, os.Stdout)
} else {
err = CompatComputeJA3FromReader(r, os.Stdout)
}
if err != nil {
panic(err)
}
Expand All @@ -65,7 +74,11 @@ func main() {
}

// Compute JA3 digests and output to os.Stdout
err = ComputeJA3FromReader(r, os.Stdout)
if *compat {
err = ComputeJA3FromReader(r, os.Stdout)
} else {
err = CompatComputeJA3FromReader(r, os.Stdout)
}
if err != nil {
panic(err)
}
Expand Down
4 changes: 3 additions & 1 deletion doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
// tree.

/*
Package ja3 provides JA3 Client Fingerprinting for the Go language.
Package ja3 provides JA3 Client Fingerprinting for the Go language by looking at the
TLS Client Hello packets.
Basic Usage
ja3 takes in TCP payload data as a []byte and computes the corresponding JA3
string and digest.
Expand Down

0 comments on commit 26c174e

Please sign in to comment.