- commit
- cc07f5a
- parent
- 3a6c629
- author
- Neale Pickett
- date
- 2020-09-24 20:41:32 -0600 MDT
Add a big pcap file for a new test
2 files changed,
+179,
-0
+179,
-0
1@@ -0,0 +1,179 @@
2+// hk_test is a start at a decoder I was writing, which exhibited some problems.
3+// It also illustrates what a real decoder might look like.
4+
5+package netshovel
6+
7+import (
8+ "fmt"
9+ "io"
10+ "log"
11+ "strings"
12+ "sync"
13+ "testing"
14+
15+ "github.com/google/gopacket"
16+ "github.com/google/gopacket/tcpassembly"
17+)
18+
19+var wg sync.WaitGroup
20+
21+// HKStreamFactory generates HKStreams.
22+type HKStreamFactory struct {
23+ err *error
24+}
25+
26+// New returns a new HKStream.
27+func (f *HKStreamFactory) New(net, transport gopacket.Flow) tcpassembly.Stream {
28+ stream := &HKStream{
29+ Stream: NewStream(net, transport),
30+ err: f.err,
31+ }
32+ wg.Add(1)
33+ go stream.Decode(&wg)
34+
35+ return stream
36+}
37+
38+// HKStream represents half of a TCP Stream.
39+type HKStream struct {
40+ *Stream
41+ err *error
42+}
43+
44+func (stream HKStream) Read(length int) (Utterance, error) {
45+ u, err := stream.Stream.Read(length)
46+ return u, err
47+}
48+
49+// DisplayUtterance prints an unparsed TCP utterance
50+func (stream HKStream) DisplayUtterance(u Utterance) {
51+ fmt.Printf("Unparsed %v:%v → %v:%v\n",
52+ stream.Net.Src().String(), stream.Transport.Src().String(),
53+ stream.Net.Dst().String(), stream.Transport.Dst().String(),
54+ )
55+ fmt.Println(u.Data.Hexdump())
56+}
57+
58+// Display prints as much about an HKPacket as we are able to determine.
59+func (stream HKStream) Display(pkt HKPacket) {
60+ out := new(strings.Builder)
61+
62+ fmt.Fprintf(out, "HK %v:%v → %v:%v\n",
63+ stream.Net.Src().String(), stream.Transport.Src().String(),
64+ stream.Net.Dst().String(), stream.Transport.Dst().String(),
65+ )
66+ out.WriteString(pkt.Describe())
67+ fmt.Println(out.String())
68+}
69+
70+// Decode decodes all data from the stream.
71+func (stream HKStream) Decode(wg *sync.WaitGroup) {
72+ defer wg.Done()
73+ for {
74+ utterance, err := stream.Read(2)
75+ if err == io.EOF {
76+ return
77+ } else if err != nil {
78+ log.Println(err)
79+ return
80+ }
81+
82+ // Was it actually HK?
83+ if utterance.Data.String("DROP") != "HK" {
84+ u, err := stream.Read(-1)
85+ if err != nil {
86+ log.Println(err)
87+ return
88+ }
89+
90+ if utterance.When != u.When {
91+ stream.DisplayUtterance(utterance)
92+ utterance = u
93+ *stream.err = fmt.Errorf("Short length on non-HK packet, and a different utterance was returned")
94+ } else {
95+ utterance.Data = utterance.Data.Append(u.Data)
96+ }
97+ if utterance.Data.Length() < 10 {
98+ *stream.err = fmt.Errorf("Short length on non-HK packet")
99+ return
100+ }
101+ stream.DisplayUtterance(utterance)
102+ continue
103+ }
104+
105+ pkt := NewHKPacket(utterance)
106+ if err := pkt.Decode(stream); err != nil {
107+ log.Println(err)
108+ return
109+ }
110+ stream.Display(pkt)
111+ }
112+}
113+
114+// NewHKPacket returns a shiny new HKPacket.
115+func NewHKPacket(u Utterance) HKPacket {
116+ pkt := HKPacket{
117+ Packet: NewPacket(),
118+ }
119+ pkt.Payload = u.Data
120+ pkt.When = u.When
121+ return pkt
122+}
123+
124+// HKPacket is a single HK packet.
125+type HKPacket struct {
126+ Packet
127+}
128+
129+// Decode from a readable
130+func (pkt *HKPacket) Decode(stream HKStream) error {
131+ header, err := stream.Read(9)
132+ if err != nil {
133+ return err
134+ }
135+ pkt.Payload = header.Data
136+
137+ unknown, _ := pkt.Uint32BE("unknown")
138+ length, _ := pkt.Uint32BE("length")
139+ opcode, _ := pkt.Uint8("opcode")
140+ pkt.Opcode = int(opcode)
141+
142+ if unknown != 0 {
143+ return fmt.Errorf("unknown header was actually %d", unknown)
144+ }
145+ if length > 100 {
146+ return fmt.Errorf("Length too big: %d", length)
147+ }
148+
149+ body, err := stream.Read(int(length - 9 - 2))
150+ if err != nil {
151+ return err
152+ }
153+ pkt.Payload = body.Data
154+
155+ subcode, _ := pkt.Uint8("subcode")
156+ if subcode != 0 {
157+ return fmt.Errorf("Subcode not zero: %d", subcode)
158+ }
159+ pkt.SetString("Payload", pkt.Payload.String("DROP"))
160+
161+ switch pkt.Opcode {
162+ case 7:
163+ pkt.Description = "Keepalive"
164+ }
165+
166+ return nil
167+}
168+
169+func TestHK(t *testing.T) {
170+ factory := HKStreamFactory{err: new(error)}
171+ streamPool := tcpassembly.NewStreamPool(&factory)
172+ assembler := tcpassembly.NewAssembler(streamPool)
173+ ShovelFile("testdata/hk.pcap", assembler)
174+ assembler.FlushAll()
175+ wg.Wait()
176+
177+ if *factory.err != nil {
178+ t.Error(*factory.err)
179+ }
180+}
+0,
-0