Skip to content

Commit 9501015

Browse files
author
shadowy-pycoder
committed
Added basic parsing for TLS messages
1 parent 4e2b740 commit 9501015

File tree

6 files changed

+211
-12
lines changed

6 files changed

+211
-12
lines changed

Makefile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
APP_NAME?=mshark
1+
APP_NAME=mshark
22

33
all: build
44

5+
.PHONY: build
56
build:
67
CGO_ENABLED=0 go build -ldflags "-s -w" -trimpath -o ./bin/${APP_NAME} ./cmd/${APP_NAME}/*.go
78

9+
.PHONY: setcap
810
setcap:
911
sudo setcap cap_net_raw+ep ./bin/${APP_NAME}
1012

13+
.PHONY: create
1114
create:
1215
go test -c -race && sudo setcap cap_net_raw+ep mshark.test
1316

17+
.PHONY: bench
1418
bench: create
1519
./mshark.test -test.bench=. -test.benchmem -test.run=^$$ -test.benchtime 1000x \
1620
-test.cpuprofile='cpu.prof' -test.memprofile='mem.prof'
1721

18-
clear:
22+
.PHONY: clean
23+
clean:
1924
rm -v *.txt *.pcap*

layers/dns.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ func (d *DNSMessage) String() string {
200200
d.ANCount,
201201
d.NSCount,
202202
d.ARCount,
203-
d.rrecords(),
203+
d.printRecords(),
204204
)
205205
}
206206

@@ -272,7 +272,7 @@ func (d *DNSMessage) NextLayer() (string, []byte) {
272272
return "", nil
273273
}
274274

275-
func (d *DNSMessage) rrecords() string {
275+
func (d *DNSMessage) printRecords() string {
276276
var sb strings.Builder
277277
if d.QDCount > 0 {
278278
sb.WriteString("- Queries:\n")

layers/http.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func (h *HTTPMessage) Summary() string {
2222
}
2323

2424
func (h *HTTPMessage) ellipsify() {
25-
h.summary = ellipsis
25+
h.summary = contdata
2626
h.data = ellipsis
2727
}
2828

layers/layers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ var (
3131
dcrlf = []byte("\r\n\r\n")
3232
proto = []byte("HTTP/1.1")
3333
ellipsis = []byte("...")
34+
contdata = []byte("Continuation data")
3435
)
3536

3637
type Layer interface {

layers/tls.go

Lines changed: 199 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,214 @@
11
package layers
22

3-
import "fmt"
3+
import (
4+
"encoding/binary"
5+
"fmt"
6+
"strings"
7+
)
8+
9+
type Record struct {
10+
ContentType uint8
11+
ContentTypeDesc string
12+
Version uint16
13+
VersionDesc string
14+
Length uint16
15+
data []byte
16+
}
17+
18+
func (r *Record) String() string {
19+
return fmt.Sprintf(` - Content Type: %s (%d)
20+
- Version: %s (%#04x)
21+
- Length: %d`,
22+
r.ContentTypeDesc,
23+
r.ContentType,
24+
r.VersionDesc,
25+
r.Version,
26+
r.Length)
27+
}
428

529
// port 443
6-
type TLSMessage struct{}
30+
// https://tls12.xargs.org/#client-hello/annotated
31+
// https://tls13.xargs.org/#client-hello/annotated
32+
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-5
33+
type TLSMessage struct {
34+
Records []*Record
35+
Data []byte
36+
}
37+
38+
func (t *TLSMessage) String() string {
39+
return fmt.Sprintf(`%s
40+
%s- Data: %d bytes
41+
`, t.Summary(), t.printRecords(), len(t.Data))
42+
}
743

8-
func (s *TLSMessage) String() string {
9-
return fmt.Sprintf(`%s`, s.Summary())
44+
func (t *TLSMessage) Summary() string {
45+
var sb strings.Builder
46+
sb.WriteString("TLS Message: ")
47+
if len(t.Records) == 0 {
48+
sb.WriteString(fmt.Sprintf("Ignored unknown record Len: %d", len(t.Data)))
49+
} else {
50+
for i, rec := range t.Records {
51+
if sb.Len() > 100 {
52+
return sb.String()[:100] + string(ellipsis)
53+
}
54+
if i > 0 {
55+
sb.WriteString(fmt.Sprintf("%s (%d) Len: %d ", rec.ContentTypeDesc, rec.ContentType, rec.Length))
56+
continue
57+
}
58+
sb.WriteString(fmt.Sprintf("%s (%#04x) ", rec.VersionDesc, rec.Version))
59+
if rec.ContentType == 22 {
60+
hstd := hstypedesc(rec.data[0])
61+
sb.WriteString(fmt.Sprintf("%s ", hstd))
62+
}
63+
sb.WriteString(fmt.Sprintf("%s (%d) Len: %d ",
64+
rec.ContentTypeDesc,
65+
rec.ContentType,
66+
rec.Length))
67+
}
68+
}
69+
return sb.String()
1070
}
1171

12-
func (s *TLSMessage) Summary() string {
13-
return fmt.Sprint("TLS Message:")
72+
func (t *TLSMessage) printRecords() string {
73+
var sb strings.Builder
74+
75+
for _, rec := range t.Records {
76+
sb.WriteString(fmt.Sprintf("- %s:\n%s\n", rec.ContentTypeDesc, rec))
77+
}
78+
return sb.String()
1479
}
80+
1581
func (t *TLSMessage) Parse(data []byte) error {
82+
t.Records = make([]*Record, 0, 5)
83+
for len(data) > 0 {
84+
ctype := data[0]
85+
ctdesc := ctdesc(ctype)
86+
if ctdesc == "Unknown" {
87+
break
88+
}
89+
ver := binary.BigEndian.Uint16(data[1:3])
90+
verdesc := verdesc(ver)
91+
if verdesc == "Unknown" {
92+
break
93+
}
94+
rlen := binary.BigEndian.Uint16(data[3:5])
95+
if 5+rlen > uint16(len(data)) {
96+
break
97+
}
98+
r := &Record{
99+
ContentType: ctype,
100+
ContentTypeDesc: ctdesc,
101+
Version: ver,
102+
VersionDesc: verdesc,
103+
Length: rlen,
104+
data: data[5 : 5+rlen],
105+
}
106+
t.Records = append(t.Records, r)
107+
data = data[5+rlen:]
108+
}
109+
t.Data = data
16110
return nil
17111
}
18112

19113
func (t *TLSMessage) NextLayer() (string, []byte) {
20114
return "", nil
21115
}
116+
117+
func ctdesc(ct uint8) string {
118+
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-5
119+
var ctdesc string
120+
switch ct {
121+
case 20:
122+
ctdesc = "Change Cipher Spec"
123+
case 21:
124+
ctdesc = "Alert"
125+
case 22:
126+
ctdesc = "Handshake"
127+
case 23:
128+
ctdesc = "Application Data"
129+
case 24:
130+
ctdesc = "Heartbeat"
131+
case 25:
132+
ctdesc = "tls12_cid"
133+
case 26:
134+
ctdesc = "ACK"
135+
default:
136+
ctdesc = "Unknown"
137+
}
138+
return ctdesc
139+
}
140+
141+
func verdesc(ver uint16) string {
142+
var verdesc string
143+
switch ver {
144+
case 0x0300:
145+
verdesc = "SSL 3.0"
146+
case 0x0301:
147+
verdesc = "TLS 1.0"
148+
case 0x0302:
149+
verdesc = "TLS 1.1"
150+
case 0x0303:
151+
verdesc = "TLS 1.2"
152+
default:
153+
verdesc = "Unknown"
154+
}
155+
return verdesc
156+
}
157+
158+
func hstypedesc(hstype uint8) string {
159+
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7
160+
var hstypedesc string
161+
switch hstype {
162+
case 0:
163+
hstypedesc = "Hello request"
164+
case 1:
165+
hstypedesc = "Client hello"
166+
case 2:
167+
hstypedesc = "Server hello"
168+
case 3:
169+
hstypedesc = "Hello verify request"
170+
case 4:
171+
hstypedesc = "New session ticket"
172+
case 5:
173+
hstypedesc = "End of early data"
174+
case 6:
175+
hstypedesc = "Hello retry request"
176+
case 8:
177+
hstypedesc = "Encrypted extensions"
178+
case 9:
179+
hstypedesc = "Request connection id"
180+
case 10:
181+
hstypedesc = "New connection id"
182+
case 11:
183+
hstypedesc = "Certificate"
184+
case 12:
185+
hstypedesc = "Server key exchange"
186+
case 13:
187+
hstypedesc = "Certificate request"
188+
case 14:
189+
hstypedesc = "Server hello done"
190+
case 15:
191+
hstypedesc = "Certificate verify"
192+
case 16:
193+
hstypedesc = "Client key exchange"
194+
case 17:
195+
hstypedesc = "Client certificate request"
196+
case 20:
197+
hstypedesc = "Finished"
198+
case 21:
199+
hstypedesc = "Certificate url"
200+
case 22:
201+
hstypedesc = "Certificate status"
202+
case 23:
203+
hstypedesc = "Supplemental data"
204+
case 24:
205+
hstypedesc = "Key update"
206+
case 25:
207+
hstypedesc = "Compressed certificate"
208+
case 26:
209+
hstypedesc = "EKT key"
210+
default:
211+
hstypedesc = "Unknown"
212+
}
213+
return hstypedesc
214+
}

mshark.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (mw *Writer) WritePacket(timestamp time.Time, data []byte) error {
8686
mw.printPacket(next, layerNum)
8787
for {
8888
name, data := next.NextLayer()
89-
if name == "" || len(data) == 0 {
89+
if name == "" || data == nil || len(data) == 0 {
9090
return nil
9191
}
9292
next = layers.LayerMap[name]

0 commit comments

Comments
 (0)