func TestPcapLogger(t *testing.T) { ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) pcapLogger := NewPcapLogger("fake-dir", flow) testWriter := NewTestPcapWriter() pcapLogger.fileWriter = testWriter pcapLogger.Start() // test pcap header want := []byte("\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00") if !bytes.Equal(testWriter.lastWrite, want) { t.Errorf("pcap header is wrong") t.Fail() } // test pcap packet rawPacket := makeTestPacket() testWriter.lastWrite = make([]byte, 0) pcapLogger.WritePacket(rawPacket, time.Now()) if !bytes.Equal(testWriter.lastWrite, rawPacket) { t.Errorf("pcap packet is wrong") t.Fail() } pcapLogger.Stop() }
func TestFlowString(t *testing.T) { ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) tcpIpFlow := NewTcpIpFlowFromFlows(ipFlow, tcpFlow) if !strings.EqualFold("1.2.3.4:1-2.3.4.5:2", tcpIpFlow.String()) { t.Error("TcpIpFlow.String() fail") t.Fail() } }
func TestFlows(t *testing.T) { ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) tcpIpFlow := NewTcpIpFlowFromFlows(ipFlow, tcpFlow) ipFlow2, tcpFlow2 := tcpIpFlow.Flows() if ipFlow2 != ipFlow || tcpFlow2 != tcpFlow { t.Error("Flows method fail") t.Fail() } }
func TestGetOverlapRingsWithZeroRings(t *testing.T) { ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SYN: true, SrcPort: 1, DstPort: 2, } tcp.SetNetworkLayerForChecksum(&ip) payload := gopacket.Payload([]byte{1, 2, 3, 4}) p := types.PacketManifest{ IP: ip, TCP: tcp, Payload: payload, } options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) clientFlow := serverFlow.Reverse() conn.serverFlow = serverFlow conn.clientFlow = clientFlow head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing) if head == nil || tail == nil { return } else { t.Fail() } return }
func TestOrderedCoalesceUsedPages(t *testing.T) { maxBufferedPagesTotal := 1024 maxBufferedPagesPerFlow := 1024 streamRing := types.NewRing(40) PageCache := newPageCache() ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) var nextSeq types.Sequence = types.Sequence(1) coalesce := NewOrderedCoalesce(nil, flow, PageCache, streamRing, maxBufferedPagesTotal, maxBufferedPagesPerFlow, false) ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ Seq: 3, SYN: false, SrcPort: 1, DstPort: 2, } p := types.PacketManifest{ Timestamp: time.Now(), Flow: flow, IP: ip, TCP: tcp, Payload: []byte{1, 2, 3, 4, 5, 6, 7}, } coalesce.insert(&p, nextSeq) if coalesce.PageCache.used != 1 { t.Errorf("coalesce.pager.Used() not equal to 1\n") t.Fail() } coalesce.Close() }
func TestNewTcpIpFlowFromPacket(t *testing.T) { buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SYN: true, SrcPort: 1, DstPort: 2, Seq: 123, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3}}, } tcp.SetNetworkLayerForChecksum(&ip) gopacket.SerializeLayers(buf, opts, &ip, &tcp) packetData := buf.Bytes() flow1, err := NewTcpIpFlowFromPacket(packetData) ipFlow2, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow2, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow2 := NewTcpIpFlowFromFlows(ipFlow2, tcpFlow2) if err != nil && !flow2.Equal(flow1) { t.Error("NewTcpIpFlowFromPacket fail") t.Fail() } flow1, err = NewTcpIpFlowFromPacket([]byte{1, 2, 3, 4, 5, 6, 7}) if err == nil || !flow1.Equal(&TcpIpFlow{}) { t.Error("NewTcpIpFlowFromPacket fail") t.Fail() } }
func TestFlowEqual(t *testing.T) { ipFlow1, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow1, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow1 := NewTcpIpFlowFromFlows(ipFlow1, tcpFlow1) ipFlow2, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow2, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow2 := NewTcpIpFlowFromFlows(ipFlow2, tcpFlow2) if !flow1.Equal(flow2) { t.Error("TcpIpFlow.Equal fail") t.Fail() } ipFlow3, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(8, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow3, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow3 := NewTcpIpFlowFromFlows(ipFlow3, tcpFlow3) if flow1.Equal(flow3) { t.Error("TcpIpFlow.Equal fail") t.Fail() } }
func init() { netFlow, _ = gopacket.FlowFromEndpoints( layers.NewIPEndpoint(net.IP{1, 2, 3, 4}), layers.NewIPEndpoint(net.IP{5, 6, 7, 8})) }
func TestTCPHijack(t *testing.T) { attackLogger := NewDummyAttackLogger() options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", DetectHijack: true, } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) conn.AttackLogger = attackLogger ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ Seq: 3, SYN: true, ACK: false, SrcPort: 1, DstPort: 2, } ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) p := types.PacketManifest{ Timestamp: time.Now(), Flow: flow, IP: ip, TCP: tcp, Payload: []byte{}, } tcp.SetNetworkLayerForChecksum(&ip) flowReversed := flow.Reverse() conn.clientFlow = flow conn.serverFlow = flowReversed conn.ReceivePacket(&p) if conn.state != TCP_CONNECTION_REQUEST { t.Error("invalid state transition\n") t.Fail() } // next state transition test ip = layers.IPv4{ SrcIP: net.IP{2, 3, 4, 5}, DstIP: net.IP{1, 2, 3, 4}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 9, SYN: true, ACK: true, Ack: 4, SrcPort: 2, DstPort: 1, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flowReversed, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) if conn.state != TCP_CONNECTION_ESTABLISHED { t.Errorf("invalid state transition: current state %d\n", conn.state) t.Fail() } // test hijack in TCP_CONNECTION_ESTABLISHED state ip = layers.IPv4{ SrcIP: net.IP{2, 3, 4, 5}, DstIP: net.IP{1, 2, 3, 4}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 6699, SYN: true, ACK: true, Ack: 4, SrcPort: 2, DstPort: 1, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flowReversed, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) if attackLogger.Count != 1 { t.Error("hijack detection fail") t.Fail() } // next state transition test ip = layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 4, SYN: false, ACK: true, Ack: 10, SrcPort: 1, DstPort: 2, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flow, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) if conn.state != TCP_DATA_TRANSFER { t.Errorf("invalid state transition; state is %d\n", conn.state) t.Fail() } // test hijack in TCP_DATA_TRANSFER state ip = layers.IPv4{ SrcIP: net.IP{2, 3, 4, 5}, DstIP: net.IP{1, 2, 3, 4}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 7711, SYN: true, ACK: true, Ack: 4, SrcPort: 2, DstPort: 1, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flowReversed, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) if attackLogger.Count != 2 { t.Error("hijack detection fail") t.Fail() } }
func HelperTestThreeWayClose(isClient bool, t *testing.T) { PageCache := newPageCache() var closerState, remoteState *uint8 attackLogger := NewDummyAttackLogger() options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: PageCache, LogDir: "fake-log-dir", } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) conn.AttackLogger = attackLogger conn.state = TCP_DATA_TRANSFER conn.serverNextSeq = 4666 conn.clientNextSeq = 9666 if isClient { closerState = &conn.clientState remoteState = &conn.serverState } else { closerState = &conn.serverState remoteState = &conn.clientState } ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ Seq: 9666, Ack: 4111, FIN: true, SYN: false, ACK: true, SrcPort: 1, DstPort: 2, } flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) p := types.PacketManifest{ Timestamp: time.Now(), Flow: flow, IP: ip, TCP: tcp, Payload: []byte{}, } conn.clientFlow = flow conn.serverFlow = flow.Reverse() conn.ReceivePacket(&p) log.Print("meow1") if conn.state != TCP_CONNECTION_CLOSING { t.Error("connection state must transition to TCP_CONNECTION_CLOSING\n") t.Fail() } if *closerState != TCP_FIN_WAIT1 { t.Error("closer state must be in TCP_FINE_WAIT1\n") t.Fail() } if *remoteState != TCP_CLOSE_WAIT { t.Error("remote state must be in TCP_CLOSE_WAIT\n") t.Fail() } // next state transition ip = layers.IPv4{ SrcIP: net.IP{2, 3, 4, 5}, DstIP: net.IP{1, 2, 3, 4}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 4111, SYN: false, FIN: true, ACK: true, Ack: 9667, SrcPort: 2, DstPort: 1, } flow2 := flow.Reverse() p = types.PacketManifest{ Timestamp: time.Now(), Flow: flow2, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) log.Print("meow2") if conn.state != TCP_CONNECTION_CLOSING { t.Error("connection state must transition to TCP_CONNECTION_CLOSING\n") t.Fail() } // next state transition ip = layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 9667, SYN: false, FIN: false, ACK: true, Ack: 4112, SrcPort: 1, DstPort: 2, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flow, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) log.Print("freeing page cache") }
func TestGetOverlapRings(t *testing.T) { overlapTests := []struct { in reassemblyInput want []*types.Reassembly }{ { reassemblyInput{7, []byte{1, 2}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 5, }, }, }, { reassemblyInput{7, []byte{6, 7}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 5, }, }, }, { reassemblyInput{5, []byte{1, 2, 3, 4, 5}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 5, }, }, }, { reassemblyInput{5, []byte{1, 2, 3, 4, 5, 6}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 10, }, }, }, { reassemblyInput{6, []byte{1, 2, 3, 4, 5}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 10, }, }, }, { reassemblyInput{7, []byte{1, 2, 3, 4, 5}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 10, }, }, }, { reassemblyInput{32, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, []*types.Reassembly{ { Seq: 30, }, { Seq: 35, }, }, }, { reassemblyInput{0, []byte{1, 2, 3}}, []*types.Reassembly{ nil, nil, }, }, { reassemblyInput{0, []byte{1, 2, 3, 4, 5, 6, 7, 8}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 5, }, }, }, { reassemblyInput{0, []byte{1, 2, 3, 4, 5, 6}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 5, }, }, }, { reassemblyInput{0, []byte{1, 2, 3}}, []*types.Reassembly{ nil, nil, }, }, { reassemblyInput{0, []byte{1, 2, 3, 4, 5}}, []*types.Reassembly{ nil, nil, }, }, { reassemblyInput{0, []byte{1, 2, 3, 4, 5, 6}}, []*types.Reassembly{ { Seq: 5, }, { Seq: 5, }, }, }, { reassemblyInput{40, []byte{1}}, []*types.Reassembly{ nil, nil, }, }, { reassemblyInput{42, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, []*types.Reassembly{ nil, nil, }, }, { reassemblyInput{38, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, []*types.Reassembly{ { Seq: 35, }, { Seq: 35, }, }, }, } ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) for j := 5; j < 40; j += 5 { reassembly := types.Reassembly{ Skip: 0, Seq: types.Sequence(j), Bytes: []byte{1, 2, 3, 4, 5}, } conn.ClientStreamRing.Reassembly = &reassembly conn.ClientStreamRing = conn.ClientStreamRing.Next() } for i := 0; i < len(overlapTests); i++ { log.Printf("test # %d", i) tcp := layers.TCP{ Seq: overlapTests[i].in.Seq, SYN: false, SrcPort: 1, DstPort: 2, } p := types.PacketManifest{ IP: ip, TCP: tcp, Payload: overlapTests[i].in.Payload, } ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) clientFlow := serverFlow.Reverse() conn.serverFlow = serverFlow conn.clientFlow = clientFlow head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing) log.Printf("head %v tail %v", head, tail) log.Printf("want %v", overlapTests[i].want[0]) if overlapTests[i].want[0] == nil { log.Print("want nil results") if head != nil { t.Error("getOverlapRings did not return a nil ring segment head\n") t.Fail() } if tail != nil { t.Error("getOverlapRings did not return a nil ring segment tail\n") t.Fail() } } else { if overlapTests[i].want[0] != nil { if head == nil || tail == nil { t.Error("head or tail is nil\n") t.Fail() } } if overlapTests[i].want[0] != nil { if head.Reassembly.Seq.Difference(overlapTests[i].want[0].Seq) != 0 { t.Errorf("test %d: reassembly.Seq %d != want.Seq %d\n", i, head.Reassembly.Seq, overlapTests[i].want[0].Seq) t.Fail() } } if overlapTests[i].want[1] != nil { if tail.Reassembly.Seq.Difference(overlapTests[i].want[1].Seq) != 0 { t.Errorf("test num %d in.Seq %d != want.Seq %d\n", i, head.Reassembly.Seq, overlapTests[i].want[1].Seq) t.Fail() } } } } return }
func TestInjectionDetector(t *testing.T) { log.Print("TestInjectionDetector") attackLogger := NewDummyAttackLogger() options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", AttackLogger: attackLogger, } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) reassembly := types.Reassembly{ Seq: types.Sequence(5), Bytes: []byte{1, 2, 3, 4, 5}, } conn.ClientStreamRing.Reassembly = &reassembly conn.ClientStreamRing = conn.ClientStreamRing.Next() p := types.PacketManifest{ IP: layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, }, TCP: layers.TCP{ Seq: 7, SrcPort: 1, DstPort: 2, }, Payload: []byte{1, 2, 3, 4, 5, 6, 7}, } ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) conn.serverFlow = serverFlow clientFlow := serverFlow.Reverse() conn.clientFlow = clientFlow conn.detectInjection(&p, serverFlow) if attackLogger.Count != 1 { t.Errorf("detectInjection failed; count == %d\n", attackLogger.Count) t.Fail() } // next test case p.TCP = layers.TCP{ Seq: 7, SrcPort: 1, DstPort: 2, } p.Payload = []byte{3, 4, 5} conn.detectInjection(&p, serverFlow) if attackLogger.Count == 0 { t.Error("failed to detect injection\n") t.Fail() } // next test case attackLogger.Count = 0 p.TCP = layers.TCP{ Seq: 1, SrcPort: 1, DstPort: 2, } p.Payload = []byte{1, 2, 3, 4, 5, 6} conn.detectInjection(&p, serverFlow) if attackLogger.Count == 0 { t.Error("failed to detect injection\n") t.Fail() } // next test case attackLogger.Count = 0 p.TCP = layers.TCP{ Seq: 1, SrcPort: 1, DstPort: 2, } p.Payload = []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17} conn.detectInjection(&p, serverFlow) if attackLogger.Count != 1 { t.Error("injection detection failure\n") t.Fail() } }
func TestGetOverlapBytes(t *testing.T) { overlapBytesTests := []struct { in reassemblyInput want TestOverlapBytesWant }{ { //0 reassemblyInput{3, []byte{2, 3, 4}}, TestOverlapBytesWant{ bytes: []byte{6}, startOffset: 2, endOffset: 3, }, }, { //1 reassemblyInput{4, []byte{2, 3, 4}}, TestOverlapBytesWant{ bytes: []byte{6, 7}, startOffset: 1, endOffset: 3, }, }, { //2 reassemblyInput{5, []byte{2, 3, 4}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8}, startOffset: 0, endOffset: 3, }, }, { //3 reassemblyInput{6, []byte{1, 2, 3}}, TestOverlapBytesWant{ bytes: []byte{7, 8, 9}, startOffset: 0, endOffset: 3, }, }, { //4 reassemblyInput{4, []byte{91, 92, 93, 94, 95, 96, 97}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11}, startOffset: 1, endOffset: 7, }, }, { reassemblyInput{4, []byte{91, 92, 93, 94, 95, 96, 97, 98}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11, 12}, startOffset: 1, endOffset: 8, }, }, { reassemblyInput{4, []byte{91, 92, 93, 94, 95, 96, 97, 98, 99}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11, 12, 13}, startOffset: 1, endOffset: 9, }, }, { reassemblyInput{3, []byte{1, 2, 3, 4, 5, 6, 7}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10}, startOffset: 2, endOffset: 7, }, }, { reassemblyInput{34, []byte{1, 2, 3, 4, 5, 6, 7}}, TestOverlapBytesWant{ bytes: []byte{35, 36, 37, 38, 39, 40}, startOffset: 0, endOffset: 6, }, }, { reassemblyInput{34, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, TestOverlapBytesWant{ bytes: []byte{35, 36, 37, 38, 39, 40}, startOffset: 0, endOffset: 6, }, }, { reassemblyInput{5, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, startOffset: 0, endOffset: 35, }, }, { reassemblyInput{5, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, startOffset: 0, endOffset: 35, }, }, { reassemblyInput{5, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, startOffset: 0, endOffset: 35, }, }, { reassemblyInput{4, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, startOffset: 1, endOffset: 36, }, }, { reassemblyInput{3, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, startOffset: 2, endOffset: 37, }, }, { reassemblyInput{4, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, TestOverlapBytesWant{ bytes: []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, startOffset: 1, endOffset: 36, }, }, } options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) for j := 5; j < 40; j += 5 { reassembly := types.Reassembly{ Seq: types.Sequence(j), Bytes: []byte{byte(j + 1), byte(j + 2), byte(j + 3), byte(j + 4), byte(j + 5)}, } conn.ClientStreamRing.Reassembly = &reassembly conn.ClientStreamRing = conn.ClientStreamRing.Next() } for i := 0; i < len(overlapBytesTests); i++ { var startSeq uint32 = overlapBytesTests[i].in.Seq start := types.Sequence(startSeq) end := start.Add(len(overlapBytesTests[i].in.Payload) - 1) p := types.PacketManifest{ IP: layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, }, TCP: layers.TCP{ Seq: startSeq, SrcPort: 1, DstPort: 2, }, Payload: overlapBytesTests[i].in.Payload, } ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) clientFlow := serverFlow.Reverse() conn.serverFlow = serverFlow conn.clientFlow = clientFlow head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing) if head == nil || tail == nil { t.Errorf("%d getOverlapRings returned a nil\n", i) t.Fail() continue } log.Printf("test #%d", i) overlapBytes, startOffset, endOffset := getOverlapBytes(head, tail, start, end) if startOffset != overlapBytesTests[i].want.startOffset { t.Errorf("test %d startOffset %d does not match want.startOffset %d\n", i, startOffset, overlapBytesTests[i].want.startOffset) t.Fail() } if endOffset != overlapBytesTests[i].want.endOffset { t.Errorf("test %d endOffset %d does not match want.endOffset %d\n", i, endOffset, overlapBytesTests[i].want.endOffset) t.Fail() } if len(overlapBytes) != len(overlapBytesTests[i].want.bytes) { t.Errorf("test %d overlapBytes len %d not equal to want.bytes len %d\n", i, len(overlapBytes), len(overlapBytesTests[i].want.bytes)) t.Fail() } if !bytes.Equal(overlapBytes, overlapBytesTests[i].want.bytes) { t.Errorf("test %d overlapBytes %x not equal to want.bytes %x\n", i, overlapBytes, overlapBytesTests[i].want.bytes) t.Fail() } } }
func TestGetRingSlice(t *testing.T) { options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) for j := 5; j < 40; j += 5 { reassembly := types.Reassembly{ Seq: types.Sequence(j), Bytes: []byte{1, 2, 3, 4, 5}, } conn.ClientStreamRing.Reassembly = &reassembly conn.ClientStreamRing = conn.ClientStreamRing.Next() } var startSeq uint32 = 5 p := types.PacketManifest{ IP: layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, }, TCP: layers.TCP{ Seq: startSeq, SrcPort: 1, DstPort: 2, }, Payload: []byte{1, 2, 3, 4, 5, 6, 7}, } ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) clientFlow := serverFlow.Reverse() conn.serverFlow = serverFlow conn.clientFlow = clientFlow head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing) if head == nil { t.Fatal() } if tail == nil { t.Fatal() } ringSlice := getRingSlice(head, tail, 0, 1) if !bytes.Equal(ringSlice, []byte{1, 2, 3, 4, 5, 1}) { t.Error("byte comparison failed") t.Fail() } ringSlice = getRingSlice(head, tail, 0, 3) if !bytes.Equal(ringSlice, []byte{1, 2, 3, 4, 5, 1, 2, 3}) { t.Error("byte comparison failed") t.Fail() } ringSlice = getRingSlice(head, tail, 0, 1) if !bytes.Equal(ringSlice, []byte{1, 2, 3, 4, 5, 1}) { t.Error("byte comparison failed") t.Fail() } ringSlice = getRingSlice(head, tail, 1, 0) if !bytes.Equal(ringSlice, []byte{2, 3, 4, 5}) { t.Error("byte comparison failed") t.Fail() } ringSlice = getRingSlice(head, tail, 1, 1) if !bytes.Equal(ringSlice, []byte{2, 3, 4, 5, 1}) { t.Error("byte comparison failed") t.Fail() } ringSlice = getRingSlice(head, tail, 2, 0) if !bytes.Equal(ringSlice, []byte{3, 4, 5}) { t.Error("byte comparison failed") t.Fail() } ringSlice = getRingSlice(head, tail, 2, 3) if !bytes.Equal(ringSlice, []byte{3, 4, 5, 1, 2, 3}) { t.Error("byte comparison failed") t.Fail() } startSeq = 1 p = types.PacketManifest{ IP: layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, }, TCP: layers.TCP{ Seq: startSeq, SrcPort: 1, DstPort: 2, }, Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, } head, tail = getOverlapRings(&p, serverFlow, conn.ClientStreamRing) log.Printf("sequence of head %d", head.Reassembly.Seq) log.Printf("and tail %d", tail.Reassembly.Seq) ringSlice = getRingSlice(head, tail, 0, 2) if !bytes.Equal(ringSlice, []byte{1, 2, 3, 4, 5, 1, 2}) { t.Errorf("ringSlice is %x\n", ringSlice) t.Fail() } ringSlice = getRingSlice(head, tail, 2, 4) if !bytes.Equal(ringSlice, []byte{3, 4, 5, 1, 2, 3, 4}) { t.Errorf("ringSlice is %x\n", ringSlice) //XXX t.Fail() } }